Beispiel #1
0
def import_solar_wind_plasma_data(t_start="2008-01-01T00:00:00",
                                  t_stop="2012-12-31T23:59:59"):
    """
    Load in the various raw solar wind plasma data, clean up the data and make it consistent, having the
    same format and span. This is then saved as a CSV for quick loading into PANDAS in the following analysis.
    :param t_start: timestring of the beginning time of the observation period to return
    :param t_stop: timestring of the end time of the observation period to return
    :return:
    """
    fmt = "%Y-%m-%dT%H:%M:%S"
    t_start = pd.datetime.strptime(t_start, fmt)
    t_stop = pd.datetime.strptime(t_stop, fmt)

    for src in ['wind', 'sta', 'stb']:

        if src == 'wind':
            data = swp.import_wind_data()
        elif src == 'sta':
            data = swp.import_sta_data()
        elif src == 'stb':
            data = swp.import_stb_data()

        # Restrict to window of interest
        find_period = (data['time'] >= t_start) & (data['time'] <= t_stop)
        data = data.loc[find_period, :]

        # Save to csv.
        proj_dirs = swp.project_info()
        out_name = "{}_mapped_speed_data_{}_{}.csv".format(
            src, t_start.strftime("%Y%m%d"), t_stop.strftime("%Y%m%d"))
        out_path = os.path.join(proj_dirs['data'], out_name)
        data.to_csv(out_path)
    return
Beispiel #2
0
def get_hi_files():
    """
    Function used to find a a days worth of HI1a files stored locally for  specific plot.
    :return:
    """
    proj_dirs = swp.project_info()
    hi_path = os.path.join(proj_dirs['data'], "hi1a")
    hi_path = os.path.join(hi_path, '*.fts')
    out_files = glob.glob(hi_path)
    return out_files
Beispiel #3
0
def spacecraft_orbits():
    """
    Produce a plot of the positions of STEREO-A, STEREO-B and WIND in Heliospheric Equatorial Coordinates
    over the studied period 2008-01-01 to 2012-12-31.
    """
    craft_cols = swp.get_craft_colors()

    au = solarconst.au.to('km').value

    # Plot each event individually
    t_s = pd.date_range("2008-01-01", "2013-01-01", freq="D")
    time = Time(t_s.to_pydatetime())

    system = 'HEEQ'
    wnd = swp.get_wind_lonlat(time, system)
    sta = spice.get_lonlat(time, 'sta', system, degrees=True)
    stb = spice.get_lonlat(time, 'stb', system, degrees=True)

    wnd[:, 0] = wnd[:, 0] / au
    sta[:, 0] = sta[:, 0] / au
    stb[:, 0] = stb[:, 0] / au

    fig, ax = plt.subplots(3, 1, figsize=(14, 7))

    for data, col, label in zip([wnd, sta, stb], craft_cols,
                                ['WIND', 'STA', 'STB']):
        for i, a in enumerate(ax):
            a.plot(time.to_datetime(), data[:, i], '-', color=col, label=label)

    for a in ax:
        a.legend(frameon=False)
        a.set_xlim(time.to_datetime().min(), time.to_datetime().max())

    for a in ax[0:2]:
        a.set_xticklabels([])

    ymin = 0.94
    ymax = 1.1
    ax[0].set_ylim(ymin, ymax)

    fnt = 15
    ax[0].set_ylabel('{} Radius (Au)'.format(system.upper()), fontsize=fnt)
    ax[1].set_ylabel('{} Lon. (deg)'.format(system.upper()), fontsize=fnt)
    ax[2].set_ylabel('{} Lat. (deg)'.format(system.upper()), fontsize=fnt)

    ax[2].set_xlabel('Date', fontsize=fnt)

    for a in ax:
        a.tick_params("both", labelsize=14)

    fig.subplots_adjust(left=0.075,
                        right=0.98,
                        bottom=0.075,
                        top=0.99,
                        wspace=0.01,
                        hspace=0.0)
    proj_dirs = swp.project_info()
    out_name = "spacecraft_orbits.png"
    out_path = os.path.join(proj_dirs['figs'], out_name)
    fig.savefig(out_path)
    return
Beispiel #4
0
def hi1a_thomson_sphere_and_parker_spiral():
    """
    Produce a plot showing the approximate layout of the Thomson sphere of HI1A, including the idealised Parker spiral
    streamlines connecting STEREO-A, STEREO-B, and WIND to the corona.
    """
    craft_cols = swp.get_craft_colors()

    rs = solarconst.radius.to('km').value

    # Plot each event individually
    time = ["{}-06-15".format(i) for i in range(2008, 2013)]
    time = Time(time)

    fig, ax = plt.subplots(2, len(time), figsize=(15, 6))
    ax_t = ax[0, :]
    ax_b = ax[1, :]

    for t, at, ab in zip(time, ax_t, ax_b):

        system = 'HEEQ'
        wnd = swp.get_wind_coords(t, system)
        sta = spice.get_coord(t, 'sta', system, no_velocity=True)
        stb = spice.get_coord(t, 'stb', system, no_velocity=True)

        wnd = wnd / rs
        sta = sta / rs
        stb = stb / rs

        sta_r = np.sqrt(np.sum(sta**2))
        wnd_r = np.sqrt(np.sum(wnd**2))
        stb_r = np.sqrt(np.sum(stb**2))

        for a in [at, ab]:
            # Plot the sun, and source elongations considered
            rad = rs / rs
            xcenter, ycenter = 0, 0
            x, y = get_circ_coords(xcenter, ycenter, rad)
            a.fill(x,
                   y,
                   facecolor='orange',
                   edgecolor='orange',
                   linewidth=2,
                   zorder=1)

            rad = (20.0 * rs / rs)
            x, y = get_circ_coords(xcenter, ycenter, rad)
            a.fill(x,
                   y,
                   facecolor='None',
                   edgecolor='k',
                   linewidth=2,
                   zorder=1)

            rad = (22.5 * rs / rs)
            x, y = get_circ_coords(xcenter, ycenter, rad)

            a.fill(x,
                   y,
                   facecolor='None',
                   edgecolor='k',
                   linewidth=2,
                   zorder=1)

            # Plot the TS for craft at x=au, y=0
            rad = sta_r / 2.0
            xcenter, ycenter = sta[1] / 2.0, sta[0] / 2.0
            x, y = get_circ_coords(xcenter, ycenter, rad)
            a.fill(x,
                   y,
                   facecolor='None',
                   edgecolor=craft_cols[1],
                   linestyle='--',
                   linewidth=2,
                   zorder=1)

            # Add on the craft
            a.plot(sta[1], sta[0], 's', color=craft_cols[1], label='STA')

            a.plot(wnd[1], wnd[0], 'o', color=craft_cols[0], label='WIND')

            a.plot(stb[1], stb[0], '^', color=craft_cols[2], label='STB')

            # Add on idealised Parker Spiral for STEREO-A, STEREO-B and WIND
            ro = 22.5
            V = 400.0
            phi_fin = np.arctan2(wnd[0], wnd[1])
            x, y = get_parker_spiral(ro, wnd_r, phi_fin, V)
            a.plot(y, x, '-', color=craft_cols[0])

            phi_fin = np.arctan2(sta[0], sta[1])
            x, y = get_parker_spiral(ro, sta_r, phi_fin, V)
            a.plot(y, x, '-', color=craft_cols[1])

            phi_fin = np.arctan2(stb[0], stb[1])
            x, y = get_parker_spiral(ro, stb_r, phi_fin, V)
            a.plot(y, x, '-', color=craft_cols[2])

        label = t.datetime.strftime("%Y-%m-%d")
        at.text(0.6,
                0.925,
                label,
                color='k',
                transform=at.transAxes,
                fontsize=14)
        at.legend(loc=2)

    for a in ax_t:
        a.set_xlim(-225, 225)
        a.set_ylim(-225, 225)

    for a in ax_b:
        a.set_xlim(-50, 50)
        a.set_ylim(-50, 50)

    for a in ax.ravel():
        a.set_xticklabels([])
        a.set_yticklabels([])
        a.set_xticks([])
        a.set_yticks([])
        a.set_aspect('equal')
        a.invert_yaxis()

    fig.subplots_adjust(left=0.01,
                        bottom=0.01,
                        right=0.99,
                        top=0.99,
                        wspace=0,
                        hspace=0)
    proj_dirs = swp.project_info()
    out_name = "hi1a_ts_relative_locations.png"
    out_path = os.path.join(proj_dirs['figs'], out_name)
    fig.savefig(out_path)
    return
Beispiel #5
0
def insitu_time_series_acf():
    """
    Compute the autocorrelation function of the in-situ solar wind parameters, and plot these with the time series, for
    each of STEREO-A, STEREO-B and WIND.
    :return:
    """
    acf_opts = swp.get_acf_opts()
    acf_opts['do_sig'] = True
    acf_opts['iters'] = 1000

    fig, ax, axl, axr = setup_time_series_acf_figure()
    craft_cols = swp.get_craft_colors()

    # Now load in the in-situ data. take daily means. compute spearman acf and sig. plot.
    epoch_start = "2008-01-01T00:00:00"
    t_start = Time(epoch_start)
    for sw_param in ['V', 'rho', 'T']:

        if sw_param == "V":
            ylabel_unit = r"Plasma speed ($km/s$)"
            ylim = [250, 800]
        elif sw_param == "rho":
            ylabel_unit = r"Density ($cm^{{-3}}$)"
            ylim = [0, 20]
        elif sw_param == "T":
            ylabel_unit = r"Temperature ($MK$)"
            ylim = [0, 0.5]

        for i, craft in enumerate(['wind', 'stb', 'sta']):

            if craft == 'wind':
                situ = swp.load_wind_data()
            elif craft == 'stb':
                situ = swp.load_stb_data()
            elif craft == 'sta':
                situ = swp.load_sta_data()

            situ_avg = swp.situ_daily_averaging(situ,
                                                reference_time=epoch_start)

            axl[i].plot(situ_avg['days'],
                        situ_avg[sw_param],
                        '-',
                        color=craft_cols[i])
            axl[i].set_ylabel(r"{} {}".format(craft.upper(), ylabel_unit))

            # Now compute acf and plot.
            lags, acf, acf_sig = swp.compute_situ_acf(situ_avg,
                                                      sw_param,
                                                      acf_opts=acf_opts)

            axr[i].plot(lags, acf, 'k-')
            axr[i].plot(lags, acf_sig[0, :], 'r--')
            axr[i].plot(lags, acf_sig[1, :], 'r--')

        for al, ar in zip(axl[:2], axr[:2]):
            al.set_xticklabels([])
            ar.set_xticklabels([])

        axl[-1].set_xlabel("Days since {}".format(
            t_start.datetime.strftime("%Y-%m-%d")))
        axr[-1].set_xlabel("Lag (days)")

        for i, (al, ar) in enumerate(zip(axl, axr)):
            al.set_xlim(situ_avg['days'].min(), situ_avg['days'].max())
            al.set_ylim(ylim[0], ylim[1])

            ar.set_xlim(0, lags.max())
            ar.set_ylim(-0.15, 1.0)

            label = "A{})".format(i + 1)
            al.text(0.01, 0.92, label, color='k', transform=al.transAxes)

            label = "B{})".format(i + 1)
            ar.text(0.0275, 0.92, label, color='k', transform=ar.transAxes)

            al.tick_params('both')
            ar.tick_params('both')

        for ar in axr:
            ar.set_ylabel('Spearman correlation')
            ar.yaxis.tick_right()
            ar.yaxis.set_label_position("right")

        fig.subplots_adjust(left=0.05,
                            bottom=0.06,
                            right=0.95,
                            top=0.99,
                            wspace=0.03,
                            hspace=0.04)
        proj_dirs = swp.project_info()
        fig_name = "{}_time_series_and_acf.png".format(sw_param)
        fig_path = os.path.join(proj_dirs['figs'], fig_name)
        fig.savefig(fig_path)

        for a in ax:
            a.clear()

    return
Beispiel #6
0
def lagged_correlation():
    """
    Compute the lagged correlation between HI1A variability and in-situ solar wind speeds, mapped to the position angle
    of their approximate source location from backward propagating the in-situ solar wind observations.
    :return:
    """
    proj_dirs = swp.project_info()
    reduced_hi_data_path = os.path.join(proj_dirs['data'],
                                        "reduced_hi_data_std.pickle")
    with open(reduced_hi_data_path, "rb") as f:
        from_pickle = pickle.load(f)

    remote_time = from_pickle['time'].copy()
    pa_bins = from_pickle['pa_bins'].copy()
    remote = from_pickle['data'].copy()
    del from_pickle

    ts = Time("2008-01-01T00:00:00")
    remote_z = (remote - np.nanmean(remote, axis=0)) / np.nanstd(remote,
                                                                 axis=0)
    remote_time_avg, remote_avg = swp.hi_daily_averaging(
        remote_time, pa_bins, remote_z, method="mean", reference_time=ts.isot)
    del remote, remote_time

    # Compute rolling acf of in-situ params and HI variability
    fig, ax = plt.subplots(1, 3, figsize=(15, 5))

    lagged_corr_colors = swp.get_lagged_corr_colors()
    years = np.arange(0, 5 * 365, 365)
    yr_cols = [lagged_corr_colors.mpl_colors[i] for i in [5, 4, 3, 2, 1]]

    # Params for significance calc.
    n_resamples = 1000
    alpha = 1.0
    alpha2 = alpha / 2.0
    lims = [alpha2, 100.0 - alpha2]

    lag_corr_stats = np.zeros((years.size, 3, 3))

    for cc, src in enumerate(['wind', 'sta', 'stb']):

        # Load in the in-situ for this observatory
        if src == 'wind':
            situ = swp.load_wind_data()
        elif src == 'sta':
            situ = swp.load_sta_data()
        elif src == 'stb':
            situ = swp.load_stb_data()

        # Compute daily mean with same reference time as remote sensing obs.
        situ_avg = swp.situ_daily_averaging(situ, reference_time=ts.isot)
        # Occasionally a missing value in PA. replace with interpolted est - smooth function so good approx.
        num_bad = np.sum(np.isnan(situ_avg['pa']))
        if num_bad > 0:
            situ_avg['pa'] = situ_avg['pa'].interpolate()
            print "Notice: {} bad PA values found. Replacing with interpolates".format(
                num_bad)

        year_name = [2008, 2009, 2010, 2011, 2012]

        for yy, year in enumerate(years):
            id_situ = (situ_avg['days'] >= year) & (situ_avg['days'] <=
                                                    year + 365)
            situ_sub = situ_avg.loc[id_situ, :].copy()

            id_remote = (remote_time_avg.jd >= year) & (remote_time_avg.jd <=
                                                        year + 365)
            remote_time_sub = remote_time_avg[id_remote].copy()
            remote_sub = remote_avg[:, id_remote].copy()

            # Directly lookup the variability along the pa path.
            lags = np.arange(-27, 28, 1, dtype=np.int)
            corr = np.zeros(lags.shape) * np.NaN
            sig_corr = np.zeros((lags.size, 2))

            for k, lag in enumerate(lags):

                pa_track = np.zeros(situ_sub.shape[0]) * np.NaN
                var_track = np.zeros(situ_sub.shape[0]) * np.NaN
                iii = 0
                for i, row in situ_sub.iterrows():

                    id_day = np.where(remote_time_sub.jd == row['days'] +
                                      lag)[0]
                    id_pa = np.argmin(np.abs(pa_bins - row['pa']))
                    pa_track[iii] = pa_bins[id_pa]
                    if id_day.size != 0:
                        var_track[iii] = remote_sub[id_pa, id_day]
                    iii += 1

                situ_sub['pa_track'] = pa_track
                situ_sub['var_track'] = var_track

                # Compute spearman r and resampling significance.
                corr[k] = st.mstats.spearmanr(situ_sub['V'],
                                              situ_sub['var_track'])[0]

                x = situ_sub['V'].values.copy()
                y = situ_sub['var_track'].values.copy()
                resamples = np.zeros(n_resamples) * np.NaN
                for kk in range(resamples.size):
                    resamples[kk] = st.mstats.spearmanr(x, y)[0]
                    np.random.shuffle(x)
                    np.random.shuffle(y)

                # Get percentiles of the null under resampling independence
                null_lims = np.nanpercentile(resamples, lims)
                sig_corr[k, :] = null_lims

            lag_corr_stats[yy, 0, ] = year
            if (src == "wind") | (src == 'sta'):

                id_lo = lags < 0
                lags2 = lags[id_lo]
                corr2 = corr[id_lo]
                id_min = np.argmin(corr2)
                lag_corr_stats[yy, 1, cc] = lags2[id_min]
                lag_corr_stats[yy, 2, cc] = corr2[id_min]
            elif src == 'stb':
                id_mid = (lags > -10) & (lags < 10)
                lags2 = lags[id_mid]
                corr2 = corr[id_mid]
                id_min = np.argmin(corr2)
                lag_corr_stats[yy, 1, cc] = lags2[id_min]
                lag_corr_stats[yy, 2, cc] = corr2[id_min]

            # Update the plot with this years data.
            ax[cc].plot(lags,
                        corr,
                        'o-',
                        color=yr_cols[yy],
                        markerfacecolor='None',
                        label="{}".format(year_name[yy]))
            id_sig = (corr < sig_corr[:, 0]) | (corr > sig_corr[:, 1])
            ax[cc].plot(lags[id_sig], corr[id_sig], 'o', color=yr_cols[yy])

        ax[cc].text(0.0275,
                    0.92,
                    src.upper(),
                    color='k',
                    transform=ax[cc].transAxes,
                    fontsize=14)
        ax[cc].set_xlabel("Lag (days)", fontsize=14)

    for a in ax:
        a.legend(fontsize=13, ncol=2)
        a.set_xlim(lags.min(), lags.max())
        a.set_ylim(-0.55, 0.5)
        a.set_xticks(np.arange(-25, 30, 5))
        a.tick_params('both', labelsize=14)
    for a in ax[1:]:
        a.set_yticklabels([])

    ax[0].set_ylabel('Spearman correlation', fontsize=14)

    fig.subplots_adjust(left=0.075,
                        bottom=0.11,
                        right=0.98,
                        top=0.98,
                        wspace=0.025)
    proj_dirs = swp.project_info()
    out_name = "hi_var_situ_lagged_corr.png"
    out_path = os.path.join(proj_dirs['figs'], out_name)
    fig.savefig(out_path)

    #TODO Break this second plot into a seperate function, saving lag_corr_stats into a aux file.

    # Scatter plot of lag vs yr
    fig, ax = plt.subplots(figsize=(7, 6))
    craft_cols = swp.get_craft_colors()
    craft_mkr = ['o', 's', '^']

    years = (np.arange(2008, 2013, 1)) + 0.5 - 2008

    for i, craft in enumerate(['WIND', 'STA', 'STB']):

        # Plot all points of lag of minimum correlation vs year
        y = lag_corr_stats[:, 1, i]
        ax.plot(years,
                y,
                linestyle='None',
                marker=craft_mkr[i],
                color=craft_cols[i],
                label=craft.upper())

        # Fit least squares regression to this, excluding an outliet for STA.
        if craft in ["WIND", "STB"]:
            slope, intercept, r_value, p_value, std_err = st.linregress(
                years, y)
            print "{}: Gradient: {} +/- {}".format(craft, slope, std_err)
            ax.plot(years, intercept + slope * years, '-', color=craft_cols[i])
            ax.plot(years,
                    intercept + (slope - 2 * std_err) * years,
                    '--',
                    color=craft_cols[i])
            ax.plot(years,
                    intercept + (slope + 2 * std_err) * years,
                    '--',
                    color=craft_cols[i])
        elif craft == 'STA':
            # Special case to exclude outlying STA point in 2012.
            years_sub = years[:-1]
            y_sub = y[:-1]
            slope, intercept, r_value, p_value, std_err = st.linregress(
                years_sub, y_sub)
            print "{}: Gradient (no outlier): {} +/- {}".format(
                craft, slope, std_err)
            ax.plot(years_sub,
                    intercept + slope * years_sub,
                    '-',
                    color=craft_cols[i])
            ax.plot(years_sub,
                    intercept + (slope - 2 * std_err) * years_sub,
                    '--',
                    color=craft_cols[i])
            ax.plot(years_sub,
                    intercept + (slope + 2 * std_err) * years_sub,
                    '--',
                    color=craft_cols[i])

    ax.legend(fontsize=14)
    ax.set_xlabel('Years since 2008-01-01', fontsize=14)
    ax.set_ylabel('Lag of peak correlation (days)', fontsize=14)
    ax.tick_params('both', labelsize=14)
    ax.set_ylim(-27, 10)
    ax.set_xlim(0.45, 4.55)
    fig.subplots_adjust(left=0.11, bottom=0.1, right=0.99, top=0.99)
    proj_dirs = swp.project_info()
    out_name = "peak_lag_with_time.png"
    out_path = os.path.join(proj_dirs['figs'], out_name)
    fig.savefig(out_path)
    return
Beispiel #7
0
def rolling_acf():
    """
    Compute the rolling acf of the HI1A variability data and the in-situ plasma observations.
    :return:
    """
    proj_dirs = swp.project_info()
    reduced_hi_data_path = os.path.join(proj_dirs['data'],
                                        "reduced_hi_data_std.pickle")
    with open(reduced_hi_data_path, "rb") as f:
        from_pickle = pickle.load(f)

    remote_time = from_pickle['time'].copy()
    pa_bins = from_pickle['pa_bins'].copy()
    remote = from_pickle['data'].copy()
    del from_pickle

    ts = Time("2008-01-01T00:00:00")
    remote_z = (remote - np.nanmean(remote, axis=0)) / np.nanstd(remote,
                                                                 axis=0)
    remote_time_avg, remote_avg = swp.hi_daily_averaging(
        remote_time, pa_bins, remote_z, method="mean", reference_time=ts.isot)
    del remote, remote_time

    # Compute rolling acf of in-situ params and HI variability
    fig, ax = plt.subplots(2, 3, figsize=(14, 9.5))
    ax_wnd = ax[:, 0]
    ax_sta = ax[:, 1]
    ax_stb = ax[:, 2]
    ax_situ = ax[0, :]
    ax_remote = ax[1, :]

    # Setup autocorrelation options
    acf_opts = swp.get_acf_opts()
    acf_opts['do_sig'] = True
    acf_opts['iters'] = 1000
    # Arguments for the rolling autocorrelation window
    acf_window_wid = 365
    acf_window_step = 14

    # Set up the colormap of the ACF contours and the normalisation. Same for each panel.
    cmap = plt.cm.coolwarm
    norm = plt.Normalize(vmin=-1.0, vmax=1.0)
    dl = 0.1
    levels = np.arange(-0.9, 0.9 + dl, dl)

    for src, ax_cft in zip(['wind', 'sta', 'stb'], [ax_wnd, ax_sta, ax_stb]):

        # Load in the in-situ for this observatory
        if src == 'wind':
            situ = swp.load_wind_data()
        elif src == 'sta':
            situ = swp.load_sta_data()
        elif src == 'stb':
            situ = swp.load_stb_data()

        # Compute daily mean with same reference time as remote sensing obs.
        situ_avg = swp.situ_daily_averaging(situ, reference_time=ts.isot)
        # Occasionally a missing value in PA. replace with interpolted est - smooth function so good approx.
        num_bad = np.sum(np.isnan(situ_avg['pa']))
        if num_bad > 0:
            situ_avg['pa'] = situ_avg['pa'].interpolate()
            print "Notice: {} bad PA values found. Replacing with interpolates".format(
                num_bad)

        # Directly lookup the variability along the pa path.
        pa_track = np.zeros(situ_avg.shape[0]) * np.NaN
        var_track = np.zeros(situ_avg.shape[0]) * np.NaN
        for i, row in situ_avg.iterrows():
            id_day = np.where(remote_time_avg.jd == row['days'])[0]
            id_pa = np.argmin(np.abs(pa_bins - row['pa']))
            pa_track[i] = pa_bins[id_pa]
            if id_day.size != 0:
                var_track[i] = remote_avg[id_pa, id_day]
        situ_avg['pa_track'] = pa_track
        situ_avg['var_track'] = var_track

        # Get final block start time for this window length
        t_max = situ_avg.shape[0] - acf_window_wid
        # Get array of start times for this window and block_step.
        t_start = np.arange(0, t_max, acf_window_step, dtype=np.int)
        # Get array of lags used in ACF (for preallocating space)...
        lags = np.arange(0, acf_opts['n_lags'] + 1.0, 1.0)

        # Loop through the parameters
        for j, var in enumerate(['V', 'var_track']):

            # Update where we are at, as this takes an age.
            print("Computing rolling acf for {} - {}".format(src.upper(), var))

            # preallocate space for the stack of ACFs and significance calcs.
            acf_stack = np.zeros((lags.size, t_start.size))
            sig_stack = np.zeros((lags.size, t_start.size, 2))

            # Loop through the block start times
            for k, t in enumerate(t_start):

                # Pull out this block of data
                data_block = situ_avg.loc[t:t + acf_window_wid].copy()
                # Compute ACF and significance, stash into the stack
                lags, acf, acf_sig = swp.compute_situ_acf(data_block,
                                                          var,
                                                          acf_opts=acf_opts)
                acf_stack[:, k] = acf
                sig_stack[:, k, 0] = acf_sig[0]
                sig_stack[:, k, 1] = acf_sig[1]

            # contour the rolling acf functions
            cntr_h = ax_cft[j].contourf(t_start,
                                        lags,
                                        acf_stack,
                                        norm=norm,
                                        cmap=cmap,
                                        levels=levels)
            # add hatching for significance
            find_sig = ~((acf_stack > sig_stack[:, :, 0]) &
                         (acf_stack < sig_stack[:, :, 1]))
            sig = np.ma.masked_where(find_sig, acf_stack)
            ax_cft[j].pcolor(t_start, lags, sig, hatch='x', alpha=0.0)

    # Format the axes
    for a in ax.ravel():
        a.set_xlim(t_start.min(), t_start.max())
        a.set_ylim(lags.min(), lags.max())

    for src, ax_cft in zip(['wind', 'sta', 'stb'], [ax_wnd, ax_sta, ax_stb]):
        ax_cft[-1].set_xlabel("Block start (days since {})".format(
            ts.datetime.strftime("%Y-%m-%d")))
        for a in ax_cft[:1]:
            a.set_xticklabels([])

    for param, ax_prm in zip(['V', 'HI. Var.'], [ax_situ, ax_remote]):
        ax_prm[0].set_ylabel("Lag (days)")
        for a in ax_prm[1:]:
            a.set_yticklabels([])

    for i, (letter, param) in enumerate(zip(['A', 'B'], ['V', 'HI var.'])):
        for j, crft in enumerate(['WIND', 'STA', 'STB']):
            label = "{}{}) {}-{}".format(letter, j, crft, param)
            ax[i, j].text(0.0275,
                          0.92,
                          label,
                          backgroundcolor='whitesmoke',
                          color='k',
                          transform=ax[i, j].transAxes)

    # Adjust axes position and add a colorbar giving scale of the ACFs
    fig.subplots_adjust(left=0.055,
                        bottom=0.055,
                        right=0.98,
                        top=0.915,
                        hspace=0.03,
                        wspace=0.03)
    cax = fig.add_axes([0.055, 0.92, 0.925, 0.025])
    cax2 = fig.colorbar(cntr_h, cax, orientation='horizontal')
    cax2.ax.xaxis.tick_top()
    cax2.ax.set_xlabel('Spearman Correlaton')
    cax2.ax.xaxis.set_label_position('top')

    # Save the figure
    proj_dirs = swp.project_info()
    out_name = "rolling_acf_new.png"
    out_path = os.path.join(proj_dirs['figs'], out_name)
    fig.savefig(out_path)
    return
Beispiel #8
0
def HI_time_series_acf():
    """
    Plot the time-series of HI1A variability, and the acfs, for all available position angles, and along 2 fixed
    position angles.
    """

    proj_dirs = swp.project_info()
    reduced_hi_data_path = os.path.join(proj_dirs['data'],
                                        "reduced_hi_data_std.pickle")
    with open(reduced_hi_data_path, "rb") as f:
        from_pickle = pickle.load(f)

    time = from_pickle['time'].copy()
    pa_bins = from_pickle['pa_bins'].copy()
    data = from_pickle['data'].copy()
    del from_pickle

    ts = Time("2008-01-01T00:00:00")
    data_z = (data - np.nanmean(data, axis=0)) / np.nanstd(data, axis=0)
    time_avg, data_avg = swp.hi_daily_averaging(time,
                                                pa_bins,
                                                data_z,
                                                method="mean")

    acf_opts = swp.get_acf_opts()
    acf_opts['do_sig'] = True
    acf_opts['iters'] = 1000

    fig, ax, axl, axr = setup_time_series_acf_figure()
    pa_cols = swp.get_pa_colors()

    # Plot out variability for all position angles
    lims = [-1.5, 1.5]
    hi_cmap = plt.cm.PiYG
    hi_cmap.set_bad('k')
    hi_norm = plt.Normalize(vmin=lims[0], vmax=lims[1])
    hi_cax = axl[0].pcolormesh(time_avg.jd,
                               pa_bins,
                               data_avg,
                               norm=hi_norm,
                               cmap=hi_cmap)
    # Compute ACF of this.
    lags, acf, acf_sig = swp.compute_hi_acf(pa_bins,
                                            data_avg,
                                            acf_opts=acf_opts)
    # Contour the ACF.
    cor_cmap = plt.cm.coolwarm
    cor_norm = plt.Normalize(vmin=-1.0, vmax=1.0)
    dl = 0.1
    levels = np.arange(-0.9, 0.9 + dl, dl)
    cor_cax = axr[0].contourf(lags,
                              pa_bins,
                              acf,
                              norm=cor_norm,
                              cmap=cor_cmap,
                              levels=levels)
    # Add hatching of significance
    find_sig = ~((acf > acf_sig[:, :, 0]) & (acf < acf_sig[:, :, 1]))
    hatching = np.ma.masked_where(find_sig, acf)
    axr[0].pcolor(lags, pa_bins, hatching, hatch='x', alpha=0.0)

    # Plot out variability along a fixed position angle
    pa_fix = 90.0
    axl[0].plot(time_avg.jd,
                pa_fix + np.zeros(time_avg.size),
                '--',
                color=pa_cols[0],
                linewidth=2)
    id_pa = np.argmin(np.abs(pa_bins - pa_fix))
    data_avg_fix_pa = data_avg[id_pa, :].copy()
    axl[1].plot(time_avg.jd, data_avg_fix_pa, '-', color=pa_cols[0])
    axr[1].plot(lags, acf[id_pa, :], 'k-')
    axr[1].plot(lags, acf_sig[id_pa, :], 'r--')
    axr[1].plot(lags, acf_sig[id_pa, :], 'r--')

    # Now plot out variability along a PA track similar to a in-situ monitor.
    situ = swp.load_wind_data()
    situ_avg = swp.situ_daily_averaging(situ)
    axl[0].plot(situ_avg['days'],
                situ_avg['pa'],
                '-.',
                color=pa_cols[2],
                linewidth=2)
    # compute variability along this track.
    var_track = np.zeros(situ_avg.shape[0]) * np.NaN
    for i, row in situ_avg.iterrows():
        id_day = np.where(time_avg.jd == row['days'])[0]
        id_pa = np.argmin(np.abs(pa_bins - row['pa']))
        if id_day.size != 0:
            var_track[i] = data_avg[id_pa, id_day]

    axl[2].plot(situ_avg['days'], var_track, '-', color=pa_cols[2])
    # Compute acf of the track variability.
    situ_avg['hi_var'] = var_track
    lags_track, acf_track, acf_track_sig = swp.compute_situ_acf(
        situ_avg, 'hi_var', acf_opts=acf_opts)
    axr[2].plot(lags_track, acf_track, 'k-')
    axr[2].plot(lags_track, acf_track_sig[0], 'r--')
    axr[2].plot(lags_track, acf_track_sig[1], 'r--')

    for al, ar in zip(axl[:2], axr[:2]):
        al.set_xticklabels([])
        ar.set_xticklabels([])

    axl[-1].set_xlabel("Days since {}".format(
        ts.datetime.strftime("%Y-%m-%d")))
    axr[-1].set_xlabel("Lag (days)")

    for a in [axl[0], axr[0]]:
        a.set_ylabel("Position angle (degrees)")
        a.set_ylim(pa_bins.min(), pa_bins.max())

    for al in axl[1:]:
        al.set_ylabel("HI1-A Variability")

    for ar in axr[1:]:
        ar.set_ylabel("Spearman correlation")
        ar.set_ylim(-0.15, 1.0)

    for i, (al, ar) in enumerate(zip(axl, axr)):
        al.set_xlim(time_avg.jd.min(), time_avg.jd.max())
        ar.set_xlim(0, lags.max())

        label = "A{})".format(i + 1)
        al.text(0.01,
                0.9,
                label,
                backgroundcolor="white",
                color='k',
                transform=al.transAxes)

        label = "B{})".format(i + 1)
        ar.text(0.0275,
                0.9,
                label,
                backgroundcolor="white",
                color='k',
                transform=ar.transAxes)

    for ar in axr:
        ar.yaxis.tick_right()
        ar.yaxis.set_label_position("right")

    fig.subplots_adjust(left=0.05,
                        bottom=0.06,
                        right=0.95,
                        top=0.925,
                        wspace=0.03,
                        hspace=0.04)

    # Add in the colorbar
    pos = axl[0].get_position()
    dw = 0.005
    dh = 0.005
    left = pos.x0 + dw
    bottom = pos.y1 + dh
    wid = pos.width - 2 * dw
    hi_cbaxes = fig.add_axes([left, bottom, wid, 0.015])
    cbar1 = fig.colorbar(hi_cax, cax=hi_cbaxes, orientation='horizontal')
    cbar1.ax.set_xlabel("HI1-A Variability")
    cbar1.ax.xaxis.tick_top()
    cbar1.ax.xaxis.set_label_position('top')

    pos = axr[0].get_position()
    dw = 0.005
    dh = 0.005
    left = pos.x0 + dw
    bottom = pos.y1 + dh
    wid = pos.width - 2 * dw

    cor_cbaxes = fig.add_axes([left, bottom, wid, 0.015])
    cbar2 = fig.colorbar(cor_cax, cax=cor_cbaxes, orientation='horizontal')
    cbar2.set_ticks([-0.8, -0.4, 0.0, 0.4, 0.8])
    cbar2.ax.set_xlabel("Spearman correlation")
    cbar2.ax.xaxis.tick_top()
    cbar2.ax.xaxis.set_label_position('top')

    proj_dirs = swp.project_info()
    out_path = os.path.join(proj_dirs['figs'],
                            'remote_sensing_time_series_and_acf.png')
    fig.savefig(out_path)
    return
Beispiel #9
0
def HI_processing_schematic():
    """
    Produces a plot used to illustrate the processing of the HI1a data. To reproduce this exact plot requires
    downloading the HI1a data
    """
    pa_lo = 60
    pa_hi = 120
    dpa = 5.0
    r_lo = 20.0
    r_hi = 22.5

    # Get files for this craft, between time limits
    hi_files = get_hi_files()

    # Split the files into current and previous, for making differenced images
    files_c = hi_files[1:]
    files_p = hi_files[0:-1]

    # Setup position angle bins
    pa_bins = np.arange(pa_lo, pa_hi + dpa, 1.0)
    # Get blank column
    z = np.zeros(len(files_c), dtype=np.float64) * np.NaN
    # Make dict to build the array
    data = {"pa_{:03d}".format(np.int32(pa)): z for pa in pa_bins}
    # Add in time axis
    data['time'] = z

    fig, ax = plt.subplots(2, 2, figsize=(12, 12))
    pa_cols = swp.get_pa_colors()
    std_all = np.zeros((len(files_c), pa_bins.size)) * np.NaN

    # Loop over files, look at stats in shell on the differenced images and fill
    sel_frame = 28
    for i, (fc, fp) in enumerate(zip(files_c, files_p)):

        # Get the map and the image
        himap = hip.get_image_diff(fc, fp, align=True, smoothing=True)
        # Get arrays of pixel coordinates and convert to HPC
        if i == 0:
            x = np.arange(0, himap.dimensions.x.value)
            y = np.arange(0, himap.dimensions.y.value)
            xm, ym = np.meshgrid(x, y)

        coords = himap.pixel_to_world(xm * u.pix, ym * u.pix)
        # Do my conversion to HPR coords, and then convert to plane of sky distance (r = d*tan(elon))
        el, pa = hip.convert_hpc_to_hpr(coords.Tx, coords.Ty)
        r_pos = ((himap.meta['dsun_obs'] * u.m) * np.tan(
            (el.to('rad').value))) / sun.constants.radius

        # Look up pixels in specified POS distance window.
        id_r = (r_pos.value > r_lo) & (r_pos.value < r_hi)

        wid = 512
        y_lo = wid - wid / 2
        y_hi = wid + wid / 2
        x_lo = wid
        xm2 = xm[y_lo:y_hi, x_lo:]
        ym2 = ym[y_lo:y_hi, x_lo:]
        id_r2 = id_r[y_lo:y_hi, x_lo:]

        if i == sel_frame:
            fig_time_stamp = himap.date.strftime("%Y-%m-%dT%H:%M:%S")
            normalise = mpl.colors.Normalize(vmin=-5e-14, vmax=5e-14)
            img = mpl.cm.gray(normalise(himap.data), bytes=True)
            ax[0, 0].imshow(img, origin='lower')
            roi = mpl.patches.Rectangle((x_lo, y_lo),
                                        wid,
                                        wid,
                                        fill=False,
                                        edgecolor='b')
            ax[0, 0].add_patch(roi)
            ax[0, 0].contour(xm2,
                             ym2,
                             id_r2,
                             levels=[0],
                             colors=['r'],
                             linewidths=3,
                             linestyles=['dashed'])

            img = mpl.cm.gray(normalise(himap.data[y_lo:y_hi, x_lo:]),
                              bytes=True)
            ax[0, 1].imshow(img, origin='lower')
            ax[0, 1].contour(xm2 - x_lo,
                             ym2 - y_lo,
                             id_r2,
                             levels=[0],
                             colors=['r'],
                             linewidths=3,
                             linestyles=['dashed'])

        # Preallocate space for the stats in each pa_bin.
        std_arr = np.zeros(pa_bins.shape)
        n_samp_arr = np.zeros(pa_bins.shape)

        for j, pa_b in enumerate(pa_bins):
            # Find this chunk of position angle, and then intersection of the POS and PA windows.
            id_pa = (pa.value > (pa_b - dpa / 2.0)) & (pa.value <
                                                       (pa_b + dpa / 2.0))
            id_block = id_r & id_pa
            id_block2 = id_block[y_lo:y_hi, x_lo:]

            # Get this sample
            sample = himap.data[id_block].ravel()
            sample = sample * 1e12

            std_arr[j] = np.nanstd(sample)
            n_samp_arr[j] = np.sum(np.isfinite(sample))

            # inspect pas at 75, 90, and 105. Plot out the distributions,
            if i == sel_frame:
                pa_sel = [75, 90, 105]
                style = ['--', '-.', '-']
                pa_plt = {
                    pa_sel[i]: {
                        'col': pa_cols[i],
                        'style': style[i]
                    }
                    for i in range(3)
                }

                if pa_b in pa_plt.keys():
                    ax[0, 1].contour(xm2 - x_lo,
                                     ym2 - y_lo,
                                     id_block2,
                                     levels=[0],
                                     colors=[pa_plt[pa_b]['col']],
                                     linewidths=3)

                    kde = st.gaussian_kde(sample)
                    diff_I = np.arange(-0.03, 0.03, 0.0005)
                    pdf = kde.pdf(diff_I)
                    std = np.nanstd(sample)
                    avg = np.nanmean(sample)
                    lo = avg - std
                    hi = avg + std
                    pdf_lo = kde.pdf(lo)
                    pdf_hi = kde.pdf(hi)

                    ax[1, 0].plot(diff_I,
                                  pdf,
                                  color=pa_plt[pa_b]['col'],
                                  linestyle=pa_plt[pa_b]['style'],
                                  label="PA = {}".format(pa_b))
                    ax[1, 0].vlines(lo,
                                    0,
                                    pdf_lo,
                                    linestyle=':',
                                    color=pa_plt[pa_b]['col'])
                    ax[1, 0].vlines(hi,
                                    0,
                                    pdf_hi,
                                    linestyle=':',
                                    color=pa_plt[pa_b]['col'])

        std_arr = (std_arr - np.nanmean(std_arr)) / (np.nanstd(std_arr))
        std_all[i, :] = std_arr
        if i == sel_frame:
            ax[1, 1].plot(pa_bins,
                          std_arr,
                          ".-",
                          color='dimgrey',
                          label='Panel B example',
                          zorder=1)
        else:
            ax[1, 1].plot(pa_bins, std_arr, ".-", color='lightgrey', zorder=0)

    std_avg = np.nanmean(std_all, axis=0)
    std_err = 2 * np.nanstd(std_all, axis=0) / np.sqrt(std_all.shape[0])
    ax[1, 1].errorbar(pa_bins,
                      std_avg,
                      yerr=std_err,
                      fmt="ro",
                      ecolor="r",
                      label='Daily mean',
                      zorder=2)

    ax[0, 0].set_xlim(0, 1024)
    ax[0, 0].set_ylim(0, 1024)

    main_fnt = 15
    sub_fnt = 14
    ax[1, 0].set_xlim(-0.028, 0.028)
    ax[1, 0].set_xlabel("Diff. Image Pixel Intensity (Arb. Unit)",
                        fontsize=main_fnt)
    ax[1, 0].set_ylabel("Kernel Density Estimate", fontsize=main_fnt)

    ax[1, 1].set_xlim(pa_lo, pa_hi)
    ax[1, 1].set_xlabel('PA Bin (degrees)', fontsize=main_fnt)
    ax[1, 1].set_ylabel('Diff. Image variability', fontsize=main_fnt)
    ax[1, 1].yaxis.set_label_position("right")
    ax[1, 1].yaxis.tick_right()

    x = 0.015
    y = 0.96
    ax[0, 0].text(x,
                  y,
                  "A) {}".format(fig_time_stamp),
                  transform=ax[0, 0].transAxes,
                  backgroundcolor='k',
                  color='w',
                  fontsize=sub_fnt)
    ax[0, 1].text(x,
                  y,
                  "B)",
                  transform=ax[0, 1].transAxes,
                  backgroundcolor='k',
                  color='w',
                  fontsize=sub_fnt)
    ax[1, 0].text(x,
                  y,
                  "C)",
                  transform=ax[1, 0].transAxes,
                  color='k',
                  fontsize=sub_fnt)
    ax[1, 1].text(x,
                  y,
                  "D)",
                  transform=ax[1, 1].transAxes,
                  color='k',
                  fontsize=sub_fnt)

    ax[1, 0].legend(fontsize=sub_fnt)
    ax[1, 1].legend(fontsize=sub_fnt)

    for a in ax[1, :]:
        a.tick_params("both", labelsize=sub_fnt)

    for a in ax[0, :]:
        a.set_xticklabels([])
        a.set_yticklabels([])
        a.set_xticks([])
        a.set_yticks([])

    fig.subplots_adjust(left=0.05,
                        bottom=0.05,
                        right=0.95,
                        top=0.95,
                        wspace=0.01,
                        hspace=0.01)
    proj_dirs = swp.project_info()
    out_name = "HI_processing_schematic.png"
    out_path = os.path.join(proj_dirs['figs'], out_name)
    fig.savefig(out_path)
    return