Plot the inference result.

        :param plot_intermediate_solutions: plot the trajectories resulting from the intermediate solutions as well
        :param filter_plots_function: A function that takes a trajectory object and returns True if it should be
                                      plotted and false if not. None plots all available trajectories
        :param legend: Whether to draw the legend or not
        :param kwargs_observed_data: Kwargs to be passed to the ``trajectory.plot`` function for the observed data
        :param kwargs_starting_trajectories: kwargs to be passed to the ``trajectory.plot`` function for the starting
                                             trajectories
        :param kwargs_optimal_trajectories: kwargs to be passed to the ``trajectory.plot`` function for the optimal
                                            trajectories
        :param kwargs_intermediate_trajectories: kwargs to be passed to the ``trajectory.plot`` function for the
                                            intermediate trajectories

def plot(self, plot_intermediate_solutions=True,
             plot_observed_data=True, plot_starting_trajectory=True, plot_optimal_trajectory=True,
             filter_plots_function=None, legend=True,
             kwargs_observed_data=None, kwargs_starting_trajectories=None, kwargs_optimal_trajectories=None,
             kwargs_intermediate_trajectories=None):
        """
        Plot the inference result.

        :param plot_intermediate_solutions: plot the trajectories resulting from the intermediate solutions as well
        :param filter_plots_function: A function that takes a trajectory object and returns True if it should be
                                      plotted and false if not. None plots all available trajectories
        :param legend: Whether to draw the legend or not
        :param kwargs_observed_data: Kwargs to be passed to the ``trajectory.plot`` function for the observed data
        :param kwargs_starting_trajectories: kwargs to be passed to the ``trajectory.plot`` function for the starting
                                             trajectories
        :param kwargs_optimal_trajectories: kwargs to be passed to the ``trajectory.plot`` function for the optimal
                                            trajectories
        :param kwargs_intermediate_trajectories: kwargs to be passed to the ``trajectory.plot`` function for the
                                            intermediate trajectories
        """
        from matplotlib import pyplot as plt
        if filter_plots_function is None:
            filter_plots_function = lambda x: True

        observed_trajectories = self.observed_trajectories

        starting_trajectories = self.starting_trajectories
        optimal_trajectories = self.optimal_trajectories

        if plot_intermediate_solutions:
            intermediate_trajectories_list = self.intermediate_trajectories
        else:
            intermediate_trajectories_list = []

        def initialise_default_kwargs(kwargs, default_data):
            if kwargs is None:
                kwargs = {}

            for key, value in default_data.iteritems():
                if key not in kwargs:
                    kwargs[key] = value

            return kwargs

        trajectories_by_description = {}
        kwargs_observed_data = initialise_default_kwargs(kwargs_observed_data, {'label': "Observed data", 'marker': '+',
                                                                                'color': 'black', 'linestyle': 'None'})

        kwargs_optimal_trajectories = initialise_default_kwargs(kwargs_optimal_trajectories,
                                                                {'label': "Optimised Trajectory", 'color': 'blue'})

        kwargs_starting_trajectories = initialise_default_kwargs(kwargs_starting_trajectories,
                                                                 {'label': "Starting trajectory", 'color': 'green'})

        kwargs_intermediate_trajectories = initialise_default_kwargs(kwargs_intermediate_trajectories,
                                                                     {'label': 'Intermediate Trajectories',
                                                                      'alpha': 0.1, 'color': 'cyan'}
                                                                     )

        if plot_observed_data:
            for trajectory in observed_trajectories:
                if not filter_plots_function(trajectory):
                    continue

                try:
                    list_ = trajectories_by_description[trajectory.description]
                except KeyError:
                    list_ = []
                    trajectories_by_description[trajectory.description] = list_

                list_.append((trajectory, kwargs_observed_data))

        if plot_starting_trajectory:
            for trajectory in starting_trajectories:
                if not filter_plots_function(trajectory):
                    continue

                try:
                    list_ = trajectories_by_description[trajectory.description]
                except KeyError:
                    list_ = []
                    trajectories_by_description[trajectory.description] = list_

                list_.append((trajectory, kwargs_starting_trajectories))

        seen_intermediate_trajectories = set()
        for i, intermediate_trajectories in enumerate(intermediate_trajectories_list):
            for trajectory in intermediate_trajectories:
                if not filter_plots_function(trajectory):
                    continue

                seen = trajectory.description in seen_intermediate_trajectories
                kwargs = kwargs_intermediate_trajectories.copy()
                # Only set label once
                if not seen:
                    seen_intermediate_trajectories.add(trajectory.description)
                else:
                    kwargs['label'] = ''

                try:
                    list_ = trajectories_by_description[trajectory.description]
                except KeyError:
                    list_ = []

                trajectories_by_description[trajectory.description] = list_
                list_.append((trajectory, kwargs))

        if plot_optimal_trajectory:
            for trajectory in optimal_trajectories:
                if not filter_plots_function(trajectory):
                    continue

                try:
                    list_ = trajectories_by_description[trajectory.description]
                except KeyError:
                    list_ = []
                    trajectories_by_description[trajectory.description] = list_

                list_.append((trajectory, kwargs_optimal_trajectories))

        for description, trajectories_list in trajectories_by_description.iteritems():
            if len(trajectories_by_description) > 1:
                plt.figure()
            plt.title(description)

            for trajectory, kwargs in trajectories_list:
                trajectory.plot(**kwargs)

            if legend:
                plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.0)