Exemplo n.º 1
0
def find_event_duration(event: datetime, probe: int) -> float:
    """
    Finds the start and end of the event by looking at changes in temperature
    :param event: time and date of reconnection
    :param probe: 1 or 2 for Helios 1 or 2
    :return: duration of the event
    """
    start_analysis = event - timedelta(hours=1)
    imported_data = HeliosData(start_date=start_analysis.strftime('%d/%m/%Y'),
                               start_hour=start_analysis.hour,
                               duration=2,
                               probe=probe)
    imported_data.data.dropna(inplace=True)
    data = imported_data.data.loc[event - timedelta(minutes=4):event +
                                  timedelta(minutes=4)]
    duration = []
    perp_outliers = get_outliers(get_derivative(data['Tp_perp']),
                                 standard_deviations=1.5,
                                 reference='median')
    par_outliers = get_outliers(get_derivative(data['Tp_par']),
                                standard_deviations=1.5,
                                reference='median')
    for n in range(len(perp_outliers)):
        if not np.isnan(perp_outliers[n]) and not np.isnan(par_outliers[n]):
            if event - timedelta(minutes=2) < perp_outliers.index[
                    n] < event + timedelta(minutes=2):
                duration.append(perp_outliers.index[n])
    if len(duration) <= 1:
        event_duration = 2
    else:
        event_duration = (duration[-1] - duration[0]).total_seconds() / 60
        print('DURATION', event_duration)
    return event_duration
Exemplo n.º 2
0
def get_alfven(event: datetime, probe: int) -> float:
    """
    Finds the Alfven speed at the event
    :param event: event whose Alfven speed we want to find
    :param probe: probe corresponding to the event
    :return: Alfven speed
    """
    interval = timedelta(minutes=5)
    start = event - timedelta(hours=2)
    imported_data = HeliosData(start_date=start.strftime('%d/%m/%Y'),
                               start_hour=start.hour,
                               duration=4,
                               probe=probe)
    imported_data.data.dropna(inplace=True)
    L, M, N = hybrid_mva(event,
                         probe,
                         outside_interval=5,
                         inside_interval=1,
                         mva_interval=10)
    _b = (np.array([
        np.mean((imported_data.data.loc[event - interval:event + interval,
                                        'Bx']).values),
        np.mean((imported_data.data.loc[event - interval:event + interval,
                                        'By']).values),
        np.mean((imported_data.data.loc[event - interval:event + interval,
                                        'Bz']).values)
    ]))
    b_l = np.abs(np.dot(_b, L))
    n = np.mean((imported_data.data.loc[event - interval:event + interval,
                                        'n_p']).values)
    alfven_speed = b_l * 10**(-9) / np.sqrt(
        n * 10**6 * 1.67e-27 * np.pi * 4e-7) * 10**(-3)  # we want in km
    return alfven_speed
Exemplo n.º 3
0
def get_probe_data(probe: Union[int, str],
                   start_date: str,
                   start_hour: int = 0,
                   duration: int = 6) -> ImportedData:
    if probe == 1 or probe == 2:
        imported_data = HeliosData(probe=probe,
                                   start_date=start_date,
                                   start_hour=start_hour,
                                   duration=duration)
    elif probe == 'ulysses':
        imported_data = UlyssesData(start_date=start_date,
                                    start_hour=start_hour,
                                    duration=duration)
    elif probe == 'imp_8':
        imported_data = ImpData(start_date=start_date,
                                duration=duration,
                                start_hour=start_hour,
                                probe=probe)
    elif probe == 'ace':
        imported_data = AceData(start_date=start_date,
                                duration=duration,
                                start_hour=start_hour)
    elif probe == 'wind':
        imported_data = WindData(start_date=start_date,
                                 duration=duration,
                                 start_hour=start_hour)
    else:
        raise NotImplementedError(
            'This function has only been implemented for Helios 1, Helios 2, Ulysses, Imp 8, ACE '
            'and Wind so far')
    return imported_data
Exemplo n.º 4
0
def find_density_and_speed(event: datetime,
                           probe: int,
                           distance: bool = False):
    """
    Returns density and speed of the solar wind (and more if distance is True)
    :param event: event date
    :param probe: 1 or 2 for Helios 1 or 2
    :param distance: if True, also returns the distance from the sun
    :return:
    """
    start_analysis = event - timedelta(hours=1)
    imported_data = HeliosData(start_date=start_analysis.strftime('%d/%m/%Y'),
                               start_hour=start_analysis.hour,
                               duration=2,
                               probe=probe)
    imported_data.data.dropna(inplace=True)
    imported_data.create_processed_column('vp_magnitude')
    imported_data.create_processed_column('b_magnitude')
    data = imported_data.data.loc[event - timedelta(minutes=5):event +
                                  timedelta(minutes=5)]
    density = np.mean(data['n_p'].values)
    speed = np.mean(data['vp_magnitude'].values)
    print(event, speed, density, np.mean(data['r_sun'].values))
    if distance:
        return density, speed, np.mean(data['r_sun'].values), np.mean(
            data['Tp_perp'].values), np.mean(data['Tp_par'].values), (
                np.mean(2 * data['Tp_perp'].values) +
                np.mean(data['Tp_par'].values)) / 3, np.mean(
                    data['b_magnitude'])
    else:
        return density, speed
Exemplo n.º 5
0
def get_test_data(known_event: MagneticReconnection, additional_data_padding_hours: tuple = (1, 2)) -> ImportedData:
    """

    :param known_event: MagneticReconnection with a start_datetime
    :param additional_data_padding_hours: (hours_before, hours_after)
    :return: ImportedData around the magnetic reconnection
    """
    start_datetime = known_event.start_datetime - timedelta(hours=additional_data_padding_hours[0])
    start_date = start_datetime.strftime('%d/%m/%Y')
    start_hour = int(start_datetime.strftime('%H'))
    duration_hours = known_event.duration.seconds // (60 * 60) + sum(additional_data_padding_hours)
    test_data = HeliosData(start_date=start_date, start_hour=start_hour, probe=known_event.probe,
                           duration=duration_hours)
    return test_data
Exemplo n.º 6
0
def plot_csv(csv_file_name: str, interval: int = 6):
    """
    Plots the data from a csv file
    :param csv_file_name: name of the file (including the .csv)
    :param interval: duration of the plot
    :return:
    """
    with open(csv_file_name, newline='') as csv_file:
        reader = csv.DictReader(csv_file)
        for row in reader:
            date = datetime(row['year'], row['month'], row['day'], row['hours'], row['minutes'], 0)
            start_of_plot = date - timedelta(hours=interval / 2)
            imported_data = HeliosData(start_date=start_of_plot.strftime('%d/%m/%Y'), start_hour=start_of_plot.hour,
                                       duration=interval)
            plot_imported_data(imported_data)
Exemplo n.º 7
0
def fitness(gene: list, event_list_split: int, finder: BaseFinder):
    """
    Calculates the mcc for a given gene
    :param gene: gene of a given population
    :param event_list_split: number of events that are considered in the mcc calculation
    :param finder: finder to be used in the fitness calculation
    :return: mcc
    """
    # test on random part of the data (avoid over-fitting and allow more iterations of the algorithm in less time)
    events = event_list[:event_list_split]
    f_n, t_n, t_p, f_p = 0, 0, 0, 0
    gene_split = len(
        gene
    ) - 2  # split between the finder test and the lmn test (which takes two arguments)
    for event, probe, reconnection_number in events:
        interval = 3
        start_time = event - timedelta(hours=interval / 2)
        start_hour = event.hour
        data = HeliosData(start_date=start_time.strftime('%d/%m/%Y'),
                          start_hour=start_hour,
                          duration=interval,
                          probe=probe)
        reconnection_corr = finder.find_magnetic_reconnections(
            data, *gene[:gene_split])
        reconnection = test_reconnection_lmn(reconnection_corr, probe,
                                             *gene[gene_split:])

        if reconnection_number == 0:
            if len(reconnection) == 0:
                t_n += 1
            else:
                f_p += len(reconnection)
        else:
            if len(reconnection) < reconnection_number:
                f_n += reconnection_number - len(reconnection)
                t_p += len(reconnection)
            elif len(reconnection) == reconnection_number:
                t_p += len(reconnection)
            else:  # more detected than real
                f_p += len(reconnection) - reconnection_number
                t_p += reconnection_number
    mcc = (t_p * t_n + f_n * f_p) / np.sqrt(
        (t_p + f_p) * (t_p + f_n) * (t_n + f_p) * (t_n + f_n))
    return mcc
Exemplo n.º 8
0
def distances_stats(events_list: List[datetime],
                    probe: int,
                    only_stats: bool = True) -> dict:
    """
    :param events_list: list of reconnection events
    :param probe: 1 or 2 for Helios 1 or 2
    :param only_stats: if True, only returns the number of events per distance, if False, also returns the dates
    :return: number of reconnection events at given distances from the sun
    """
    times_and_radii = {}
    for key in radii_names:
        times_and_radii[key] = []
    for event in events_list:
        start_time = event
        imported_data = HeliosData(start_date=start_time.strftime('%d/%m/%Y'),
                                   start_hour=start_time.hour,
                                   duration=1,
                                   probe=probe)
        try:
            radius = imported_data.data['r_sun'].loc[event]
        except ValueError:
            radius = np.mean(imported_data.data['r_sun'].values)
            print('exception in finding the radius')
        for n in range(len(radii_divisions)):
            radius_division = radii_divisions[len(radii_divisions) - n - 1]
            if radius > radius_division:
                radius_type = radii_names[len(radii_divisions) - n - 1]
                times_and_radii[radius_type].append([event, radius])
                break
    for key in times_and_radii.keys():
        if only_stats:
            times_and_radii[key] = len(times_and_radii[key])
        else:
            times_and_radii[key].append(str(len(times_and_radii[key])))
    times_and_radii['total number of reconnection events'] = len(events_list)
    pprint.pprint(times_and_radii)
    return times_and_radii
Exemplo n.º 9
0
def get_events_relations(
    helios1_events: List[datetime],
    helios2_events: List[datetime],
    orbiter_helios1: spice.Trajectory,
    orbiter_helios2: spice.Trajectory,
    allowed_error: float = 0.2
) -> List[List[Union[Union[datetime, int], Any]]]:
    """
    Checks whether two events might be the same by calculating the expected time taken by the solar wind to travel
    between them
    :param helios1_events: events detected by Helios 1
    :param helios2_events: events detected by Helios 2
    :param orbiter_helios1: Helios 1 orbiter
    :param orbiter_helios2: Helios 2 orbiter
    :param allowed_error: allowed percentage error between the theoretical and actual time intervals
    :return: possible pair of events with associated probes and the distance between them
    """
    same_events = []
    _helios1_events = []
    for event in helios1_events:
        if datetime(1976, 1, 20) < event < datetime(1979, 10, 1):
            _helios1_events.append(event)
    helios1_events = _helios1_events
    for event_helios1 in helios1_events:
        for event_helios2 in helios2_events:
            if event_helios1 < event_helios2:
                start, end = event_helios1, event_helios2
                probe_start, probe_end = 1, 2
                orbiter_start, orbiter_end = orbiter_helios1, orbiter_helios2
            else:
                start, end = event_helios2, event_helios1
                probe_start, probe_end = 2, 1
                orbiter_start, orbiter_end = orbiter_helios2, orbiter_helios1

            if (end - start).total_seconds(
            ) > 864000:  # not the same after 10 days (supposed to die out in 1/2 days)
                continue
            else:
                imported_data_start = HeliosData(
                    start_date=start.strftime('%d/%m/%Y'),
                    start_hour=start.hour,
                    probe=probe_start,
                    duration=20)
                _end = end - timedelta(hours=20)
                imported_data_end = HeliosData(
                    start_date=_end.strftime('%d/%m/%Y'),
                    start_hour=_end.hour,
                    probe=probe_end,
                    duration=20)
                imported_data_start.data.dropna(inplace=True)
                imported_data_end.data.dropna(inplace=True)
                imported_data_start.create_processed_column('vp_magnitude')
                imported_data_end.create_processed_column('vp_magnitude')
                speed_start = np.mean(
                    imported_data_start.data['vp_magnitude'].values)
                speed_end = np.mean(
                    imported_data_end.data['vp_magnitude'].values)
                speed = (speed_start + speed_end) / 2
                speed += (get_alfven(start, probe_start) +
                          get_alfven(end, probe_end)) / 2

                start_position = orbiter_start.times.index(
                    datetime(start.year, start.month, start.day))
                end_position = orbiter_end.times.index(
                    datetime(end.year, end.month, end.day))

                start_x, start_y, start_z = orbiter_start.x[start_position].to(
                    u.km) / u.km, orbiter_start.y[start_position].to(
                        u.km) / u.km, orbiter_start.z[start_position].to(
                            u.km) / u.km
                end_x, end_y, end_z = orbiter_end.x[end_position].to(
                    u.km) / u.km, orbiter_end.y[end_position].to(
                        u.km) / u.km, orbiter_end.z[end_position].to(
                            u.km) / u.km

                probes_separation = np.sqrt((start_x - end_x)**2 +
                                            (start_y - end_y)**2 +
                                            (start_z - end_z)**2)
                time_between_events = (end - start).total_seconds()
                expected_time = probes_separation / speed

                if 1 - allowed_error < time_between_events / expected_time < 1 + allowed_error:
                    print(
                        np.abs(orbiter_start.x[start_position] -
                               orbiter_end.x[end_position]),
                        np.abs(orbiter_start.y[start_position] -
                               orbiter_end.y[end_position]),
                        np.abs(orbiter_start.z[start_position] -
                               orbiter_end.z[end_position]))
                    print(time_between_events / expected_time)
                    print('expected ',
                          start + timedelta(seconds=int(expected_time)),
                          ' but got ', end, 'starting with probe ',
                          probe_start, start, 'and ending with ', probe_end,
                          end)
                    same_events.append([
                        start, probe_start, end, probe_end, probes_separation
                    ])

    return same_events
Exemplo n.º 10
0
def find_directions(event1: datetime,
                    event2: datetime,
                    probe1: int,
                    probe2: int,
                    allowed_error=0.2) -> List[Union[datetime, int]]:
    """
    Checks whether the solar wind could have travelled between the two probes by finding the distances between
    the probes in SSE and comparing them to the distance traveled by the solar wind
    :param event1: first event to happen
    :param event2: second event to happen
    :param probe1: probe corresponding to the first event
    :param probe2: probe corresponding to the second event
    :param allowed_error: allowed percentage error in the distance difference between the two obtained distances
    :return: possible pair of events with associated probes
    """
    data1 = HeliosData(start_date=event1.strftime('%d/%m/%Y'),
                       duration=24,
                       probe=probe1)
    data2 = HeliosData(start_date=event2.strftime('%d/%m/%Y'),
                       duration=24,
                       probe=probe2)
    data1.data.dropna(inplace=True)
    data2.data.dropna(inplace=True)

    times = orbit_times_generator(start_date='20/01/1976',
                                  end_date='01/10/1979')
    orbiter1_sse = kernel_loader(probe1)
    orbit_generator(orbiter1_sse,
                    times,
                    observing_body='Earth',
                    frame='SSE',
                    probe=probe1)
    orbiter2_sse = kernel_loader(probe2)
    orbit_generator(orbiter2_sse,
                    times,
                    observing_body='Earth',
                    frame='SSE',
                    probe=probe2)

    index1 = orbiter1_sse.times.index(
        datetime(event1.year, event1.month, event1.day))
    index2 = orbiter2_sse.times.index(
        datetime(event2.year, event2.month, event2.day))
    x_orb = (orbiter2_sse.x[index2] - orbiter1_sse.x[index1]).to(
        u.km) / u.km * 6.68459e-9
    y_orb = (orbiter2_sse.y[index2] - orbiter1_sse.y[index1]).to(
        u.km) / u.km * 6.68459e-9
    z_orb = (orbiter2_sse.z[index2] - orbiter1_sse.z[index1]).to(
        u.km) / u.km * 6.68459e-9

    time_between_events = (event2 - event1).total_seconds()
    v = np.array([
        np.mean(data1.data['vp_x'].values),
        np.mean(data1.data['vp_y'].values),
        np.mean(data1.data['vp_z'].values)
    ])
    interval = timedelta(minutes=2)
    radius = data2.data.loc[event2:event2 + interval,
                            'r_sun'][0] - data1.data.loc[event1:event1 +
                                                         interval, 'r_sun'][0]
    x_dist = time_between_events * v[0] * 6.68459e-9
    y_dist = time_between_events * v[1] * 6.68459e-9
    z_dist = time_between_events * v[2] * 6.68459e-9

    print(np.sqrt(x_orb**2 + y_orb**2 + z_orb**2))
    print(x_orb, y_orb, z_orb)
    print(x_dist, y_dist, z_dist)

    if radius > 0:
        if 1 - allowed_error < np.abs(x_orb / x_dist) < 1 + allowed_error:
            return [event1, event2, probe1, probe2]