# Buggy code
def _load_dictionary(self, file_data_dict):
    """Load data from dictionary.

    Parameters
    ----------
    file_data_dict : dictionary
        A dictionary containing at least a 'data' keyword with an array of
        arbitrary dimensions. Additionally the dictionary can contain the
        following items:
        data : numpy array
           The signal data. It can be an array of any dimensions.
        axes : dictionary (optional)
            Dictionary to define the axes (see the
            documentation of the AxesManager class for more details).
        attributes : dictionary (optional)
            A dictionary whose items are stored as attributes.
        metadata : dictionary (optional)
            A dictionary containing a set of parameters
            that will to stores in the `metadata` attribute.
            Some parameters might be mandatory in some cases.
        original_metadata : dictionary (optional)
            A dictionary containing a set of parameters
            that will to stores in the `original_metadata` attribute. It
            typically contains all the parameters that has been
            imported from the original data file.

    """

    self.data = file_data_dict["data"]
    if "models" in file_data_dict:
        self.models._add_dictionary(file_data_dict["models"])
    if "axes" not in file_data_dict:
        file_data_dict["axes"] = self._get_undefined_axes_list()
    self.axes_manager = AxesManager(file_data_dict["axes"])
    if "metadata" not in file_data_dict:
        file_data_dict["metadata"] = {}
    if "original_metadata" not in file_data_dict:
        file_data_dict["original_metadata"] = {}
    if "attributes" in file_data_dict:
        for key, value in file_data_dict["attributes"].items():
            if hasattr(self, key):
                if isinstance(value, dict):
                    for k, v in value.items():
                        eval("self.%s.__setattr__(k,v)" % key)
                else:
                    self.__setattr__(key, value)
    self.original_metadata.add_dictionary(file_data_dict["original_metadata"])
    self.metadata.add_dictionary(file_data_dict["metadata"])
    if "title" not in self.metadata.General:
        self.metadata.General.title = ""
    if self._signal_type or not self.metadata.has_item("Signal.signal_type"):
        self.metadata.Signal.signal_type = self._signal_type


# Traceback (AttributeError)
s = hs.signals.Signal1D(np.random.rand(10,15, 1024))
s.decomposition(True)
s2 = s.get_decomposition_model(9)
s.blind_source_separation(9)

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-34-ef9c7adc7bb5> in <module>()
----> 1 s.blind_source_separation(9)

/home/eric/Python_prog/hyperspy/hyperspy/learn/mva.py in blind_source_separation(self, number_of_components, algorithm, diff_order, diff_axes, factors, comp_list, mask, on_loadings, pretreatment, **kwargs)
528             if not hasattr(lr, 'factors') or lr.factors is None:
529                 raise AttributeError(
--> 530                     'A decomposition must be performed before blind '
531                     'source seperation or factors must be provided.')
532

AttributeError: A decomposition must be performed before blind source seperation or factors must be provided.

# Fixed code
def _load_dictionary(self, file_data_dict):
    """Load data from dictionary.

    Parameters
    ----------
    file_data_dict : dictionary
        A dictionary containing at least a 'data' keyword with an array of
        arbitrary dimensions. Additionally the dictionary can contain the
        following items:
        data : numpy array
           The signal data. It can be an array of any dimensions.
        axes : dictionary (optional)
            Dictionary to define the axes (see the
            documentation of the AxesManager class for more details).
        attributes : dictionary (optional)
            A dictionary whose items are stored as attributes.
        metadata : dictionary (optional)
            A dictionary containing a set of parameters
            that will to stores in the `metadata` attribute.
            Some parameters might be mandatory in some cases.
        original_metadata : dictionary (optional)
            A dictionary containing a set of parameters
            that will to stores in the `original_metadata` attribute. It
            typically contains all the parameters that has been
            imported from the original data file.

    """

    self.data = file_data_dict["data"]
    if "models" in file_data_dict:
        self.models._add_dictionary(file_data_dict["models"])
    if "axes" not in file_data_dict:
        file_data_dict["axes"] = self._get_undefined_axes_list()
    self.axes_manager = AxesManager(file_data_dict["axes"])
    if "metadata" not in file_data_dict:
        file_data_dict["metadata"] = {}
    if "original_metadata" not in file_data_dict:
        file_data_dict["original_metadata"] = {}
    if "attributes" in file_data_dict:
        for key, value in file_data_dict["attributes"].items():
            if hasattr(self, key):
                if isinstance(value, dict):
                    for k, v in value.items():
                        eval("self.%s.__setattr__(k,v)" % key)
                else:
                    self.__setattr__(key, value)
    self.original_metadata.add_dictionary(file_data_dict["original_metadata"])
    self.metadata.add_dictionary(file_data_dict["metadata"])
    if "title" not in self.metadata.General:
        self.metadata.General.title = ""
    if self._signal_type or not self.metadata.has_item("Signal.signal_type"):
        self.metadata.Signal.signal_type = self._signal_type
    if "learning_results" in file_data_dict:
        self.learning_results.__dict__.update(file_data_dict["learning_results"])