Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions hyperspyui/images/nmf.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 43 additions & 0 deletions hyperspyui/plugins/mva.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ def create_actions(self):
icon='bss.svg',
tip=tr("Run Blind Source Separation"),
selection_callback=self.selection_rules)
self.add_action('nmf', tr("NMF"), self.nmf,
icon='nmf.svg',
tip=tr("Run Non-negative Matrix Factorization"),
selection_callback=self.selection_rules)
self.add_action('bss_model', tr("BSS model"), self.bss_model,
icon='bss.svg',
tip=tr("Create a Blind Source Separation "
Expand All @@ -130,12 +134,14 @@ def create_menu(self):
self.ui.actions['plot_decomposition_results'])
self.add_menuitem('Decomposition', self.ui.actions['pca'])
self.add_menuitem('Decomposition', self.ui.actions['bss'])
self.add_menuitem('Decomposition', self.ui.actions['nmf'])
self.add_menuitem('Decomposition', self.ui.actions['bss_model'])
self.add_menuitem('Decomposition', self.ui.actions['clear'])

def create_toolbars(self):
self.add_toolbar_button("Decomposition", self.ui.actions['pca'])
self.add_toolbar_button("Decomposition", self.ui.actions['bss'])
self.add_toolbar_button("Decomposition", self.ui.actions['nmf'])

def selection_rules(self, win, action):
"""
Expand Down Expand Up @@ -200,12 +206,25 @@ def _do_bss(self, s, n_components, algorithm=None):
else:
s.blind_source_separation(n_components)

def _do_nmf(self, s, n_components, algorithm=None):
"""
Perform NMF decomposition
"""
s.decomposition(algorithm=algorithm, output_dimension=n_components)


def get_bss_results(self, signal):
factors = signal.get_bss_factors()
loadings = signal.get_bss_loadings()
factors.axes_manager._axes[0] = loadings.axes_manager._axes[0]
return loadings, factors

def get_decomposition_results(self, signal):
factors = signal.get_decomposition_factors()
loadings = signal.get_decomposition_loadings()
factors.axes_manager._axes[0] = loadings.axes_manager._axes[0]
return loadings, factors

def _record(self, autosig, model, signal, n_components):
if autosig:
self.record_code(r"<p>.{0}(n_components={1})".format(
Expand Down Expand Up @@ -255,6 +274,14 @@ def _perform_model(self, ns, n_components):
o.metadata.General.title = ns.signal.name + "[BSS-Loadings]"
f.plot()
o.plot()
elif ns.model == 'nmf':
self._do_nmf(ns.s, n_components=n_components, algorithm='nmf')
f, o = self.get_decomposition_results(ns.s)
o.metadata.add_dictionary(ns.s.metadata.as_dictionary())
f.metadata.General.title = ns.signal.name + "[NMF-Factors]"
o.metadata.General.title = ns.signal.name + "[NMF-Loadings]"
f.plot()
o.plot()
elif ns.model == 'bss_model':
# Here we have to assume the user has actually performed the BSS
# decomposition first!
Expand Down Expand Up @@ -365,6 +392,22 @@ def bss(self, signal=None, n_components=None, advanced=False):
else:
self.do_after_scree('bss', signal, n_components)

def nmf(self, signal=None, n_components=None, advanced=False):
"""
Performs decomposition if neccessary, then plots the scree for the user
to select the number of components to use for a non-negative matrix
factorization. The selection is made by clicking on the scree, which
closes the scree and proceeds with the factorization.
"""
if advanced:
diag = make_advanced_dialog(self.ui)
dr = diag.exec_()
if dr == QDialog.Accepted:
self.do_after_scree(
'nmf', signal, n_components=diag.components())
else:
self.do_after_scree('nmf', signal, n_components)

def bss_model(self, signal=None, n_components=None, advanced=False):
"""
Performs decomposition if neccessary, then plots the scree for the user
Expand Down