Ejemplo n.º 1
0
    def __init__(self, w_s, w_u, u_section, round_order_connection):

        # orbit_idx = []
        # for l_point, orbit_type in [(l_point_1, orbit_type_1), (l_point_2, orbit_type_2)]
        #     df = load_initial_conditions_incl_M('../../data/raw/' + l_point + '_' + orbit_type + '_initial_conditions.txt')
        #     orbit_idx.append(df[abs(df[0] - C) == (abs(df[0] - C)).min()].index)

        l_point, orbit_type, orbit_id, w, s, sign = w_s.split('_')
        self.C = [
            load_initial_conditions_incl_M('../../data/raw/' + l_point + '_' +
                                           orbit_type +
                                           '_initial_conditions.txt').xs(
                                               int(orbit_id))[0]
        ]
        l_point, orbit_type, orbit_id, w, s, sign = w_u.split('_')
        self.C.append(
            load_initial_conditions_incl_M('../../data/raw/' + l_point + '_' +
                                           orbit_type +
                                           '_initial_conditions.txt').xs(
                                               int(orbit_id))[0])

        self.WS = load_manifold('../../data/raw/' + w_s + '.txt')
        self.WU = load_manifold('../../data/raw/' + w_u + '.txt')
        self.numberOfOrbitsPerManifold = len(
            set(self.WS.index.get_level_values(0)))
        self.U_section = u_section
        self.roundOrderConnection = round_order_connection
        # Select last entry of manifolds
        ls_s = []
        ls_u = []

        for i in range(len(set(self.WS.index.get_level_values(0)))):
            ls_s.append(self.WS.xs(i).tail(1))
            ls_u.append(self.WU.xs(i).tail(1))

        self.poincareWS = pd.concat(ls_s).reset_index(drop=True)
        self.poincareWU = pd.concat(ls_u).reset_index(drop=True)

        self.figSize = (40, 40)
        self.titleSize = 20
        self.suptitleSize = 30

        EARTH_GRAVITATIONAL_PARAMETER = 3.986004418E14
        SUN_GRAVITATIONAL_PARAMETER = 1.32712440018e20
        MOON_GRAVITATIONAL_PARAMETER = SUN_GRAVITATIONAL_PARAMETER / (
            328900.56 * (1.0 + 81.30059))
        self.massParameter = MOON_GRAVITATIONAL_PARAMETER / (
            MOON_GRAVITATIONAL_PARAMETER + EARTH_GRAVITATIONAL_PARAMETER)
        pass
def findIdxCorrespondingToC(c_level):
    # Find index of orbit which is closest to the desired Jacobi energy C

    orbit_types = ['horizontal', 'halo', 'vertical']
    lagrange_point_nrs = [1, 2]

    print('Index for orbit closest to C = ' + str(c_level) + '\n')

    for idx, orbit_type in enumerate(orbit_types):
        for lagrange_point_nr in lagrange_point_nrs:
            initial_conditions_file_path = '../../data/raw/orbits/L' + str(
                lagrange_point_nr
            ) + '_' + orbit_type + '_initial_conditions.txt'
            initial_conditions_incl_m_df = load_initial_conditions_incl_M(
                initial_conditions_file_path)

            if (initial_conditions_incl_m_df[
                    initial_conditions_incl_m_df[0] == c_level -
                    min(abs(initial_conditions_incl_m_df[0] -
                            c_level))]).empty:
                row = initial_conditions_incl_m_df[
                    initial_conditions_incl_m_df[0] == c_level +
                    min(abs(initial_conditions_incl_m_df[0] - c_level))]
            else:
                row = initial_conditions_incl_m_df[
                    initial_conditions_incl_m_df[0] == c_level -
                    min(abs(initial_conditions_incl_m_df[0] - c_level))]

            print('L' + str(lagrange_point_nr) + ' ' + orbit_type +
                  ' at index: ' + str(row.index[0]) + ' (dC = |' +
                  str(abs(row[0].values[0] - c_level)) + '|)')
    pass
Ejemplo n.º 3
0
    def plot_2d_shooting_conditions(self):
        fig = plt.figure(figsize=self.figSize)
        ax = fig.gca()

        orbit_types = ['horizontal', 'vertical', 'halo']
        lagrange_point_nrs = [1, 2]

        x = []
        z = []
        ydot = []
        c = []
        for idx, orbit_type in enumerate(orbit_types):
            for lagrange_point_nr in lagrange_point_nrs:
                initial_conditions_file_path = '../../data/raw/orbits/L' + str(
                    lagrange_point_nr) + '_' + orbit_type + '_initial_conditions.txt'
                initial_conditions_incl_m_df = load_initial_conditions_incl_M(initial_conditions_file_path)

                plot_label = orbit_type.capitalize()
                if plot_label == 'Horizontal' or plot_label == 'Vertical':
                    plot_label += ' Lyapunov'

                x.extend(list(initial_conditions_incl_m_df[2].values))
                z.extend(list(initial_conditions_incl_m_df[4].values))
                c.extend(list(initial_conditions_incl_m_df[0].values))

        sc = ax.scatter(x, z, c=c, cmap='viridis', s=20)
        cb = plt.colorbar(sc)
        cb.set_label('$C \enskip [-]$')

        lagrange_points_df = load_lagrange_points_location()
        lagrange_point_nrs = ['L1', 'L2']
        # Lagrange points and bodies
        for lagrange_point_nr in lagrange_point_nrs:
            ax.scatter(lagrange_points_df[lagrange_point_nr]['x'], lagrange_points_df[lagrange_point_nr]['z'], color='black', marker='x')

        bodies_df = load_bodies_location()
        u = np.linspace(0, 2 * np.pi, 100)
        v = np.linspace(0, np.pi, 100)
        for body in bodies_df:
            x = bodies_df[body]['r'] * np.outer(np.cos(u), np.sin(v)) + bodies_df[body]['x']
            y = bodies_df[body]['r'] * np.outer(np.sin(u), np.sin(v))
            z = bodies_df[body]['r'] * np.outer(np.ones(np.size(u)), np.cos(v))
            ax.contourf(x, z, y, colors='black')

        ax.legend(frameon=True, loc='upper right')
        ax.set_xlabel('x [-]')
        ax.set_ylabel('z [-]')
        ax.grid(True, which='both', ls=':')
        fig.tight_layout()
        fig.subplots_adjust(top=0.9)
        plt.suptitle('$L_1, L_2$ - Shooting conditions for H-L, halo, and V-L', size=self.suptitleSize)
        if self.lowDPI:
            fig.savefig('../../data/figures/orbits/orbit_shooting_conditions_2d.png', transparent=True, dpi=self.dpi)
        else:
            fig.savefig('../../data/figures/orbits/orbit_shooting_conditions_2d.pdf', transparent=True)
        pass
Ejemplo n.º 4
0
    def plot_3d_shooting_conditions(self):
        fig = plt.figure(figsize=self.figSize)
        ax = fig.gca(projection='3d')

        orbit_types = ['horizontal', 'vertical', 'halo']
        lagrange_point_nrs = [1, 2]

        lines = []
        linewidth = 2
        for lagrange_point_nr in lagrange_point_nrs:
            for idx, orbit_type in enumerate(orbit_types):
                initial_conditions_file_path = '../../data/raw/orbits/L' + str(
                    lagrange_point_nr) + '_' + orbit_type + '_initial_conditions.txt'
                initial_conditions_incl_m_df = load_initial_conditions_incl_M(initial_conditions_file_path)

                plot_label = orbit_type.capitalize()
                if plot_label == 'Horizontal' or plot_label == 'Vertical':
                    plot_label += ' Lyapunov'

                line, = ax.plot(initial_conditions_incl_m_df[2].values, initial_conditions_incl_m_df[6].values,
                                initial_conditions_incl_m_df[4].values, label=plot_label, linewidth=linewidth,
                                color=self.plottingColors['tripleLine'][idx])
                lines.append(line)

        lagrange_points_df = load_lagrange_points_location()
        lagrange_point_nrs = ['L1', 'L2']
        # Lagrange points and bodies
        for lagrange_point_nr in lagrange_point_nrs:
            ax.scatter(lagrange_points_df[lagrange_point_nr]['x'], lagrange_points_df[lagrange_point_nr]['z'],
                       color='black', marker='x')

        bodies_df = load_bodies_location()
        u = np.linspace(0, 2 * np.pi, 100)
        v = np.linspace(0, np.pi, 100)
        for body in bodies_df:
            x = bodies_df[body]['r'] * np.outer(np.cos(u), np.sin(v)) + bodies_df[body]['x']
            y = bodies_df[body]['r'] * np.outer(np.sin(u), np.sin(v))
            z = bodies_df[body]['r'] * np.outer(np.ones(np.size(u)), np.cos(v))
            ax.plot_surface(x, y, z, color='black')


        # print(ax.elev)
        # print(ax.azim)
        # ax.view_init(20, -75)
        plt.plot(ax.get_xlim(), [0, 0], 'black', linewidth=0.5)
        ax.legend(frameon=True, loc='upper right', handles=lines[:3])
        ax.set_xlabel('x [-]')
        ax.set_ylabel('$\dot{y}$ [-]')
        ax.set_zlabel('z [-]')
        ax.grid(True, which='both', ls=':')
        fig.tight_layout()
        fig.subplots_adjust(top=0.9)
        plt.suptitle('$L_1, L_2$ - Shooting conditions', size=self.suptitleSize)
        fig.savefig('../../data/figures/orbits/orbit_shooting_conditions_3d.pdf', transparent=True)
        pass
    def __init__(self, orbit_type, lagrange_point_nr, orbit_id_per_c):
        print('=======================')
        print(str(orbit_type) + ' in L' + str(lagrange_point_nr))
        print('=======================')
        self.orbitType = orbit_type
        self.orbitIdPerC = orbit_id_per_c

        self.orbitTypeForTitle = orbit_type.capitalize()
        if (self.orbitTypeForTitle == 'Horizontal') or (self.orbitTypeForTitle
                                                        == 'Vertical'):
            self.orbitTypeForTitle += ' Lyapunov'

        self.lagrangePointNr = lagrange_point_nr

        EARTH_GRAVITATIONAL_PARAMETER = 3.986004418E14
        SUN_GRAVITATIONAL_PARAMETER = 1.32712440018e20
        MOON_GRAVITATIONAL_PARAMETER = SUN_GRAVITATIONAL_PARAMETER / (
            328900.56 * (1.0 + 81.30059))
        self.massParameter = MOON_GRAVITATIONAL_PARAMETER / (
            MOON_GRAVITATIONAL_PARAMETER + EARTH_GRAVITATIONAL_PARAMETER)

        initial_conditions_file_path = '../../data/raw/orbits/L' + str(
            lagrange_point_nr) + '_' + orbit_type + '_initial_conditions.txt'
        initial_conditions_incl_m_df = load_initial_conditions_incl_M(
            initial_conditions_file_path)

        self.C = []
        self.orbitDf = []
        self.W_S_plus = []
        self.W_S_min = []
        self.W_U_plus = []
        self.W_U_min = []

        for c_level in reversed(sorted(orbit_id_per_c)):
            orbit_id = orbit_id_per_c[c_level]
            # self.C.append(initial_conditions_incl_m_df.iloc[orbit_id][0])
            self.orbitDf.append(
                load_orbit('../../data/raw/orbits/refined_for_c/L' +
                           str(lagrange_point_nr) + '_' + orbit_type + '_' +
                           str(orbit_id) + '.txt'))

            self.C.append(
                computeJacobiEnergy(self.orbitDf[-1].iloc[0]['x'],
                                    self.orbitDf[-1].iloc[0]['y'],
                                    self.orbitDf[-1].iloc[0]['z'],
                                    self.orbitDf[-1].iloc[0]['xdot'],
                                    self.orbitDf[-1].iloc[0]['ydot'],
                                    self.orbitDf[-1].iloc[0]['zdot']))

            self.W_S_plus.append(
                load_manifold_refactored(
                    '../../data/raw/manifolds/refined_for_c/L' +
                    str(lagrange_point_nr) + '_' + orbit_type + '_' +
                    str(orbit_id) + '_W_S_plus.txt'))
            self.W_S_min.append(
                load_manifold_refactored(
                    '../../data/raw/manifolds/refined_for_c/L' +
                    str(lagrange_point_nr) + '_' + orbit_type + '_' +
                    str(orbit_id) + '_W_S_min.txt'))
            self.W_U_plus.append(
                load_manifold_refactored(
                    '../../data/raw/manifolds/refined_for_c/L' +
                    str(lagrange_point_nr) + '_' + orbit_type + '_' +
                    str(orbit_id) + '_W_U_plus.txt'))
            self.W_U_min.append(
                load_manifold_refactored(
                    '../../data/raw/manifolds/refined_for_c/L' +
                    str(lagrange_point_nr) + '_' + orbit_type + '_' +
                    str(orbit_id) + '_W_U_min.txt'))

        self.numberOfOrbitsPerManifold = len(
            set(self.W_S_plus[0].index.get_level_values(0)))

        self.figSize = (7 * (1 + np.sqrt(5)) / 2, 7 * 2)
        blues = sns.color_palette('Blues', 100)
        greens = sns.color_palette('BuGn', 100)
        self.colorPaletteStable = sns.dark_palette(
            'green', n_colors=self.numberOfOrbitsPerManifold)
        self.colorPaletteUnstable = sns.dark_palette(
            'red', n_colors=self.numberOfOrbitsPerManifold)

        self.plottingColors = {
            'lambda1': blues[40],
            'lambda2': greens[50],
            'lambda3': blues[90],
            'lambda4': blues[90],
            'lambda5': greens[70],
            'lambda6': blues[60],
            'singleLine': blues[80],
            'doubleLine': [greens[50], blues[80]],
            'tripleLine': [blues[40], greens[50], blues[80]],
            'W_S_plus': self.colorPaletteStable[90],
            'W_S_min': self.colorPaletteStable[40],
            'W_U_plus': self.colorPaletteUnstable[90],
            'W_U_min': self.colorPaletteUnstable[40],
            'limit': 'black',
            'orbit': 'navy'
        }
        self.suptitleSize = 20

        pass
Ejemplo n.º 6
0
    def __init__(self, libration_point_nr):
        self.suptitleSize = 44
        self.timeTextSize = 33

        axis_bounds = 0.1 * libration_point_nr
        libration_point_df = load_lagrange_points_location()
        libration_point_x_loc = libration_point_df[
            'L' + str(libration_point_nr)]['x']

        self.xLim = [0.8, 1.2]
        self.yLim = [-0.5, 0.5]
        self.zLim = [-0.5, 0.5]

        # self.xLim = [libration_point_x_loc - axis_bounds, libration_point_x_loc + axis_bounds]
        # self.yLim = [-axis_bounds, axis_bounds]
        # self.zLim = self.yLim
        self.orbitAlpha = 0.8
        self.orbitLinewidth = 2
        self.lagrangePointMarkerSize = 300
        self.orbitColor = 'gray'
        self.librationPointNr = libration_point_nr
        self.lines = []
        self.horizontalLyapunov = []
        self.jacobiEnergyText = ''  # Will become a plt.text-object
        self.jacobiEnergyHorizontalLyapunov = []
        self.jacobiEnergyAxial = []
        self.jacobiEnergyVerticalLyapunov = []
        self.orderOfLinearInstabilityHorizontalLyapunov = []
        self.orderOfLinearInstabilityVerticalLyapunov = []
        self.orbitIdBifurcationsFromHorizontalLyapunov = []
        self.orbitIdBifurcationsFromVerticalLyapunov = []

        # Determine the index for bifurcation for horizontal family
        initial_conditions_incl_m_df = load_initial_conditions_incl_M(
            '../../../data/raw/orbits/L' + str(self.librationPointNr) +
            '_horizontal_initial_conditions.txt')
        for row in initial_conditions_incl_m_df.iterrows():
            self.jacobiEnergyHorizontalLyapunov.append(row[1][0])

            M = np.matrix([
                list(row[1][8:14]),
                list(row[1][14:20]),
                list(row[1][20:26]),
                list(row[1][26:32]),
                list(row[1][32:38]),
                list(row[1][38:44])
            ])
            eigenvalue = np.linalg.eigvals(M)

            # Determine order of linear instability
            reduction = 0
            for i in range(6):
                if (abs(eigenvalue[i]) - 1.0) < 1e-2:
                    reduction += 1

            if len(self.orderOfLinearInstabilityHorizontalLyapunov) > 0:
                # Check for a bifurcation, when the order of linear instability changes
                if (6 - reduction
                    ) != self.orderOfLinearInstabilityHorizontalLyapunov[-1]:
                    self.orbitIdBifurcationsFromHorizontalLyapunov.append(
                        row[0])
            self.orderOfLinearInstabilityHorizontalLyapunov.append(6 -
                                                                   reduction)

        print('Index for bifurcations from horizontal Lyapunov family: ')
        print(self.orbitIdBifurcationsFromHorizontalLyapunov)

        # Select the indices to be plotted for the horizontal Lyapunov family (please remember that the bifurcation to the axial family corresponds to the second bifurcation of the horizontal Lyapunov family)
        self.horizontalLyapunovIndices = list(
            range(0, self.orbitIdBifurcationsFromHorizontalLyapunov[1]))
        self.horizontalLyapunovIndices.append(
            self.orbitIdBifurcationsFromHorizontalLyapunov[1])

        # Save jacobi energy values for the axial family
        initial_conditions_file_path = '../../../data/raw/orbits/L' + str(
            self.librationPointNr) + '_axial_initial_conditions.txt'
        initial_conditions_incl_m_df = load_initial_conditions_incl_M(
            initial_conditions_file_path)
        for row in initial_conditions_incl_m_df.iterrows():
            self.jacobiEnergyAxial.append(row[1][0])
        self.numberOfAxialOrbits = len(self.jacobiEnergyAxial)

        # Determine the index for bifurcation for vertical family
        initial_conditions_incl_m_df = load_initial_conditions_incl_M(
            '../../../data/raw/orbits/L' + str(self.librationPointNr) +
            '_vertical_initial_conditions.txt')
        for row in initial_conditions_incl_m_df.iterrows():
            self.jacobiEnergyVerticalLyapunov.append(row[1][0])

            M = np.matrix([
                list(row[1][8:14]),
                list(row[1][14:20]),
                list(row[1][20:26]),
                list(row[1][26:32]),
                list(row[1][32:38]),
                list(row[1][38:44])
            ])
            eigenvalue = np.linalg.eigvals(M)

            # Determine order of linear instability
            reduction = 0
            for i in range(6):
                if (abs(eigenvalue[i]) - 1.0) < 1e-2:
                    reduction += 1

            if len(self.orderOfLinearInstabilityVerticalLyapunov) > 0:
                # Check for a bifurcation, when the order of linear instability changes
                if (6 - reduction
                    ) != self.orderOfLinearInstabilityVerticalLyapunov[-1]:
                    self.orbitIdBifurcationsFromVerticalLyapunov.append(row[0])
            self.orderOfLinearInstabilityVerticalLyapunov.append(6 - reduction)

        print('Index for bifurcations from vertical Lyapunov family: ')
        print(self.orbitIdBifurcationsFromVerticalLyapunov)

        # Select the indices to be plotted for the vertical Lyapunov family (please remember that the bifurcation to the axial family corresponds to the first bifurcation of the vertical Lyapunov family)
        self.verticalLyapunovIndices = list(
            range(self.orbitIdBifurcationsFromVerticalLyapunov[0],
                  len(self.jacobiEnergyVerticalLyapunov)))
        pass
    lines[2].set_data(vertical_L1[i]['x'].values, vertical_L1[i]['y'].values)
    lines[2].set_3d_properties(vertical_L1[i]['z'].values)
    lines[3].set_data(vertical_L2[i]['x'].values, vertical_L2[i]['y'].values)
    lines[3].set_3d_properties(vertical_L2[i]['z'].values)
    lines[4].set_data(halo_L1[i]['x'].values, halo_L1[i]['y'].values)
    lines[4].set_3d_properties(halo_L1[i]['z'].values)
    lines[5].set_data(halo_L2[i]['x'].values, halo_L2[i]['y'].values)
    lines[5].set_3d_properties(halo_L2[i]['z'].values)
    # fig.suptitle('C = ' + str(np.round(initial_conditions_vertical_L1.iloc[i][1], 2)), size=30)
    return lines


orbit_type = 'halo'

# Load data
initial_conditions_horizontal_L1 = load_initial_conditions_incl_M(
    '../data/raw/horizontal_L1_initial_conditions.txt')
initial_conditions_horizontal_L2 = load_initial_conditions_incl_M(
    '../data/raw/horizontal_L2_initial_conditions.txt')
initial_conditions_vertical_L1 = load_initial_conditions_incl_M(
    '../data/raw/vertical_L1_initial_conditions.txt')
initial_conditions_vertical_L2 = load_initial_conditions_incl_M(
    '../data/raw/vertical_L2_initial_conditions.txt')
initial_conditions_halo_L1 = load_initial_conditions_incl_M(
    '../data/raw/halo_L1_initial_conditions.txt')
initial_conditions_halo_L2 = load_initial_conditions_incl_M(
    '../data/raw/halo_L2_initial_conditions.txt')

horizontal_L1 = []
horizontal_L2 = []
vertical_L1 = []
vertical_L2 = []
        sns.color_palette("viridis", n_colors)[0],
        sns.color_palette("viridis", n_colors)[n_colors - 1],
        sns.color_palette("viridis", n_colors)[int((n_colors - 1) / 2)]
    ],
    'limit':
    'black'
}

fig = plt.figure(figsize=(7 * (1 + np.sqrt(5)) / 2, 3.5))
ax = fig.gca()
for lagrange_point_nr in lagrange_point_nrs:
    for idx, orbit_type in enumerate(orbit_types):

        initial_conditions_file_path = '../../data/raw/orbits/L' + str(
            lagrange_point_nr) + '_' + orbit_type + '_initial_conditions.txt'
        initial_conditions_incl_m_df = load_initial_conditions_incl_M(
            initial_conditions_file_path)

        plot_label = orbit_type.capitalize()
        if plot_label == 'Horizontal' or plot_label == 'Vertical':
            plot_label += ' Lyapunov'

        if lagrange_point_nr == 1:
            linestyle = '-'
        else:
            linestyle = '--'

        ax.plot(initial_conditions_incl_m_df[1].values,
                initial_conditions_incl_m_df[0].values,
                label='$L_' + str(lagrange_point_nr) + '$ ' + plot_label,
                linestyle=linestyle,
                color=plottingColors['tripleLine'][idx])
Ejemplo n.º 9
0
    def __init__(self, orbit_type, lagrange_point_nr):
        self.C = []
        self.T = []
        self.x = []
        self.X = []
        self.delta_r = []
        self.delta_v = []
        self.delta_x = []
        self.delta_y = []
        self.delta_z = []
        self.delta_x_dot = []
        self.delta_y_dot = []
        self.delta_z_dot = []

        self.numberOfIterations = []
        self.C_half_period = []
        self.T_half_period = []
        self.X_half_period = []

        self.eigenvalues = []
        self.D = []
        self.orderOfLinearInstability = []
        self.orbitIdBifurcations = []
        self.lambda1 = []
        self.lambda2 = []
        self.lambda3 = []
        self.lambda4 = []
        self.lambda5 = []
        self.lambda6 = []
        self.v1 = []
        self.v2 = []
        self.v3 = []

        self.lagrangePointNr = lagrange_point_nr

        print('=======================')
        print(str(orbit_type) + ' in L' + str(lagrange_point_nr))
        print('=======================')

        self.orbitType = orbit_type
        self.orbitTypeForTitle = orbit_type.capitalize()
        if self.orbitTypeForTitle == 'Horizontal' or self.orbitTypeForTitle == 'Vertical':
            self.orbitTypeForTitle += ' Lyapunov'

        initial_conditions_file_path = '../../data/raw/orbits/extended/L' + str(lagrange_point_nr) + '_' \
                                       + orbit_type + '_initial_conditions.txt'
        initial_conditions_incl_m_df = load_initial_conditions_incl_M(
            initial_conditions_file_path)

        differential_correction_file_path = '../../data/raw/orbits/extended/L' + str(lagrange_point_nr) + '_' \
                                            + orbit_type + '_differential_correction.txt'
        differential_correction_df = load_differential_corrections(
            differential_correction_file_path)
        # Fix for extended v-l
        self.indexNanEntries = pd.isnull(initial_conditions_incl_m_df).any(
            1).nonzero()[0]
        print(self.indexNanEntries)

        initial_conditions_incl_m_df.dropna(axis=0, how='any', inplace=True)
        differential_correction_df.drop(
            differential_correction_df.index[self.indexNanEntries],
            inplace=True)

        for row in differential_correction_df.iterrows():
            self.numberOfIterations.append(row[1][0])
            self.C_half_period.append(row[1][1])
            self.T_half_period.append(row[1][2])
            self.X_half_period.append(np.array(row[1][3:9]))

        self.maxEigenvalueDeviation = 1.0e-3  # Changed from 1e-3

        for row in initial_conditions_incl_m_df.iterrows():
            self.C.append(row[1][0])
            self.T.append(row[1][1])
            self.x.append(row[1][2])
            self.X.append(np.array(row[1][2:8]))

            # self.X.append(np.array(row[1][3:9]))
            M = np.matrix([
                list(row[1][8:14]),
                list(row[1][14:20]),
                list(row[1][20:26]),
                list(row[1][26:32]),
                list(row[1][32:38]),
                list(row[1][38:44])
            ])

            eigenvalue = np.linalg.eigvals(M)
            print(str(row[0]) + ' at x-loc: ' + str(row[1][2]))

            sorting_indices = [-1, -1, -1, -1, -1, -1]
            idx_real_one = []
            # Find indices of the first pair of real eigenvalue equal to one
            for idx, l in enumerate(eigenvalue):
                if abs(l.imag) < self.maxEigenvalueDeviation:
                    if abs(l.real - 1.0) < self.maxEigenvalueDeviation:
                        if sorting_indices[2] == -1:
                            sorting_indices[2] = idx
                            idx_real_one.append(idx)
                        elif sorting_indices[3] == -1:
                            sorting_indices[3] = idx
                            idx_real_one.append(idx)

            # Find indices of the pair of largest/smallest real eigenvalue (corresponding to the unstable/stable subspace)
            for idx, l in enumerate(eigenvalue):
                if idx == (sorting_indices[2] or sorting_indices[3]):
                    continue
                if abs(l.imag) < self.maxEigenvalueDeviation:
                    if abs(l.real) == max(abs(eigenvalue.real)):
                        sorting_indices[0] = idx
                    elif abs(abs(l.real) - 1.0 / max(abs(eigenvalue.real))
                             ) < self.maxEigenvalueDeviation:
                        sorting_indices[5] = idx

            missing_indices = sorted(
                list(set(list(range(-1, 6))) - set(sorting_indices)))
            if eigenvalue.imag[missing_indices[0]] > eigenvalue.imag[
                    missing_indices[1]]:
                sorting_indices[1] = missing_indices[0]
                sorting_indices[4] = missing_indices[1]
            else:
                sorting_indices[1] = missing_indices[1]
                sorting_indices[4] = missing_indices[0]

            # reset sorting index for regime halo in l1
            if orbit_type == 'halo' and lagrange_point_nr == 1 and row[
                    0] >= 1972 and row[0] <= 2316:
                sorting_indices = [
                    -1, -1, idx_real_one[0], idx_real_one[1], -1, -1
                ]

            # # TODO check that all indices are unique and no -
            if len(sorting_indices) > len(set(sorting_indices)):
                print('\nWARNING: SORTING INDEX IS NOT UNIQUE FOR ' +
                      self.orbitType + ' AT L' + str(self.lagrangePointNr))
                print(eigenvalue)
                if len(idx_real_one) != 2:
                    idx_real_one = []
                    # Find indices of the first pair of real eigenvalue equal to one
                    for idx, l in enumerate(eigenvalue):
                        if abs(l.imag) < 2 * self.maxEigenvalueDeviation:
                            if abs(l.real -
                                   1.0) < 2 * self.maxEigenvalueDeviation:
                                if sorting_indices[2] == -1:
                                    sorting_indices[2] = idx
                                    idx_real_one.append(idx)
                                elif sorting_indices[3] == -1:
                                    sorting_indices[3] = idx
                                    idx_real_one.append(idx)

                if len(idx_real_one) == 2:
                    sorting_indices = [-1, -1, -1, -1, -1, -1]
                    sorting_indices[2] = idx_real_one[0]
                    sorting_indices[3] = idx_real_one[1]
                    print('minimum angle = ' + str(
                        min(
                            abs(
                                np.angle(eigenvalue[list(
                                    set(range(6)) - set(idx_real_one))],
                                         deg=True)))))
                    print('maximum angle = ' + str(
                        max(
                            abs(
                                np.angle(eigenvalue[list(
                                    set(range(6)) - set(idx_real_one))],
                                         deg=True)))))
                    # Assume two times real one and two conjugate pairs
                    for idx, l in enumerate(eigenvalue):
                        print(idx)
                        print(abs(np.angle(l, deg=True)))
                        # min(abs(np.angle(eigenvalue[list(set(range(6)) - set(idx_real_one))], deg=True)))
                        # if abs(np.angle(l, deg=True))%180 == min(abs(np.angle(eigenvalue[list(set(range(6)) - set(idx_real_one))], deg=True)) %180):
                        if l.real == eigenvalue[list(
                                set(range(6)) - set(idx_real_one))].real.max():
                            if l.imag > 0:
                                sorting_indices[0] = idx
                            elif l.imag < 0:
                                sorting_indices[5] = idx
                        # if abs(np.angle(l, deg=True))%180 == max(abs(np.angle(eigenvalue[list(set(range(6)) - set(idx_real_one))], deg=True)) %180):
                        if l.real == eigenvalue[list(
                                set(range(6)) - set(idx_real_one))].real.min():
                            if l.imag > 0:
                                sorting_indices[1] = idx
                            elif l.imag < 0:
                                sorting_indices[4] = idx
                        print(sorting_indices)

            if len(sorting_indices) > len(set(sorting_indices)):
                print('\nWARNING: SORTING INDEX IS STILL NOT UNIQUE')
                # Sorting eigenvalues from largest to smallest norm, excluding real one

                # Sorting based on previous phase
                if len(idx_real_one) == 2:
                    sorting_indices = [-1, -1, -1, -1, -1, -1]
                    sorting_indices[2] = idx_real_one[0]
                    sorting_indices[3] = idx_real_one[1]

                    # Assume two times real one and two conjugate pairs
                    for idx, l in enumerate(
                            eigenvalue[list(set(range(6)) -
                                            set(idx_real_one))]):
                        print(idx)
                        if abs(l.real - self.lambda1[-1].real) == min(
                                abs(eigenvalue.real - self.lambda1[-1].real)
                        ) and abs(l.imag - self.lambda1[-1].imag) == min(
                                abs(eigenvalue.imag - self.lambda1[-1].imag)):
                            sorting_indices[0] = idx
                        if abs(l.real - self.lambda2[-1].real) == min(
                                abs(eigenvalue.real - self.lambda2[-1].real)
                        ) and abs(l.imag - self.lambda2[-1].imag) == min(
                                abs(eigenvalue.imag - self.lambda2[-1].imag)):
                            sorting_indices[1] = idx
                        if abs(l.real - self.lambda5[-1].real) == min(
                                abs(eigenvalue.real - self.lambda5[-1].real)
                        ) and abs(l.imag - self.lambda5[-1].imag) == min(
                                abs(eigenvalue.imag - self.lambda5[-1].imag)):
                            sorting_indices[4] = idx
                        if abs(l.real - self.lambda6[-1].real) == min(
                                abs(eigenvalue.real - self.lambda6[-1].real)
                        ) and abs(l.imag - self.lambda6[-1].imag) == min(
                                abs(eigenvalue.imag - self.lambda6[-1].imag)):
                            sorting_indices[5] = idx
                        print(sorting_indices)

                pass
            if (sorting_indices[1] and sorting_indices[4]) == -1:
                # Fill two missing values
                two_missing_indices = list(
                    set(list(range(-1, 6))) - set(sorting_indices))
                if abs(eigenvalue[two_missing_indices[0]].real) > abs(
                        eigenvalue[two_missing_indices[1]].real):
                    sorting_indices[1] = two_missing_indices[0]
                    sorting_indices[4] = two_missing_indices[1]
                else:
                    sorting_indices[1] = two_missing_indices[1]
                    sorting_indices[4] = two_missing_indices[0]
                print(sorting_indices)
            if (sorting_indices[0] and sorting_indices[5]) == -1:
                # Fill two missing values
                two_missing_indices = list(
                    set(list(range(-1, 6))) - set(sorting_indices))
                print(eigenvalue)
                print(sorting_indices)
                print(two_missing_indices)
                # TODO quick fix for extended v-l
                # if len(two_missing_indices)==1:
                #     print('odd that only one index remains')
                #     if sorting_indices[0] == -1:
                #         sorting_indices[0] = two_missing_indices[0]
                #     else:
                #         sorting_indices[5] = two_missing_indices[0]
                # sorting_indices = abs(eigenvalue).argsort()[::-1]
                if abs(eigenvalue[two_missing_indices[0]].real) > abs(
                        eigenvalue[two_missing_indices[1]].real):
                    sorting_indices[0] = two_missing_indices[0]
                    sorting_indices[5] = two_missing_indices[1]
                else:
                    sorting_indices[0] = two_missing_indices[1]
                    sorting_indices[5] = two_missing_indices[0]
                print(sorting_indices)

            if len(sorting_indices) > len(set(sorting_indices)):
                print('\nWARNING: SORTING INDEX IS STILL STILL NOT UNIQUE')
                # Sorting eigenvalues from largest to smallest norm, excluding real one
                sorting_indices = abs(eigenvalue).argsort()[::-1]
            print(eigenvalue[sorting_indices])
            self.eigenvalues.append(eigenvalue[sorting_indices])
            self.lambda1.append(eigenvalue[sorting_indices[0]])
            self.lambda2.append(eigenvalue[sorting_indices[1]])
            self.lambda3.append(eigenvalue[sorting_indices[2]])
            self.lambda4.append(eigenvalue[sorting_indices[3]])
            self.lambda5.append(eigenvalue[sorting_indices[4]])
            self.lambda6.append(eigenvalue[sorting_indices[5]])

            # Determine order of linear instability
            reduction = 0
            for i in range(6):
                if (abs(eigenvalue[i]) - 1.0) < 1e-2:
                    reduction += 1

            if len(self.orderOfLinearInstability) > 0:
                # Check for a bifurcation, when the order of linear instability changes
                if (6 - reduction) != self.orderOfLinearInstability[-1]:
                    self.orbitIdBifurcations.append(row[0])

            self.orderOfLinearInstability.append(6 - reduction)
            self.v1.append(
                abs(eigenvalue[sorting_indices[0]] +
                    eigenvalue[sorting_indices[5]]) / 2)
            self.v2.append(
                abs(eigenvalue[sorting_indices[1]] +
                    eigenvalue[sorting_indices[4]]) / 2)
            self.v3.append(
                abs(eigenvalue[sorting_indices[2]] +
                    eigenvalue[sorting_indices[3]]) / 2)
            self.D.append(np.linalg.det(M))
        print('Index for bifurcations: ')
        print(self.orbitIdBifurcations)

        # Determine heatmap for level of C
        self.numberOfPlotColorIndices = len(self.C)
        self.plotColorIndexBasedOnC = []
        for jacobi_energy in self.C:
            self.plotColorIndexBasedOnC.append(
                int(
                    np.round((jacobi_energy - min(self.C)) /
                             (max(self.C) - min(self.C)) *
                             (self.numberOfPlotColorIndices - 1))))

        for i in range(0, len(initial_conditions_incl_m_df)):
            df = load_orbit('../../data/raw/orbits/extended/L' +
                            str(self.lagrangePointNr) + '_' + self.orbitType +
                            '_' + str(i) + '.txt')
            self.delta_r.append(
                np.sqrt((df.head(1)['x'].values - df.tail(1)['x'].values)**2 +
                        (df.head(1)['y'].values - df.tail(1)['y'].values)**2 +
                        (df.head(1)['z'].values - df.tail(1)['z'].values)**2))

            self.delta_v.append(
                np.sqrt((df.head(1)['xdot'].values -
                         df.tail(1)['xdot'].values)**2 +
                        (df.head(1)['ydot'].values -
                         df.tail(1)['ydot'].values)**2 +
                        (df.head(1)['zdot'].values -
                         df.tail(1)['zdot'].values)**2))

            self.delta_x.append(
                abs(df.head(1)['x'].values - df.tail(1)['x'].values))
            self.delta_y.append(
                abs(df.head(1)['y'].values - df.tail(1)['y'].values))
            self.delta_z.append(
                abs(df.head(1)['z'].values - df.tail(1)['z'].values))
            self.delta_x_dot.append(
                abs(df.head(1)['xdot'].values - df.tail(1)['xdot'].values))
            self.delta_y_dot.append(
                abs(df.head(1)['ydot'].values - df.tail(1)['ydot'].values))
            self.delta_z_dot.append(
                abs(df.head(1)['zdot'].values - df.tail(1)['zdot'].values))

        # self.figSize = (20, 20)
        self.figSize = (7 * (1 + np.sqrt(5)) / 2, 7)
        n_colors = 3
        n_colors_l = 6
        self.plottingColors = {
            'lambda1':
            sns.color_palette("viridis", n_colors_l)[0],
            'lambda2':
            sns.color_palette("viridis", n_colors_l)[2],
            'lambda3':
            sns.color_palette("viridis", n_colors_l)[4],
            'lambda4':
            sns.color_palette("viridis", n_colors_l)[5],
            'lambda5':
            sns.color_palette("viridis", n_colors_l)[3],
            'lambda6':
            sns.color_palette("viridis", n_colors_l)[1],
            'singleLine':
            sns.color_palette("viridis", n_colors)[0],
            'doubleLine': [
                sns.color_palette("viridis", n_colors)[n_colors - 1],
                sns.color_palette("viridis", n_colors)[0]
            ],
            'tripleLine': [
                sns.color_palette("viridis", n_colors)[n_colors - 1],
                sns.color_palette("viridis", n_colors)[int(
                    (n_colors - 1) / 2)],
                sns.color_palette("viridis", n_colors)[0]
            ],
            'limit':
            'black'
        }

        self.suptitleSize = 20
        self.xlim = [min(self.x), max(self.x)]

        pass
    def __init__(self, libration_point_nr):
        self.suptitleSize = 44
        self.timeTextSize = 33

        self.xLim = [0.8, 1.2]
        self.yLim = [-0.15, 0.15]
        self.zLim = [-0.3, 0.3]

        self.orbitAlpha = 0.8
        self.orbitLinewidth = 2
        self.lagrangePointMarkerSize = 300
        self.orbitColor = 'gray'
        self.librationPointNr = libration_point_nr
        self.t = []
        self.lines = []
        self.horizontalLyapunov = []
        self.halo = []
        self.jacobiEnergyText = ''  # Will become a plt.text-object
        self.jacobiEnergyHorizontalLyapunov = []
        self.jacobiEnergyHalo = []
        self.jacobiEnergyHaloN = []
        self.T = []
        self.orderOfLinearInstability = []
        self.orbitIdBifurcations = []

        # Include reverse halo orbit continuation to horizontal Lyapunov tangent bifurcation

        initial_conditions_file_path = '../../../data/raw/orbits/L' + str(self.librationPointNr) + '_halo_n_initial_conditions.txt'
        initial_conditions_incl_m_df = load_initial_conditions_incl_M(initial_conditions_file_path)[::-1]
        self.numberOfHaloExtensionOrbits = len(initial_conditions_incl_m_df)
        for row in initial_conditions_incl_m_df.iterrows():
            self.jacobiEnergyHaloN.append(row[1][0])

        initial_conditions_incl_m_df = load_initial_conditions_incl_M('../../../data/raw/orbits/L' + str(self.librationPointNr) + '_halo_initial_conditions.txt')
        for row in initial_conditions_incl_m_df.iterrows():
            self.jacobiEnergyHalo.append(row[1][0])

        # Determine the index for bifurcation
        initial_conditions_incl_m_df = load_initial_conditions_incl_M('../../../data/raw/orbits/L' + str(self.librationPointNr) + '_horizontal_initial_conditions.txt')
        for row in initial_conditions_incl_m_df.iterrows():
            self.jacobiEnergyHorizontalLyapunov.append(row[1][0])
            self.T.append(row[1][1])

            M = np.matrix([list(row[1][8:14]), list(row[1][14:20]), list(row[1][20:26]), list(row[1][26:32]), list(row[1][32:38]), list(row[1][38:44])])
            eigenvalue = np.linalg.eigvals(M)

            # Determine order of linear instability
            reduction = 0
            for i in range(6):
                if (abs(eigenvalue[i]) - 1.0) < 1e-2:
                    reduction += 1

            if len(self.orderOfLinearInstability) > 0:
                # Check for a bifurcation, when the order of linear instability changes
                if (6 - reduction) != self.orderOfLinearInstability[-1]:
                    self.orbitIdBifurcations.append(row[0])
            self.orderOfLinearInstability.append(6 - reduction)

        print('Index for bifurcations from horizontal Lyapunov family: ')
        print(self.orbitIdBifurcations)

        # Select the indices to be plotted for the horizontal Lyapunov family (please remember that the bifurcation to the halo family corresponds to the first bifurcation of the horizontal Lyapunov family)
        self.horizontalLyapunovIndices = list(range(0, self.orbitIdBifurcations[0]))
        self.horizontalLyapunovIndices.append(self.orbitIdBifurcations[0])

        # Determine the indices for the halo family
        initial_conditions_incl_m_df = load_initial_conditions_incl_M(
            '../../../data/raw/orbits/L' + str(self.librationPointNr) + '_halo_initial_conditions.txt')
        self.haloIndices = list(range(0, initial_conditions_incl_m_df.index.max()))
        self.haloIndices.append(initial_conditions_incl_m_df.index.max())
        pass