def main():
    MIN_NUM_RAW = 3
    TEXT_SIZE = 13

    RKN_data = getRKN()  # get RKN data

    # remove the string descriptions and create numpy arrays
    RKN_start_UT = np.asarray(RKN_data[0]) if RKN_data[0].pop(
        0) == "start" else print("Error: RKN start time data")
    # RKN_end_UT = np.asarray(RKN_data[1]) if RKN_data[1].pop(0) == "end" else print("Error getting end time data")
    RKN_gate = np.asarray(RKN_data[2]) if RKN_data[2].pop(
        0) == "gate" else print("Error: RKN gate data")
    RKN_n10 = np.asarray(RKN_data[3]) if RKN_data[3].pop(
        0) == "n10" else print("Error: RKN number of 10 MHz points")
    RKN_med_vel10 = np.asarray(RKN_data[4]) if RKN_data[4].pop(
        0) == "med_vel10" else print("Error: RKN 10MHz vel data")
    RKN_std_vel10 = np.asarray(RKN_data[5]) if RKN_data[5].pop(
        0) == "std_vel10" else print("Error: RKN std_vel_10")
    RKN_n12 = np.asarray(RKN_data[6]) if RKN_data[6].pop(
        0) == "n12" else print("Error: RKN number of 12 MHz points")
    RKN_med_vel12 = np.asarray(RKN_data[7]) if RKN_data[7].pop(
        0) == "med_vel12" else print("Error: RKN 12MHz vel data")
    RKN_std_vel12 = np.asarray(RKN_data[8]) if RKN_data[8].pop(
        0) == "stddev_vel12" else print("Error: RKN std_vel_12")

    # Restrict to a specific time period (19.10-19.19)
    valid_times_RKN = RKN_start_UT == 19.10  # Get the bool array of all elements with start time 19.10
    _RKN_gate = RKN_gate[valid_times_RKN]
    _RKN_vel10 = RKN_med_vel10[valid_times_RKN]
    _RKN_vel12 = RKN_med_vel12[valid_times_RKN]
    _RKN_n10 = RKN_n10[valid_times_RKN]
    _RKN_n12 = RKN_n12[valid_times_RKN]
    _RKN_std_vel10 = RKN_std_vel10[valid_times_RKN]
    _RKN_std_vel12 = RKN_std_vel12[valid_times_RKN]

    # Restrict to range gates <30
    valid_gates_RKN = _RKN_gate <= 30  # Get the bool array of all elements with gates <30
    __RKN_gate = _RKN_gate[valid_gates_RKN]
    __RKN_vel10 = _RKN_vel10[valid_gates_RKN]
    __RKN_vel12 = _RKN_vel12[valid_gates_RKN]
    __RKN_n10 = _RKN_n10[valid_gates_RKN]
    __RKN_n12 = _RKN_n12[valid_gates_RKN]
    __RKN_std_vel10 = _RKN_std_vel10[valid_gates_RKN]
    __RKN_std_vel12 = _RKN_std_vel12[valid_gates_RKN]

    # remove velocity points where there are less than MIN_NUM_RAW data points used in calculation of the mean
    for i in range(len(__RKN_vel10)):
        if __RKN_n10[i] < MIN_NUM_RAW:
            __RKN_vel10[i] = math.nan
        if __RKN_n12[i] < MIN_NUM_RAW:
            __RKN_n12[i] = math.nan

    # Plot velocities as a function of range gate
    plt.rc('font', size=TEXT_SIZE)

    # plot RKN data
    plt.plot(__RKN_gate - 0.1,
             __RKN_vel10,
             'rd',
             label='10.4 MHz',
             markersize=5)
    plt.plot(__RKN_gate + 0.1,
             __RKN_vel12,
             'bd',
             label='12.3 MHz',
             markersize=5)

    # plot error in RKN data
    for i in range(len(__RKN_vel10)):
        if not math.isnan(__RKN_n10[i]):
            plt.plot([__RKN_gate[i] - 0.1, __RKN_gate[i] - 0.1], [
                __RKN_vel10[i] + __RKN_std_vel10[i],
                __RKN_vel10[i] - __RKN_std_vel10[i]
            ],
                     'r-',
                     linewidth=0.5)
    for i in range(len(__RKN_vel12)):
        if not math.isnan(__RKN_n12[i]):
            plt.plot([__RKN_gate[i] + 0.1, __RKN_gate[i] + 0.1], [
                __RKN_vel12[i] + __RKN_std_vel12[i],
                __RKN_vel12[i] - __RKN_std_vel12[i]
            ],
                     'b-',
                     linewidth=0.5)

    RISR_data = getRISR()  # get RISR_HDF5 data

    RISR_start_UT = np.asarray(RISR_data[0]) if RISR_data[0].pop(0) == "START_UT" else \
        print("Error: RISR_HDF5 start time data")
    # RISR_end_UT = np.asarray(RISR_data[1]) if RISR_data[1].pop(0) == "END_UT" else \
    #     print("Error: RISR_HDF5 end time data")
    RISR_geolat = np.asarray(RISR_data[2]) if RISR_data[2].pop(0) == "LATITUDE" else \
        print("Error: RISR_HDF5 geolat data")
    RISR_vel = np.asarray(RISR_data[3]) if RISR_data[3].pop(0) == "VEL" else \
        print("Error: RISR_HDF5 velocity data")
    RISR_dvel = np.asarray(RISR_data[4]) if RISR_data[4].pop(0) == "D_VEL" else \
        print("Error: RISR_HDF5 velocity data")

    # Restrict to a specific time period (19.10-19.19)
    valid_times_RISR = RISR_start_UT == 19.10  # Get the bool array of all elements with start time 19.10
    _RISR_geolat = RISR_geolat[valid_times_RISR]
    _RISR_vel = RISR_vel[valid_times_RISR]
    _RISR_dvel = RISR_dvel[valid_times_RISR]

    _RISR_gate = glatToGate(_RISR_geolat)  # convert geolat to gate

    # since we are connecting with a line we have to remove all NaN values so there are no breaks in the line
    not_nan = []
    for i in range(len(_RISR_vel)):
        if math.isnan(_RISR_vel[i]):
            not_nan.append(False)
        else:
            not_nan.append(True)

    __RISR_gate = _RISR_gate[not_nan]
    __RISR_vel = _RISR_vel[not_nan]
    __RISR_dvel = _RISR_dvel[not_nan]

    # plot the data
    plt.plot(__RISR_gate, __RISR_vel, 'k2', label='RISR_HDF5', markersize=6)
    plt.plot(__RISR_gate, __RISR_vel, 'k-', linewidth=0.7)

    # Plot error
    for i in range(len(__RISR_gate)):
        plt.plot([_RISR_gate[i], _RISR_gate[i]],
                 [_RISR_vel[i] + _RISR_dvel[i], _RISR_vel[i] - _RISR_dvel[i]],
                 'k-',
                 linewidth=0.5)

    # fix up plot and show
    plt.plot([-1, 31], [0, 0], 'k-', linewidth='0.6')
    plt.xlabel('Range Gate')
    plt.ylabel('Velocity [m/s]')
    plt.title('Velocity Range Profile')
    plt.axis([-0.5, max(__RKN_gate) + 0.5, -1250, 500])
    plt.legend(loc='upper right')
    plt.grid(axis='y', linestyle='--')
    plt.show()
Пример #2
0
def VelScatCompWFitting():
    """
    Purpose:
        Plot a velocity scatter comparison of RKN 12 MHz and RISR_HDF5 velocities.
        Bin and fit linear, quadratic, rational and logarithmic functions among points that fit certain
        arbitrary criteria.
    Pre-conditions:
        Data files and the programs to read in these files must exist
    Post-conditions:
        Creates a plot of RKN 12 MHz velocity as a function of RISR_HDF5 velocity
        Optionally create an out file with the plot
    Return:
        none
    """

    SAVE_PLOTS = False  # Save the plot in the Processed data folder
    START_UT = 19.0
    END_UT = 20.5
    MIN_NUM_RAW = 3  # minimum number of data points required for a RKN median to be plotted
    TEXT_SIZE = 15  # size of text in plot
    FIG_SIZE = (12, 6)  # size of the PNG figure created
    PLT_RANGE = [-1200, 400, -1200, 400]  # plot range [xmin, xmax, ymin, ymax]
    OUT_FILE_NAME = "06032016_VelScatCompWFitting_" + str(START_UT) + "-" + str(END_UT) + "UT"

# < -- GET RKN DATA -- >

    RKN_data = getRKN()  # get RKN data
    # remove the string descriptions and create numpy arrays
    RKN_start_UT = np.asarray(RKN_data[0]) if RKN_data[0].pop(0) == "start" else print("Error: RKN start time data")
    RKN_end_UT = np.asarray(RKN_data[1]) if RKN_data[1].pop(0) == "end" else print("Error getting end time data")
    RKN_gate = np.asarray(RKN_data[2]) if RKN_data[2].pop(0) == "gate" else print("Error: RKN gate data")
    RKN_n10 = np.asarray(RKN_data[3]) if RKN_data[3].pop(0) == "n10" else print("Error: RKN number of 10 MHz points")
    RKN_med_vel10 = np.asarray(RKN_data[4]) if RKN_data[4].pop(0) == "med_vel10" else print("Error: RKN 10MHz vel data")
    RKN_n12 = np.asarray(RKN_data[6]) if RKN_data[6].pop(0) == "n12" else print("Error: RKN number of 12 MHz points")
    RKN_med_vel12 = np.asarray(RKN_data[7]) if RKN_data[7].pop(0) == "med_vel12" else print("Error: RKN 12MHz vel data")

    # Restrict to a specific time period
    valid_times_RKN = (RKN_start_UT >= START_UT) & (RKN_end_UT <= END_UT)
    _RKN_start_UT = RKN_start_UT[valid_times_RKN]
    _RKN_gate = RKN_gate[valid_times_RKN]
    _RKN_vel10 = RKN_med_vel10[valid_times_RKN]
    _RKN_vel12 = RKN_med_vel12[valid_times_RKN]
    _RKN_n10 = RKN_n10[valid_times_RKN]
    _RKN_n12 = RKN_n12[valid_times_RKN]

    # remove velocity points where there are less than MIN_NUM_RAW data points used in calculation of the mean
    for i in range(len(_RKN_vel10)):
        if _RKN_n10[i] < MIN_NUM_RAW:
            _RKN_vel10[i] = math.nan
        if _RKN_n12[i] < MIN_NUM_RAW:
            _RKN_vel12[i] = math.nan

# < -- GET RISR_HDF5 DATA -- >

    RISR_data = getRISR()  # get RISR_HDF5 data
    RISR_start_UT = np.asarray(RISR_data[0]) if RISR_data[0].pop(0) == "START_UT" else \
        print("Error: RISR_HDF5 start time data")
    RISR_end_UT = np.asarray(RISR_data[1]) if RISR_data[1].pop(0) == "END_UT" else \
        print("Error: RISR_HDF5 end time data")
    RISR_geolat = np.asarray(RISR_data[2]) if RISR_data[2].pop(0) == "LATITUDE" else \
        print("Error: RISR_HDF5 geolat data")
    RISR_vel = np.asarray(RISR_data[3]) if RISR_data[3].pop(0) == "VEL" else \
        print("Error: RISR_HDF5 velocity data")

    # Restrict RISR_HDF5 data to a specific time period (START_UT-END_UT)
    valid_times_RISR = (RISR_start_UT >= START_UT) & (RISR_end_UT <= END_UT) & (RISR_start_UT < RISR_end_UT)
    _RISR_start_UT = RISR_start_UT[valid_times_RISR]
    _RISR_geolat = RISR_geolat[valid_times_RISR]
    _RISR_vel = RISR_vel[valid_times_RISR]

    _RISR_gate = glatToGate(_RISR_geolat)  # convert geolat to gate

# < -- MATCH UP RKN AND RISR_HDF5 DATA -- >

    # Remove all RKN data that is not within the RISR_HDF5 gate range
    valid_gates_RKN = (_RKN_gate >= math.floor(min(_RISR_gate))) & (_RKN_gate <= math.ceil(max(_RISR_gate)))
    __RKN_start_UT = _RKN_start_UT[valid_gates_RKN]
    __RKN_gate = _RKN_gate[valid_gates_RKN]
    __RKN_vel10 = _RKN_vel10[valid_gates_RKN]
    __RKN_vel12 = _RKN_vel12[valid_gates_RKN]

    # Round all RISR_HDF5 gate data to whole numbers so they can be easily picked out and
    # compared with the corresponding RKN gate
    _RISR_gate_rounded = np.around(_RISR_gate)

    new_RISR_vel = np.zeros(len(__RKN_gate))  # pre-allocate
    # Loop through the RKN data and make points by averaging the corresponding RISR_HDF5 data
    for i in range(len(__RKN_gate)):
        RISR_idexs_that_match = (_RISR_gate_rounded == __RKN_gate[i]) & (_RISR_start_UT == __RKN_start_UT[i])
        new_RISR_vel[i] = mean(_RISR_vel[RISR_idexs_that_match])  # between 1 and 3 points will be averaged

# < -- PLOT THE DATA -->

    # Plot RKN velocities as a function of RISR_HDF5 velocities (RISR_HDF5 velocities should be representative of ExB)
    myPlot = plt.figure(figsize=FIG_SIZE)
    plt.rc('font', size=TEXT_SIZE)
    plt.plot([PLT_RANGE[0], PLT_RANGE[1]], [PLT_RANGE[0], PLT_RANGE[1]], 'k-', linewidth='0.6')  # bisector
    plt.plot([PLT_RANGE[0], PLT_RANGE[1]], [0, 0], 'k-', linewidth='0.6')
    plt.plot([0, 0], [PLT_RANGE[2], PLT_RANGE[3]], 'k-', linewidth='0.6')
    plt.xlabel('Velocity (RISR_HDF5) [m/s]')
    plt.ylabel('12 MHz Velocity (RKN) [m/s]')
    plt.title('6 March 2016, ' + str(int(START_UT)) + ':' + str(int((START_UT * 60) % 60)).zfill(2) + '-'
              + str(int(END_UT)) + ':' + str(int((END_UT * 60) % 60)).zfill(2) + 'UT')
    plt.axis(PLT_RANGE)
    plt.grid(linestyle='--')
    ax = plt.gca()
    ax.tick_params(axis='x', rotation=30)
    ax.set_xticks([400, 200, 0, -200, -400, -600, -800, -1000, -1200])

    # We have to remove all NaN values to make it easier down the line
    not_nan = []
    for i in range(len(__RKN_vel12)):
        if math.isnan(new_RISR_vel[i]) or math.isnan(__RKN_vel12[i]):
            not_nan.append(False)
        else:
            not_nan.append(True)

    new_RISR_vel = new_RISR_vel[not_nan]
    __RKN_vel12 = __RKN_vel12[not_nan]
    # __RKN_vel10 = __RKN_vel10[not_nan]

    # plot the data
    # plt.scatter(new_RISR_vel, __RKN_vel10, s=40, facecolors='none', edgecolors='r', label='10.4 MHz', linewidths=1.5)
    plt.scatter(new_RISR_vel, __RKN_vel12, c='blue', marker="o", label='All 12 MHz pts', s=1)

# < -- FIT SOME OF THE DATA -- >

    # Restrict based on what is currently arbitrary criteria
    # - both have to be of the same sign
    # - points have to be 20% above the bisector
    ForFit = (((__RKN_vel12 < 0) & (new_RISR_vel < 0)) | ((__RKN_vel12 > 0) & (new_RISR_vel > 0))) & \
             (1.3 * __RKN_vel12 > new_RISR_vel)

    ForFit_RKN = __RKN_vel12[ForFit]
    ForFit_RISR = new_RISR_vel[ForFit]
    plt.scatter(ForFit_RISR, ForFit_RKN, s=20, marker="+", c='blue', label='Pts considered', linewidths=0.3)

    # Run binning
    x, y = x_binner(ForFit_RISR, ForFit_RKN, 200, PLT_RANGE[0])
    plt.plot(x, y, c='black', marker='s', label='Binned points', markersize=7)

    # Run rational fit on raw data (y=A+B/x)
    fit = np.polyfit(1 / ForFit_RISR, ForFit_RKN, 1)
    dummy_x = np.arange(PLT_RANGE[0], 0, 1)
    plt.plot(dummy_x, fit[0] / dummy_x + fit[1], label='Rational fit to raw points \ny = '
             + str(round(fit[0], 2)) + '/x ' + str(round(fit[1], 2)), c='m')

    # Run rational fit on the results from binnning (y=A+B/x)
    fit = np.polyfit(1 / x, y, 1)
    plt.plot(dummy_x, fit[0] / dummy_x + fit[1], label='Rational fit to binned results \ny = '
             + str(round(fit[0], 2)) + '/x ' + str(round(fit[1], 2)), c='r')

    # Run quadratic fit on raw data (y=A+Bx+Cx^2)
    fit = np.polyfit(ForFit_RISR, ForFit_RKN, 2)
    plt.plot(dummy_x, fit[0]*np.power(dummy_x, 2) + fit[1]*dummy_x + fit[2],
             label='Quadratic fit to raw points \ny = '
             + str(round(fit[0], 6)) + 'x^2 + ' + str(round(fit[1], 2)) + 'x +' + str(round(fit[2], 2)), c='g')

    # Run quadratic fit on binned data (y=A+Bx+Cx^2)
    fit = np.polyfit(x, y, 2)
    plt.plot(dummy_x, fit[0] * np.power(dummy_x, 2) + fit[1] * dummy_x + fit[2],
             label='Quadratic fit to binned points \ny = '
                   + str(round(fit[0], 6)) + 'x^2 + ' + str(round(fit[1], 2)) + 'x +' + str(round(fit[2], 2)),
                   c='coral')

    # # Run logarithmic fit (y = A + B log(x))
    # fit = np.polyfit(np.log(np.negative(ForFit_RISR)), ForFit_RKN, 1)
    # dummy_x = np.arange(PLT_RANGE[0], 0, 1)
    # plt.plot(dummy_x, fit[0] * np.log(np.negative(dummy_x)) + fit[1], label='Logarithmic fit', c='gold')

    # # Run y = a + bx^2 fit - doesn't do a good job because you need the linear term
    # dummy_y = np.arange(PLT_RANGE[0], 0, 1)
    # fit_coeffs = np.polyfit(np.power(ForFit_RKN, 2), ForFit_RISR, 1)
    # plt.plot(fit_coeffs[0] * np.power(dummy_y, 2) + fit_coeffs[1], dummy_y, label='y = a + bx^2', c='gold')

    plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))
    plt.show()

    if SAVE_PLOTS:
        cur_path = os.path.dirname(__file__)  # where we are
        myPlot.savefig(cur_path + '/Processed_data/' + OUT_FILE_NAME + '.eps', format='eps', bbox_inches='tight')
        myPlot.savefig(cur_path + '/Processed_data/' + OUT_FILE_NAME + '.svg', format='svg', dpi=1200)
def VelocityScatterComparison():
    """
    Purpose:
        Program to plot a scatter plot comparing RKN 10 MHz and RKN 12 MHz velocities to RISR_HDF5 velocities
    Pre-conditions:
        Data files and the programs to read in these files must exist
    Post-conditions:
        Velocity comparison plot is created
        If SAVE_PLOTS then the plot will be saved in the processed data folder
    Return:
        :return: ax: Plot axes
    """

    SAVE_PLOTS = False  # Save the plot in the Processed data folder
    START_UT = 19.0
    END_UT = 20.5
    MIN_NUM_RAW = 3  # minimum number of data points required for a RKN median to be plotted
    TEXT_SIZE = 19  # size of text in plot
    FIG_SIZE = (8, 7)  # size of the PNG figure created
    PLT_RANGE = [-1400, 400, -1200, 400]  # plot range [xmin, xmax, ymin, ymax]
    OUT_FILE_NAME = "06032016_Velocity_Comparison_" + str(
        START_UT) + "-" + str(END_UT) + "UT"

    RKN_data = getRKN()  # get RKN data
    # remove the string descriptions and create numpy arrays
    RKN_start_UT = np.asarray(RKN_data[0]) if RKN_data[0].pop(
        0) == "start" else print("Error: RKN start time data")
    RKN_end_UT = np.asarray(RKN_data[1]) if RKN_data[1].pop(
        0) == "end" else print("Error getting end time data")
    RKN_gate = np.asarray(RKN_data[2]) if RKN_data[2].pop(
        0) == "gate" else print("Error: RKN gate data")
    RKN_n10 = np.asarray(RKN_data[3]) if RKN_data[3].pop(
        0) == "n10" else print("Error: RKN number of 10 MHz points")
    RKN_med_vel10 = np.asarray(RKN_data[4]) if RKN_data[4].pop(
        0) == "med_vel10" else print("Error: RKN 10MHz vel data")
    # RKN_std_vel10 = np.asarray(RKN_data[5]) if RKN_data[5].pop(0) == "std_vel10" else print("Error: RKN std_vel_10")
    RKN_n12 = np.asarray(RKN_data[6]) if RKN_data[6].pop(
        0) == "n12" else print("Error: RKN number of 12 MHz points")
    RKN_med_vel12 = np.asarray(RKN_data[7]) if RKN_data[7].pop(
        0) == "med_vel12" else print("Error: RKN 12MHz vel data")
    # RKN_std_vel12 = np.asarray(RKN_data[8]) if RKN_data[8].pop(0) == "stddev_vel12" else print("Err: RKN std_vel_12")

    # Restrict to a specific time period
    valid_times_RKN = (RKN_start_UT >= START_UT) & (RKN_end_UT <= END_UT)
    _RKN_start_UT = RKN_start_UT[valid_times_RKN]
    _RKN_gate = RKN_gate[valid_times_RKN]
    _RKN_vel10 = RKN_med_vel10[valid_times_RKN]
    _RKN_vel12 = RKN_med_vel12[valid_times_RKN]
    _RKN_n10 = RKN_n10[valid_times_RKN]
    _RKN_n12 = RKN_n12[valid_times_RKN]

    # remove velocity points where there are less than MIN_NUM_RAW data points used in calculation of the median
    for i in range(len(_RKN_vel10)):
        if _RKN_n10[i] < MIN_NUM_RAW:
            _RKN_vel10[i] = math.nan
        if _RKN_n12[i] < MIN_NUM_RAW:
            _RKN_vel12[i] = math.nan

    RISR_data = getRISR()  # get RISR_HDF5 data

    RISR_start_UT = np.asarray(RISR_data[0]) if RISR_data[0].pop(0) == "START_UT" else \
        print("Error: RISR_HDF5 start time data")
    RISR_end_UT = np.asarray(RISR_data[1]) if RISR_data[1].pop(0) == "END_UT" else \
        print("Error: RISR_HDF5 end time data")
    RISR_geolat = np.asarray(RISR_data[2]) if RISR_data[2].pop(0) == "LATITUDE" else \
        print("Error: RISR_HDF5 geolat data")
    RISR_vel = np.asarray(RISR_data[3]) if RISR_data[3].pop(0) == "VEL" else \
        print("Error: RISR_HDF5 velocity data")
    # RISR_dvel = np.asarray(RISR_data[4]) if RISR_data[4].pop(0) == "D_VEL" else \
    #     print("Error: RISR_HDF5 velocity data")

    # Restrict RISR_HDF5 data to a specific time period (START_UT-END_UT)
    valid_times_RISR = (RISR_start_UT >= START_UT) & (
        RISR_end_UT <= END_UT) & (RISR_start_UT < RISR_end_UT)
    _RISR_start_UT = RISR_start_UT[valid_times_RISR]
    _RISR_geolat = RISR_geolat[valid_times_RISR]
    _RISR_vel = RISR_vel[valid_times_RISR]

    _RISR_gate = glatToGate(_RISR_geolat)  # convert geolat to gate

    # Remove all RKN data that is not within the RISR_HDF5 gate range
    valid_gates_RKN = (_RKN_gate >= math.floor(
        min(_RISR_gate))) & (_RKN_gate <= math.ceil(max(_RISR_gate)))
    __RKN_start_UT = _RKN_start_UT[valid_gates_RKN]
    __RKN_gate = _RKN_gate[valid_gates_RKN]
    __RKN_vel10 = _RKN_vel10[valid_gates_RKN]
    __RKN_vel12 = _RKN_vel12[valid_gates_RKN]

    # Round all RISR_HDF5 gate data to whole numbers so they can be easily picked out and
    # compared with the corresponding RKN gate
    _RISR_gate_rounded = np.around(
        _RISR_gate)  # includes gates 9 through 22 (14 gates)

    new_RISR_vel = np.zeros(len(__RKN_gate))  # pre-allocate
    # Loop through the RKN data and make points by averaging the corresponding RISR_HDF5 data
    for i in range(len(__RKN_gate)):
        RISR_idexs_that_match = (_RISR_gate_rounded == __RKN_gate[i]) & (
            _RISR_start_UT == __RKN_start_UT[i])
        new_RISR_vel[i] = mean(_RISR_vel[RISR_idexs_that_match]
                               )  # between 1 and 3 points will be averaged

    # Plot RKN velocities as a function of RISR_HDF5 velocities (RISR_HDF5 velocities should be representative of ExB)
    # Set up plot
    myPlot = plt.figure(figsize=FIG_SIZE)
    plt.rc('font', size=TEXT_SIZE)
    plt.plot([PLT_RANGE[0], PLT_RANGE[1]], [PLT_RANGE[0], PLT_RANGE[1]],
             'k-',
             linewidth='0.6')  # bisector
    plt.plot([PLT_RANGE[0], PLT_RANGE[1]], [0, 0], 'k-', linewidth='0.6')
    plt.plot([0, 0], [PLT_RANGE[2], PLT_RANGE[3]], 'k-', linewidth='0.6')
    plt.xlabel('Velocity (RISR_HDF5) [m/s]')
    plt.ylabel('Velocity (RKN) [m/s]')
    plt.title('6 March 2016, ' + str(int(START_UT)) + ':' +
              str(int((START_UT * 60) % 60)).zfill(2) + '-' +
              str(int(END_UT)) + ':' + str(int((END_UT * 60) % 60)).zfill(2) +
              ' UT')
    plt.axis(PLT_RANGE)
    plt.grid(linestyle='--')
    ax = plt.gca()
    ax.tick_params(axis='x', rotation=30)
    ax.set_xticks([400, 200, 0, -200, -400, -600, -800, -1000, -1200, -1400])

    # Multiply RISR_HDF5 velocities by 1.2, idk why?
    new_RISR_vel = 1.2 * new_RISR_vel

    # plot the data
    plt.scatter(new_RISR_vel,
                __RKN_vel10,
                s=40,
                facecolors='none',
                edgecolors='r',
                label='10.4 MHz',
                linewidths=1.5)
    plt.scatter(new_RISR_vel,
                __RKN_vel12,
                s=40,
                facecolors='none',
                edgecolors='b',
                label='12.3 MHz',
                linewidths=1.5)

    # Count the number of non-nan data points
    count_10 = 0
    count_12 = 0
    for i in range(len(__RKN_vel10)):
        if not np.isnan(__RKN_vel10[i]):
            count_10 = count_10 + 1
    for i in range(len(__RKN_vel12)):
        if not np.isnan(__RKN_vel12[i]):
            count_12 = count_12 + 1

    print("Count 10 = " + str(count_10))
    print("Count 12 = " + str(count_12))

    # Calculate Cs versus ExB drift curves acording to previous study
    # Fit_99 = 309.0 + 0.0000448 * drift^2
    # Fit_102 = 319.0 + 0.0000674 * drift^2

    # nielsen = 300. + 0.00011 * drift ^ 2
    # koustov = 390 + 0.00015 * drift ^ 2
    # fit_105 = 333.4 + 0.0001045 * drift ^ 2
    # fit_108 = 352.6 + 0.000139 * drift ^ 2
    # fit_111 = 379.6 + 0.000156 * drift ^ 2
    # fit_114 = 410.1 + 0.000141 * drift ^ 2
    # fit_117 = 452.5 + 0.000114 * drift ^ 2
    # fit_120 = 479.8 + 0.000119 * drift ^ 2

    drift = [-300, -600, -800, -1000, -1200, -1400]
    fit_99 = 309.0 + 0.0000448 * np.power(drift, 2)
    fit_102 = 319.0 + 0.0000674 * np.power(drift, 2)
    nielsen = 300. + 0.00011 * np.power(drift, 2)
    koustov = 390 + 0.00015 * np.power(drift, 2)
    fit_105 = 333.4 + 0.0001045 * np.power(drift, 2)
    fit_108 = 352.6 + 0.000139 * np.power(drift, 2)
    fit_111 = 379.6 + 0.000156 * np.power(drift, 2)
    fit_114 = 410.1 + 0.000141 * np.power(drift, 2)
    fit_117 = 452.5 + 0.000114 * np.power(drift, 2)
    fit_120 = 479.8 + 0.000119 * np.power(drift, 2)

    Line_Width = 2
    # Plot the Cs versus ExB drift curves
    plt.plot(drift, -fit_99, 'k-', linewidth=Line_Width)
    plt.plot(drift, -fit_102, 'm-', linewidth=Line_Width)
    plt.plot(drift, -nielsen, 'g-', linewidth=Line_Width)
    # plt.plot(drift, -koustov, 'm-', linewidth=Line_Width)
    # plt.plot(drift, -fit_105, 'c-', linewidth=Line_Width)
    # plt.plot(drift, -fit_108, 'k-', linewidth=Line_Width)
    # plt.plot(drift, -fit_111, 'r-', linewidth=Line_Width)
    # plt.plot(drift, -fit_114, 'g-', linewidth=Line_Width)
    # plt.plot(drift, -fit_117, 'm-', linewidth=Line_Width)
    # plt.plot(drift, -fit_120, 'c-', linewidth=Line_Width)

    # fix up plot and show
    plt.legend(loc='lower right')
    plt.show()

    if SAVE_PLOTS:
        cur_path = os.path.dirname(__file__)  # where we are
        myPlot.savefig(cur_path + '/Processed_data/' + OUT_FILE_NAME + '.eps',
                       format='eps',
                       dpi=2400)
        myPlot.savefig(cur_path + '/Processed_data/' + OUT_FILE_NAME + '.svg',
                       format='svg')
        # myPlot.savefig(cur_path + '/Processed_data/' + OUT_FILE_NAME + '.jpeg', format='jpeg')
        myPlot.savefig(cur_path + '/Processed_data/' + OUT_FILE_NAME + '.pdf',
                       format='pdf',
                       dpi=500)
        myPlot.savefig(cur_path + '/Processed_data/' + OUT_FILE_NAME + '.jpg',
                       format='jpg',
                       dpi=500)
        # myPlot.savefig(cur_path + '/Processed_data/' + OUT_FILE_NAME + '.svg', format='svg', dpi=1200)

    return plt.gca()
Пример #4
0
def VelocityScatterComparison():
    """
    Purpose:
        Plot a velocity range profile and a velocity scatter comparision together in one figure
        Does not plot morphological groupings
    Pre-conditions:
        Data files and the programs to read in these files must exist
    Post-conditions:
        Figure is created with 2 subplots:
        - Velocity Range Profile (RKN 10 and 12 MHz data as a function of range gate)
        - Velocity Scatter Comparision (RKN 10 and 12 MHz velocity as a function of RISR_HDF5 velocity (ExB))

        Optionally creates an eps file of the figure
    Return:
        none
    """

    START_UT = 19.10
    END_UT = 19.19
    MIN_NUM_RAW = 3  # minimum number of data points required for a RKN median to be plotted
    SAVE_PLOTS = False
    RKN_PT_OFFSET = 0.1  # how offset from the actual position RKN data points are, done so the points are not right \
    # on top of each other
    OUT_FILE_NAME = "06032016_VelRng_VelScat_" + str(START_UT) + "-" + str(
        END_UT) + "UT"
    FIG_SIZE = (10, 12)  # size of the figure created
    VEL_RNG_PLT_RANGE = [-0.5, 30.5, -1200, 400]
    VEL_SCAT_PLT_RANGE = [-1200, 400, -1200, 400]
    LABEL_SIZE = 25
    TICK_LABEL_SIZE = 20

    fig = plt.figure(figsize=FIG_SIZE)
    gs = GridSpec(50, 50)  # 50 rows, 50 columns
    fig.suptitle('6 March 2016, ' + str(int(START_UT)) + ':' +
                 str(int((START_UT * 60) % 60)).zfill(2) + '-' +
                 str(int(END_UT)) + ':' + str(int(
                     (END_UT * 60) % 60)).zfill(2) + 'UT',
                 fontsize=35)

    VelRngAx = fig.add_subplot(gs[0:20, 2:48])
    VelScatAx = fig.add_subplot(gs[26:45, 12:37])

    # get RKN data
    RKN_data = getRKN()
    # remove the string descriptions and create numpy arrays
    RKN_start_UT = np.asarray(RKN_data[0]) if RKN_data[0].pop(
        0) == "start" else print("Error: RKN start time data")
    RKN_end_UT = np.asarray(RKN_data[1]) if RKN_data[1].pop(
        0) == "end" else print("Error getting end time data")
    RKN_gate = np.asarray(RKN_data[2]) if RKN_data[2].pop(
        0) == "gate" else print("Error: RKN gate data")
    RKN_n10 = np.asarray(RKN_data[3]) if RKN_data[3].pop(
        0) == "n10" else print("Error: RKN number of 10 MHz points")
    RKN_med_vel10 = np.asarray(RKN_data[4]) if RKN_data[4].pop(
        0) == "med_vel10" else print("Error: RKN 10MHz vel data")
    RKN_std_vel10 = np.asarray(RKN_data[5]) if RKN_data[5].pop(
        0) == "std_vel10" else print("Error: RKN std_vel_10")
    RKN_n12 = np.asarray(RKN_data[6]) if RKN_data[6].pop(
        0) == "n12" else print("Error: RKN number of 12 MHz points")
    RKN_med_vel12 = np.asarray(RKN_data[7]) if RKN_data[7].pop(
        0) == "med_vel12" else print("Error: RKN 12MHz vel data")
    RKN_std_vel12 = np.asarray(RKN_data[8]) if RKN_data[8].pop(
        0) == "stddev_vel12" else print("Error: RKN std_vel_12")

    # Restrict to a specific time period and gate range
    valid_RKN = (RKN_start_UT
                 == START_UT) & (RKN_end_UT <= END_UT) & (RKN_gate <= 30)
    _RKN_start_UT = RKN_start_UT[valid_RKN]
    _RKN_gate = RKN_gate[valid_RKN]
    _RKN_vel10 = RKN_med_vel10[valid_RKN]
    _RKN_vel12 = RKN_med_vel12[valid_RKN]
    _RKN_std_vel10 = RKN_std_vel10[valid_RKN]
    _RKN_std_vel12 = RKN_std_vel12[valid_RKN]
    _RKN_n10 = RKN_n10[valid_RKN]
    _RKN_n12 = RKN_n12[valid_RKN]

    # remove velocity points where there are less than MIN_NUM_RAW data points used in calculation of the mean
    # also remove any group value that may have been assigned here if necessary
    for i in range(len(_RKN_vel10)):
        if _RKN_n10[i] < MIN_NUM_RAW:
            _RKN_vel10[i] = math.nan
        if _RKN_n12[i] < MIN_NUM_RAW:
            _RKN_vel12[i] = math.nan

    # Set up velocity as a function of range gate plot (on top)
    VelRngAx.set_xlabel('Range Gate', size=LABEL_SIZE)
    VelRngAx.set_ylabel('Velocity [m/s]', size=LABEL_SIZE)
    VelRngAx.minorticks_on()
    VelRngAx.set_yticks([400, 200, 0, -200, -400, -600, -800, -1000, -1200])
    VelRngAx.tick_params(axis='y', which='minor', left=False)
    VelRngAx.tick_params(axis='both', which='major', labelsize=TICK_LABEL_SIZE)
    VelRngAx.set_xlim(left=VEL_RNG_PLT_RANGE[0], right=VEL_RNG_PLT_RANGE[1])
    VelRngAx.set_ylim(bottom=VEL_RNG_PLT_RANGE[2], top=VEL_RNG_PLT_RANGE[3])
    VelRngAx.grid(axis='y', which='major', linestyle='--')
    VelRngAx.plot([-1, 31], [0, 0], 'k-', linewidth='0.6')
    VelRngAx.text(VEL_RNG_PLT_RANGE[0] +
                  0.94 * abs(VEL_RNG_PLT_RANGE[1] - VEL_RNG_PLT_RANGE[0]),
                  VEL_RNG_PLT_RANGE[2] +
                  0.04 * abs(VEL_RNG_PLT_RANGE[3] - VEL_RNG_PLT_RANGE[2]),
                  'a',
                  fontsize=37)

    # plot RKN data, 10 MHz slightly offset to the left, and 12 MHz slightly offset to the right
    VelRngAx.plot(_RKN_gate - RKN_PT_OFFSET,
                  _RKN_vel10,
                  'rd',
                  label='10.4 MHz',
                  markersize=6.25)
    VelRngAx.plot(_RKN_gate + RKN_PT_OFFSET,
                  _RKN_vel12,
                  'bd',
                  label='12.3 MHz',
                  markersize=6.25)

    # plot error in RKN data
    for i in range(len(_RKN_vel10)):
        if not math.isnan(_RKN_vel10[i]):
            VelRngAx.plot(
                [_RKN_gate[i] - RKN_PT_OFFSET, _RKN_gate[i] - RKN_PT_OFFSET], [
                    _RKN_vel10[i] + _RKN_std_vel10[i],
                    _RKN_vel10[i] - _RKN_std_vel10[i]
                ],
                'r-',
                linewidth=1.25)
    for i in range(len(_RKN_vel12)):
        if not math.isnan(_RKN_vel12[i]):
            VelRngAx.plot(
                [_RKN_gate[i] + RKN_PT_OFFSET, _RKN_gate[i] + RKN_PT_OFFSET], [
                    _RKN_vel12[i] + _RKN_std_vel12[i],
                    _RKN_vel12[i] - _RKN_std_vel12[i]
                ],
                'b-',
                linewidth=1.25)

    # get RISR_HDF5 data
    RISR_data = getRISR()
    RISR_start_UT = np.asarray(RISR_data[0]) if RISR_data[0].pop(0) == "START_UT" else \
        print("Error: RISR_HDF5 start time data")
    RISR_end_UT = np.asarray(RISR_data[1]) if RISR_data[1].pop(0) == "END_UT" else \
        print("Error: RISR_HDF5 end time data")
    RISR_geolat = np.asarray(RISR_data[2]) if RISR_data[2].pop(0) == "LATITUDE" else \
        print("Error: RISR_HDF5 geolat data")
    RISR_vel = np.asarray(RISR_data[3]) if RISR_data[3].pop(0) == "VEL" else \
        print("Error: RISR_HDF5 velocity data")
    RISR_dvel = np.asarray(RISR_data[4]) if RISR_data[4].pop(0) == "D_VEL" else \
        print("Error: RISR_HDF5 velocity data")

    # Restrict to a specific time period (START_UT-END_UT)
    valid_times_RISR = (RISR_start_UT >= START_UT) & (
        RISR_end_UT <= END_UT) & (RISR_start_UT < RISR_end_UT)
    # for i in range(len(valid_times_RISR)):
    #     if valid_times_RISR[i]:
    #         print(True)
    # print(valid_times_RISR)
    _RISR_start_UT = RISR_start_UT[valid_times_RISR]
    _RISR_geolat = RISR_geolat[valid_times_RISR]
    _RISR_vel = RISR_vel[valid_times_RISR]
    _RISR_dvel = RISR_dvel[valid_times_RISR]

    _RISR_gate = glatToGate(_RISR_geolat)  # convert geolat to gate

    # since we are connecting with a line we have to remove all NaN values so there are no breaks in the line
    not_nan = []
    for i in range(len(_RISR_vel)):
        if math.isnan(_RISR_vel[i]):
            not_nan.append(False)
        else:
            not_nan.append(True)

    __RISR_gate = _RISR_gate[not_nan]
    __RISR_vel = _RISR_vel[not_nan]
    __RISR_dvel = _RISR_dvel[not_nan]

    # plot the data
    VelRngAx.plot(__RISR_gate,
                  __RISR_vel,
                  'ks',
                  label='RISR_HDF5',
                  markersize=6)
    VelRngAx.plot(__RISR_gate, __RISR_vel, 'k-', linewidth=1.25)
    for i in range(len(__RISR_gate)):  # Plot error
        VelRngAx.plot(
            [_RISR_gate[i], _RISR_gate[i]],
            [_RISR_vel[i] + _RISR_dvel[i], _RISR_vel[i] - _RISR_dvel[i]],
            'k-',
            linewidth=1.25)

    # add legend
    VelRngAx.legend(loc='lower left', fontsize=17)

    # Remove all RKN data that is not within the RISR_HDF5 gate range
    valid_gates_RKN = (_RKN_gate >= math.floor(
        min(_RISR_gate))) & (_RKN_gate <= math.ceil(max(_RISR_gate)))
    __RKN_start_UT = _RKN_start_UT[valid_gates_RKN]
    __RKN_gate = _RKN_gate[valid_gates_RKN]
    __RKN_vel10 = _RKN_vel10[valid_gates_RKN]
    __RKN_vel12 = _RKN_vel12[valid_gates_RKN]

    # Round all RISR_HDF5 gate data to whole numbers so they can be easily picked out and
    # compared with the corresponding RKN gate
    _RISR_gate_rounded = np.around(_RISR_gate)

    new_RISR_vel = np.zeros(len(__RKN_gate))  # pre-allocate
    # Loop through the RKN data and make points by averaging the corresponding RISR_HDF5 data
    for i in range(len(__RKN_gate)):
        RISR_idexs_that_match = (_RISR_gate_rounded == __RKN_gate[i]) & (
            _RISR_start_UT == __RKN_start_UT[i])
        new_RISR_vel[i] = mean(_RISR_vel[RISR_idexs_that_match]
                               )  # between 1 and 3 points will be averaged

    # Set up RKN velocity as a function of RISR_HDF5 velocity plot (on bottom)
    VelScatAx.set_xlim(left=VEL_SCAT_PLT_RANGE[0], right=VEL_SCAT_PLT_RANGE[1])
    VelScatAx.set_ylim(bottom=VEL_SCAT_PLT_RANGE[2], top=VEL_SCAT_PLT_RANGE[3])
    VelScatAx.grid(axis='both', which='major', linestyle='--')
    VelScatAx.set_xlabel('Velocity (RISR_HDF5) [m/s]', size=LABEL_SIZE)
    VelScatAx.set_ylabel('Velocity (RKN) [m/s]', size=LABEL_SIZE)
    VelScatAx.set_xticks([400, 200, 0, -200, -400, -600, -800, -1000, -1200])
    VelScatAx.set_yticks([400, 200, 0, -200, -400, -600, -800, -1000, -1200])
    VelScatAx.plot([VEL_SCAT_PLT_RANGE[0], VEL_SCAT_PLT_RANGE[1]],
                   [VEL_SCAT_PLT_RANGE[0], VEL_SCAT_PLT_RANGE[1]],
                   'k-',
                   linewidth='0.6')  # bisector
    VelScatAx.plot([VEL_SCAT_PLT_RANGE[0], VEL_SCAT_PLT_RANGE[1]], [0, 0],
                   'k-',
                   linewidth='0.6')
    VelScatAx.plot([0, 0], [VEL_SCAT_PLT_RANGE[2], VEL_SCAT_PLT_RANGE[3]],
                   'k-',
                   linewidth='0.6')
    VelScatAx.text(VEL_SCAT_PLT_RANGE[0] +
                   0.89 * abs(VEL_SCAT_PLT_RANGE[1] - VEL_SCAT_PLT_RANGE[0]),
                   VEL_SCAT_PLT_RANGE[2] +
                   0.045 * abs(VEL_SCAT_PLT_RANGE[3] - VEL_SCAT_PLT_RANGE[2]),
                   'b',
                   fontsize=37)
    VelScatAx.tick_params(axis='both',
                          which='major',
                          labelsize=TICK_LABEL_SIZE)
    VelScatAx.tick_params(axis='x', rotation=45)

    # plot the data
    VelScatAx.scatter(new_RISR_vel,
                      __RKN_vel10,
                      s=45,
                      facecolors='none',
                      edgecolors='r',
                      label='10.4 MHz',
                      linewidths=1.5)
    VelScatAx.scatter(new_RISR_vel,
                      __RKN_vel12,
                      s=45,
                      facecolors='none',
                      edgecolors='b',
                      label='12.3 MHz',
                      linewidths=1.5)

    VelScatAx.legend(loc=(0.465, 0.765), fontsize=17)

    if SAVE_PLOTS:
        cur_path = os.path.dirname(__file__)  # where we are
        fig.savefig(cur_path + '/Processed_data/' + OUT_FILE_NAME + '.eps',
                    format='eps',
                    bbox_inches='tight')
        fig.savefig(cur_path + '/Processed_data/' + OUT_FILE_NAME + '.svg',
                    format='svg',
                    dpi=1200)

    plt.show()
def VelocityRangeProfiler():
    """
    Purpose: Plot RKN and RISR_HDF5 velocities as a function of range gate.  Plots +/- given error in RISR_HDF5 velocities and
        +/- 1 standard deviation in RKN velocities.
        Additionally, boxes are drawn around given groups of RKN velocities, we have the following groups,
            Group 1 (Coral): Low velocity echoes. Two types -> those of the same polarity and those of opposite
            polarities.

            Group 2 (Pink): Higher velocity echoes. Two types -> those of the same polarity and those of opposite
            polarities (Opposite polarity indicates a malfunction).

            Group 3 (Green): High velocity echoes in good agreement.  Both frequencies are detecting ExB.

            Group 4 (Purple): Medium-High velocity echoes in disagreement.  One frequency (usually 10) is detecting
            F while the other (usually 12) is detecting E.
    Pre-conditions:
        Data files and the programs to read in these files must exist
    Post-conditions:
        Velocity Range Profile plot is created
        Optionally an outfile is created with the given plot
    Return:
        :return: ax: Plot axes
    """

    OUT_FILE_NAME = "06032016_Velocity_Range_Profile"
    SAVE_PLOTS = False  # Save the plot in the Processed data folder
    PLOT_GROUPINGS = False  # Plot the morphological groups as described above
    START_UT = 19.10
    END_UT = 19.19
    MIN_NUM_RAW = 3  # minimum number of data points required for a RKN median to be plotted
    TEXT_SIZE = 17  # size of text in plot
    RKN_PT_OFFSET = 0.1  # how offset from the actual position RKN data points are, done so the points are not right \
    # on top of each other
    GROUP_PT_OFFSET = 0.3  # how offset from the actual gate the RKN grouping boxes are
    FIG_SIZE = (10, 6)  # size of the figure created
    PLT_RANGE = [-0.5, 30.5, -1250, 500]  # plot range [xmin, xmax, ymin, ymax]
    OUT_FILE_NAME = "06032016_Velocity_Range_Profile" + str(
        START_UT) + "-" + str(END_UT) + "UT"

    RKN_data = getRKN()  # get RKN data

    # remove the string descriptions and create numpy arrays
    RKN_start_UT = np.asarray(RKN_data[0]) if RKN_data[0].pop(
        0) == "start" else print("Error: RKN start time data")
    # RKN_end_UT = np.asarray(RKN_data[1]) if RKN_data[1].pop(0) == "end" else print("Error getting end time data")
    RKN_gate = np.asarray(RKN_data[2]) if RKN_data[2].pop(
        0) == "gate" else print("Error: RKN gate data")
    RKN_n10 = np.asarray(RKN_data[3]) if RKN_data[3].pop(
        0) == "n10" else print("Error: RKN number of 10 MHz points")
    RKN_med_vel10 = np.asarray(RKN_data[4]) if RKN_data[4].pop(
        0) == "med_vel10" else print("Error: RKN 10MHz vel data")
    RKN_std_vel10 = np.asarray(RKN_data[5]) if RKN_data[5].pop(
        0) == "std_vel10" else print("Error: RKN std_vel_10")
    RKN_n12 = np.asarray(RKN_data[6]) if RKN_data[6].pop(
        0) == "n12" else print("Error: RKN number of 12 MHz points")
    RKN_med_vel12 = np.asarray(RKN_data[7]) if RKN_data[7].pop(
        0) == "med_vel12" else print("Error: RKN 12MHz vel data")
    RKN_std_vel12 = np.asarray(RKN_data[8]) if RKN_data[8].pop(
        0) == "stddev_vel12" else print("Error: RKN std_vel_12")
    RKN_group1 = np.asarray(RKN_data[9]) if RKN_data[9].pop(
        0) == "group1" else print("Error: group1 data")
    RKN_group2 = np.asarray(RKN_data[10]) if RKN_data[10].pop(
        0) == "group2" else print("Error: group2 data")
    RKN_group3 = np.asarray(RKN_data[11]) if RKN_data[11].pop(
        0) == "group3" else print("Error: group3 data")
    RKN_group4 = np.asarray(RKN_data[12]) if RKN_data[12].pop(
        0) == "group4" else print("Error: group4 data")

    # Restrict to a specific time period and gate range
    valid_RKN = (RKN_start_UT == START_UT) & (RKN_gate <= 30)

    _RKN_gate = RKN_gate[valid_RKN]
    _RKN_vel10 = RKN_med_vel10[valid_RKN]
    _RKN_vel12 = RKN_med_vel12[valid_RKN]
    _RKN_std_vel10 = RKN_std_vel10[valid_RKN]
    _RKN_std_vel12 = RKN_std_vel12[valid_RKN]
    _RKN_n10 = RKN_n10[valid_RKN]
    _RKN_n12 = RKN_n12[valid_RKN]
    _RKN_group1 = RKN_group1[valid_RKN]
    _RKN_group2 = RKN_group2[valid_RKN]
    _RKN_group3 = RKN_group3[valid_RKN]
    _RKN_group4 = RKN_group4[valid_RKN]

    # remove velocity points where there are less than MIN_NUM_RAW data points used in calculation of the mean
    # also remove any group value that may have been assigned here
    for i in range(len(_RKN_vel10)):
        if _RKN_n10[i] < MIN_NUM_RAW:
            _RKN_vel10[i] = math.nan
            _RKN_group1[i] = 0.
            _RKN_group2[i] = 0.
            _RKN_group3[i] = 0.
            _RKN_group4[i] = 0.
        if _RKN_n12[i] < MIN_NUM_RAW:
            _RKN_vel12[i] = math.nan
            _RKN_group1[i] = 0.
            _RKN_group2[i] = 0.
            _RKN_group3[i] = 0.
            _RKN_group4[i] = 0.

    # Plot velocities as a function of range gate
    # Set up plot
    myPlot = plt.figure(figsize=FIG_SIZE)
    plt.rc('font', size=TEXT_SIZE)
    plt.plot([-1, 31], [0, 0], 'k-', linewidth='0.6')
    plt.xlabel('Range Gate')
    plt.ylabel('Velocity [m/s]')
    plt.title('6 March 2016, ' + str(int(START_UT)) + ':' +
              str(int((START_UT * 60) % 60)).zfill(2) + '-' +
              str(int(END_UT)) + ':' + str(int((END_UT * 60) % 60)).zfill(2) +
              'UT')
    plt.axis(PLT_RANGE)
    ax = plt.gca()
    ax.minorticks_on()
    ax.tick_params(axis='y', which='minor', left=False)

    # plot error in RKN data
    for i in range(len(_RKN_vel10)):
        if not math.isnan(_RKN_vel10[i]):
            plt.plot(
                [_RKN_gate[i] - RKN_PT_OFFSET, _RKN_gate[i] - RKN_PT_OFFSET], [
                    _RKN_vel10[i] + _RKN_std_vel10[i],
                    _RKN_vel10[i] - _RKN_std_vel10[i]
                ],
                'r-',
                linewidth=1.25)
    for i in range(len(_RKN_vel12)):
        if not math.isnan(_RKN_vel12[i]):
            plt.plot(
                [_RKN_gate[i] + RKN_PT_OFFSET, _RKN_gate[i] + RKN_PT_OFFSET], [
                    _RKN_vel12[i] + _RKN_std_vel12[i],
                    _RKN_vel12[i] - _RKN_std_vel12[i]
                ],
                'b-',
                linewidth=1.25)

    if PLOT_GROUPINGS:
        # Look through all groups and add rectangles to the plot
        for group in range(4):
            if group == 0:  # go through each group
                # Low velocity echoes
                # Two types -> those of the same polarity and those of opposite polarity
                group_i = _RKN_group1
                COL = 'coral'
                BASE_HEIGHT = -225
                HEIGHT = 275
            elif group == 1:
                # Higher velocity echoes, both frequencies detecting E region echoes Two types -> those of the same
                # polarity and those of opposite polarities, opposite polarities indicate malfunction
                group_i = _RKN_group2
                COL = 'deeppink'
                BASE_HEIGHT = -525
                HEIGHT = 500
            elif group == 2:
                # High velocity echoes in good agreement, both frequencies detecting ExB
                group_i = _RKN_group3
                COL = 'forestgreen'
                BASE_HEIGHT = -1025
                HEIGHT = 875
            else:
                # High velocity echoes in disagreement
                # One frequency (usually 10) is detecting F while the other (usually 12) is detecting E
                group_i = _RKN_group4
                COL = 'm'
                BASE_HEIGHT = -1025
                HEIGHT = 1250

            i = 0
            while i < len(group_i):
                if group_i[i]:
                    j = i + 1
                    if j == len(group_i):  # we are at the end of the array
                        group1_rect = patches.Rectangle(
                            (_RKN_gate[i] - GROUP_PT_OFFSET, BASE_HEIGHT),
                            2 * GROUP_PT_OFFSET,
                            HEIGHT,  # One one spot, always 0.6 wide
                            linewidth=1,
                            edgecolor=COL,
                            facecolor='none')
                        plt.gca().add_patch(
                            group1_rect
                        )  # have to add right away encase there is another group2 set
                    else:
                        while group_i[j]:
                            j += 1
                            if j == len(
                                    group_i):  # we are at the end of the array
                                break
                        group1_rect = patches.Rectangle(
                            (_RKN_gate[i] - GROUP_PT_OFFSET, BASE_HEIGHT),
                            (j - i - 1 + 2 * GROUP_PT_OFFSET),
                            HEIGHT,
                            linewidth=1,
                            edgecolor=COL,
                            facecolor='none')
                        plt.gca().add_patch(
                            group1_rect
                        )  # have to add right away encase there is another group2 set
                        i = j + 1
                i += 1

    # plot RKN data, 10 MHz slightly offset to the left, and 12 MHz slightly offset to the right
    plt.plot(_RKN_gate - RKN_PT_OFFSET,
             _RKN_vel10,
             'rd',
             label='10.4 MHz',
             markersize=6.25)
    plt.plot(_RKN_gate + RKN_PT_OFFSET,
             _RKN_vel12,
             'bd',
             label='12.3 MHz',
             markersize=6.25)

    RISR_data = getRISR()  # get RISR_HDF5 data

    RISR_start_UT = np.asarray(RISR_data[0]) if RISR_data[0].pop(0) == "START_UT" else \
        print("Error: RISR_HDF5 start time data")
    # RISR_end_UT = np.asarray(RISR_data[1]) if RISR_data[1].pop(0) == "END_UT" else \
    #     print("Error: RISR_HDF5 end time data")
    RISR_geolat = np.asarray(RISR_data[2]) if RISR_data[2].pop(0) == "LATITUDE" else \
        print("Error: RISR_HDF5 geolat data")
    RISR_vel = np.asarray(RISR_data[3]) if RISR_data[3].pop(0) == "VEL" else \
        print("Error: RISR_HDF5 velocity data")
    RISR_dvel = np.asarray(RISR_data[4]) if RISR_data[4].pop(0) == "D_VEL" else \
        print("Error: RISR_HDF5 velocity data")

    # Restrict to a specific time period (19.10-19.19)
    valid_times_RISR = RISR_start_UT == 19.10  # Get the bool array of all elements with start time 19.10
    _RISR_geolat = RISR_geolat[valid_times_RISR]
    _RISR_vel = RISR_vel[valid_times_RISR]
    _RISR_dvel = RISR_dvel[valid_times_RISR]

    _RISR_gate = glatToGate(_RISR_geolat)  # convert geolat to gate

    # since we are connecting with a line we have to remove all NaN values so there are no breaks in the line
    not_nan = []
    for i in range(len(_RISR_vel)):
        if math.isnan(_RISR_vel[i]):
            not_nan.append(False)
        else:
            not_nan.append(True)

    __RISR_gate = _RISR_gate[not_nan]
    __RISR_vel = _RISR_vel[not_nan]
    __RISR_dvel = _RISR_dvel[not_nan]

    # plot the data
    plt.plot(__RISR_gate, __RISR_vel, 'ks', label='RISR_HDF5', markersize=6)
    plt.plot(__RISR_gate, __RISR_vel, 'k-', linewidth=1.25)

    # Plot error
    for i in range(len(__RISR_gate)):
        plt.plot([_RISR_gate[i], _RISR_gate[i]],
                 [_RISR_vel[i] + _RISR_dvel[i], _RISR_vel[i] - _RISR_dvel[i]],
                 'k-',
                 linewidth=1.25)

    # fix up plot and show
    plt.legend(loc='lower left')
    plt.grid(axis='y', linestyle='--')

    # Look at size of plot
    # fig_size = plt.rcParams["figure.figsize"]   # default [6.4, 4.8]
    # print(fig_size)

    # plt.show()

    if SAVE_PLOTS:
        cur_path = os.path.dirname(__file__)  # where we are
        myPlot.savefig(cur_path + '/Processed_data/' + OUT_FILE_NAME + '.ps',
                       format='ps',
                       orientation='landscape')
        # myPlot.savefig(cur_path + '/Processed_data/' + OUT_FILE_NAME + '.svg', format='svg', dpi=1200)

    return plt.gca()