|
|
|
""" |
|
Created on Fri Sep 30 10:13:32 2022 |
|
|
|
@author: DELL |
|
""" |
|
|
|
import os |
|
import re |
|
import hnswlib |
|
import string |
|
import random |
|
import shutil |
|
import pickle |
|
import numpy as np |
|
import pandas as pd |
|
|
|
from itertools import chain |
|
|
|
from PyQt5.QtCore import Qt, QVariant, QThread |
|
from PyQt5 import QtCore, QtWidgets, QtGui |
|
from PyQt5.QtGui import QPixmap |
|
from PyQt5.QtWidgets import QApplication, QMainWindow, QGridLayout, QLabel |
|
|
|
from matplotlib.figure import Figure |
|
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas |
|
from matplotlib.backends.backend_qt5 import NavigationToolbar2QT as NavigationToolbar |
|
|
|
import matchms.filtering as msfilters |
|
from hnswlib import Index |
|
from rdkit import Chem |
|
from rdkit.Chem import Draw, rdFMCS |
|
from molmass import Formula |
|
from matchms.Spectrum import Spectrum |
|
from matchms.importing import load_from_mgf |
|
from gensim.models import Word2Vec |
|
|
|
from uic import main |
|
from core.identification import identify_unknown, match_spectrum |
|
|
|
|
|
class DeepMASS2(QMainWindow, main.Ui_MainWindow): |
|
|
|
def __init__(self, parent=None): |
|
super(DeepMASS2, self).__init__(parent) |
|
self.setupUi(self) |
|
self.setWindowTitle("DeepMASS2") |
|
self.setWindowIcon(QtGui.QIcon("icon/favicon.ico")) |
|
|
|
try: |
|
shutil.rmtree('temp') |
|
os.mkdir('temp') |
|
except: |
|
pass |
|
|
|
|
|
self.label_logo.setPixmap(QPixmap("icon/logo_deepmass.png")) |
|
|
|
|
|
self.LabelAnno = QLabel() |
|
self.gridlayoutAnno = QGridLayout(self.groupBoxAnno) |
|
self.gridlayoutAnno.addWidget(self.LabelAnno) |
|
self.LabelRef = QLabel() |
|
self.gridlayoutRef = QGridLayout(self.groupBoxRef) |
|
self.gridlayoutRef.addWidget(self.LabelRef) |
|
|
|
self.figSpe = MakeFigure(3.6, 2.4, dpi = 300) |
|
self.figSpe_ntb = NavigationToolbar(self.figSpe, self) |
|
self.gridlayoutfigSpec = QGridLayout(self.box_spectrum) |
|
self.gridlayoutfigSpec.addWidget(self.figSpe) |
|
self.gridlayoutfigSpec.addWidget(self.figSpe_ntb) |
|
|
|
|
|
|
|
self.pn = None |
|
self.pp = None |
|
self.database = pd.DataFrame() |
|
self.spectrums = pd.DataFrame(columns=['title', 'spectrum']) |
|
self.identified_spectrums = [] |
|
self.reference_positive = None |
|
self.reference_negative = None |
|
self.default_index_positive = 'data/references_index_positive_spec2vec.bin' |
|
self.default_index_negative = 'data/references_index_negative_spec2vec.bin' |
|
self.default_reference_positive = 'data/references_spectrums_positive.pickle' |
|
self.default_reference_negative = 'data/references_spectrums_negative.pickle' |
|
try: |
|
self.default_database = pd.read_csv('data/DeepMassStructureDB-v1.0.csv') |
|
except: |
|
self.ErrorMsg("Missing data files") |
|
return |
|
self.current_spectrum = None |
|
self.current_reference = None |
|
|
|
|
|
self.butt_open.setDisabled(True) |
|
self.butt_run.setDisabled(True) |
|
self.butt_match.setDisabled(True) |
|
self.butt_save.setDisabled(True) |
|
self.butt_open.clicked.connect(self.load_spectrums) |
|
self.butt_save.clicked.connect(self.save_identification) |
|
self.butt_run.clicked.connect(self.run_identification) |
|
self.butt_match.clicked.connect(self.run_matching_ms) |
|
self.butt_spectrum.clicked.connect(self.plot_spectrum) |
|
self.butt_loss.clicked.connect(self.plot_loss) |
|
self.butt_plotComm.clicked.connect(self.plot_mol_with_highlight) |
|
self.list_spectrum.itemClicked.connect(self.fill_formula_table) |
|
self.tab_formula.itemClicked.connect(self.fill_structural_table) |
|
self.tab_structure.itemClicked.connect(self.fill_reference_table) |
|
self.tab_reference.itemClicked.connect(self.plot_spectrum) |
|
|
|
self.tab_formula.setSelectionBehavior(QtWidgets.QTableView.SelectRows) |
|
self.tab_structure.setSelectionBehavior(QtWidgets.QTableView.SelectRows) |
|
self.tab_reference.setSelectionBehavior(QtWidgets.QTableView.SelectRows) |
|
|
|
|
|
self.Thread_LoadIndexPositive = None |
|
self.Thread_LoadIndexNegative = None |
|
self.Thread_LoadReference = None |
|
self.Thread_Identification = None |
|
self.Thread_Matching = None |
|
|
|
self.progressBar.setValue(0) |
|
self.progressBar.setFormat('Loading database') |
|
self.load_references_positive() |
|
try: |
|
self.deepmass_positive = Word2Vec.load("model/Ms2Vec_allGNPSpositive.hdf5") |
|
self.deepmass_negative = Word2Vec.load("model/Ms2Vec_allGNPSnegative.hdf5") |
|
except: |
|
self.ErrorMsg("Missing model files") |
|
return |
|
|
|
|
|
def WarnMsg(self, Text): |
|
msg = QtWidgets.QMessageBox() |
|
msg.resize(550, 200) |
|
msg.setIcon(QtWidgets.QMessageBox.Warning) |
|
msg.setText(Text) |
|
msg.setWindowTitle("Warning") |
|
msg.exec_() |
|
|
|
|
|
def ErrorMsg(self, Text): |
|
msg = QtWidgets.QMessageBox() |
|
msg.resize(550, 200) |
|
msg.setIcon(QtWidgets.QMessageBox.Critical) |
|
msg.setText(Text) |
|
msg.setWindowTitle("Error") |
|
msg.exec_() |
|
|
|
|
|
def InforMsg(self, Text): |
|
msg = QtWidgets.QMessageBox() |
|
msg.resize(550, 200) |
|
msg.setIcon(QtWidgets.QMessageBox.Information) |
|
msg.setText(Text) |
|
msg.setWindowTitle("Information") |
|
msg.exec_() |
|
|
|
|
|
def _set_index_positive(self, msg): |
|
self.pp = msg |
|
|
|
|
|
def _set_index_negative(self, msg): |
|
self.pn = msg |
|
|
|
|
|
def _set_database(self, msg): |
|
self.database = msg |
|
|
|
|
|
def _set_reference_positive(self, msg): |
|
self.reference_positive = msg |
|
|
|
|
|
def _set_reference_negative(self, msg): |
|
self.reference_negative = msg |
|
|
|
|
|
def _set_succeed_annotation(self, msg): |
|
self.identified_spectrums.append(msg) |
|
|
|
|
|
def _set_process_bar(self, msg): |
|
self.progressBar.setValue(int(msg)) |
|
|
|
|
|
def _set_table_widget(self, widget, data): |
|
widget.setRowCount(0) |
|
widget.setRowCount(data.shape[0]) |
|
widget.setColumnCount(data.shape[1]) |
|
widget.setHorizontalHeaderLabels(data.columns) |
|
widget.setVerticalHeaderLabels(data.index.astype(str)) |
|
for i in range(data.shape[0]): |
|
for j in range(data.shape[1]): |
|
if type(data.iloc[i,j]) == np.float64: |
|
item = QtWidgets.QTableWidgetItem() |
|
item.setData(Qt.EditRole, QVariant(float(data.iloc[i,j]))) |
|
else: |
|
item = QtWidgets.QTableWidgetItem(str(data.iloc[i,j])) |
|
widget.setItem(i, j, item) |
|
|
|
|
|
def _set_busy(self): |
|
self.butt_open.setDisabled(True) |
|
self.butt_run.setDisabled(True) |
|
self.butt_match.setDisabled(True) |
|
self.butt_save.setDisabled(True) |
|
|
|
|
|
def _set_finished(self): |
|
self.progressBar.setValue(100) |
|
self.progressBar.setFormat('Ready') |
|
self.butt_open.setDisabled(False) |
|
self.butt_run.setDisabled(False) |
|
self.butt_match.setDisabled(False) |
|
self.butt_save.setDisabled(False) |
|
|
|
|
|
def get_formula_mass(self, formula): |
|
f = Formula(formula) |
|
return f.isotope.mass |
|
|
|
|
|
def load_references_positive(self): |
|
self.progressBar.setValue(22) |
|
self.progressBar.setFormat('Loading positive references') |
|
try: |
|
self.Thread_LoadIndexPositive = Thread_LoadIndex(self.default_index_positive) |
|
self.Thread_LoadIndexPositive._index.connect(self._set_index_positive) |
|
self.Thread_LoadIndexPositive.start() |
|
self.Thread_LoadIndexPositive.finished.connect(self.load_references_negative) |
|
except: |
|
self.ErrorMsg("Missing data files") |
|
return |
|
|
|
|
|
def load_references_negative(self): |
|
self.progressBar.setValue(44) |
|
self.progressBar.setFormat('Loading negative references') |
|
try: |
|
self.Thread_LoadIndexNegative = Thread_LoadIndex(self.default_index_negative) |
|
self.Thread_LoadIndexNegative._index.connect(self._set_index_negative) |
|
self.Thread_LoadIndexNegative.start() |
|
self.Thread_LoadIndexNegative.finished.connect(self.load_reference_spectrums) |
|
except: |
|
self.ErrorMsg("Missing data files") |
|
return |
|
|
|
|
|
def load_reference_spectrums(self): |
|
self.progressBar.setValue(77) |
|
self.progressBar.setFormat('Loading reference spectrums') |
|
if self.reference_positive is not None: |
|
self._set_finished() |
|
else: |
|
self.Thread_LoadReference = Thread_LoadReference(self.default_reference_positive, self.default_reference_negative) |
|
self.Thread_LoadReference._reference_positive.connect(self._set_reference_positive) |
|
self.Thread_LoadReference._reference_negative.connect(self._set_reference_negative) |
|
self.Thread_LoadReference._i.connect(self._set_process_bar) |
|
self.Thread_LoadReference.start() |
|
self.Thread_LoadReference.finished.connect(self._set_finished) |
|
|
|
|
|
def load_spectrums(self): |
|
self._set_busy() |
|
options = QtWidgets.QFileDialog.Options() |
|
options |= QtWidgets.QFileDialog.DontUseNativeDialog |
|
fileNames, _ = QtWidgets.QFileDialog.getOpenFileNames(self, "Load", "","MGF Files (*.mgf)", options=options) |
|
if len(fileNames) == 0: |
|
self._set_finished() |
|
return |
|
spectrums = [] |
|
for fileName in fileNames: |
|
spectrums += [s for s in load_from_mgf(fileName) if 'compound_name' in list(s.metadata.keys())] |
|
titles = [s.metadata['compound_name'] for s in spectrums] |
|
self.spectrums = pd.DataFrame({'title': titles, 'spectrum': spectrums}) |
|
self.set_list_spectrums() |
|
self._set_finished() |
|
|
|
|
|
def set_list_spectrums(self): |
|
data = self.spectrums |
|
if len(data) == 0: |
|
return |
|
self.list_spectrum.clear() |
|
for i in data.index: |
|
self.list_spectrum.addItem(data.loc[i, 'title']) |
|
self.list_spectrum.show() |
|
self.list_spectrum.setCurrentRow(0) |
|
|
|
|
|
def run_identification(self): |
|
self._set_busy() |
|
self.identified_spectrums = [] |
|
if len(self.spectrums) == 0: |
|
self.ErrorMsg('Please load unknown spectrums first') |
|
self._set_finished() |
|
return |
|
self.progressBar.setValue(0) |
|
self.progressBar.setFormat('Identifying unknowns') |
|
spectrums = self.spectrums['spectrum'] |
|
p_positive = self.pp |
|
p_negative = self.pn |
|
model_positive = self.deepmass_positive |
|
model_negative = self.deepmass_negative |
|
reference_positive = self.reference_positive |
|
reference_negative = self.reference_negative |
|
|
|
self.Thread_Identification = Thread_Identification(spectrums, p_positive, p_negative, |
|
model_positive, model_negative, |
|
reference_positive, reference_negative, |
|
self.default_database) |
|
self.Thread_Identification._result.connect(self._set_succeed_annotation) |
|
self.Thread_Identification._i.connect(self._set_process_bar) |
|
self.Thread_Identification.start() |
|
self.Thread_Identification.finished.connect(self.fill_formula_table) |
|
|
|
|
|
def run_matching_ms(self): |
|
self._set_busy() |
|
self.identified_spectrums = [] |
|
if len(self.spectrums) == 0: |
|
self.ErrorMsg('Please load unknown spectrums first') |
|
self._set_finished() |
|
return |
|
self.progressBar.setValue(0) |
|
self.progressBar.setFormat('Identifying unknowns') |
|
spectrums = self.spectrums['spectrum'] |
|
reference_positive = self.reference_positive |
|
reference_negative = self.reference_negative |
|
precursors_positive = np.array([s.get('precursor_mz') for s in reference_positive]) |
|
precursors_negative = np.array([s.get('precursor_mz') for s in reference_negative]) |
|
self.Thread_Matching = Thread_Matching(spectrums, |
|
precursors_positive, precursors_negative, |
|
reference_positive, reference_negative) |
|
self.Thread_Matching._result.connect(self._set_succeed_annotation) |
|
self.Thread_Matching._i.connect(self._set_process_bar) |
|
self.Thread_Matching.start() |
|
self.Thread_Matching.finished.connect(self.fill_formula_table) |
|
|
|
|
|
def fill_reference_table(self): |
|
if 'reference' not in self.current_spectrum.metadata.keys(): |
|
self.WarnMsg('No identification result for the selected spectrum') |
|
return |
|
self.current_reference = self.current_spectrum.metadata['reference'] |
|
i = self.tab_structure.currentRow() |
|
header = [self.tab_structure.horizontalHeaderItem(i).text() for i in range(self.tab_structure.columnCount())] |
|
j = list(header).index('CanonicalSMILES') |
|
smi_anno = self.tab_structure.item(i, j).text() |
|
|
|
annotation = self.current_spectrum.metadata['annotation'] |
|
i = np.where(annotation['CanonicalSMILES'].values == smi_anno)[0][0] |
|
|
|
reference_table = [] |
|
for s in self.current_reference: |
|
if 'smiles' in s.metadata.keys(): |
|
smiles = s.metadata['smiles'] |
|
else: |
|
smiles = '' |
|
if 'compound_name' in s.metadata.keys(): |
|
name = s.metadata['compound_name'] |
|
else: |
|
name = smiles |
|
if 'adduct' in s.metadata.keys(): |
|
adduct = s.metadata['adduct'] |
|
else: |
|
adduct = '' |
|
if 'parent_mass' in s.metadata.keys(): |
|
parent_mass = s.metadata['parent_mass'] |
|
else: |
|
parent_mass = '' |
|
if 'database' in s.metadata.keys(): |
|
ref_database = s.metadata['database'] |
|
else: |
|
ref_database = '' |
|
reference_table.append([name, adduct, smiles, parent_mass, ref_database]) |
|
reference_table = pd.DataFrame(reference_table, columns = ['name', 'adduct', 'smiles', 'parent_mass', 'database']) |
|
self._set_table_widget(self.tab_reference, reference_table) |
|
self.tab_reference.setCurrentCell(0, 0) |
|
self.plot_spectrum() |
|
self._set_finished() |
|
|
|
|
|
def fill_formula_table(self): |
|
data = self.spectrums |
|
selectItem = self.list_spectrum.currentItem().text() |
|
w = np.where(data.loc[:, 'title'] == selectItem)[0][0] |
|
try: |
|
self.current_spectrum = self.identified_spectrums[w] |
|
except: |
|
self.WarnMsg('No available structures') |
|
return |
|
|
|
if 'annotation' not in self.current_spectrum.metadata.keys(): |
|
self.WarnMsg('No available structures') |
|
return |
|
annotation = self.current_spectrum.metadata['annotation'] |
|
if len(annotation) == 0: |
|
self.WarnMsg('No available structures') |
|
return |
|
formula = np.unique(annotation['MolecularFormula']) |
|
mass = [self.get_formula_mass(f) for f in formula] |
|
|
|
if 'parent_mass' in self.current_spectrum.metadata.keys(): |
|
diff = np.array([abs(m - float(self.current_spectrum.metadata['parent_mass'])) for m in mass]) |
|
else: |
|
diff = np.repeat(np.nan, len(mass)) |
|
|
|
formula_table = pd.DataFrame({'formula': formula, 'mass': mass, 'error (mDa)': 1000*diff}) |
|
formula_table = formula_table.sort_values(by = 'error (mDa)', ascending=True, ignore_index=True) |
|
self._set_table_widget(self.tab_formula, formula_table) |
|
self.tab_formula.setCurrentCell(0, 0) |
|
self.fill_structural_table() |
|
self.fill_information_table() |
|
self._set_finished() |
|
|
|
|
|
def fill_structural_table(self): |
|
annotation = self.current_spectrum.metadata['annotation'] |
|
i = self.tab_formula.currentRow() |
|
header = [self.tab_formula.horizontalHeaderItem(i).text() for i in range(self.tab_formula.columnCount())] |
|
j = list(header).index('formula') |
|
formula = self.tab_formula.item(i, j).text() |
|
|
|
structural_table = annotation.loc[annotation['MolecularFormula'] == formula,:] |
|
structural_table = structural_table.reset_index(drop = True) |
|
if len(structural_table) == 0: |
|
self.WarnMsg('No available structures') |
|
self._set_finished() |
|
return |
|
self._set_table_widget(self.tab_structure, structural_table) |
|
self.tab_structure.setCurrentCell(0, 0) |
|
self.fill_reference_table() |
|
self._set_finished() |
|
|
|
|
|
def fill_information_table(self): |
|
information = self.current_spectrum.metadata |
|
keys = [k for k in information.keys() if k in ['compound_name', 'precursor_mz', 'precursor_intensity', 'retention_time', 'inchikey', |
|
'formula', 'smiles', 'adduct', 'charge', 'parent_mass', 'ionmode']] |
|
values = [information[k] for k in keys] |
|
info_table = pd.DataFrame({'keys':keys, 'values':values}) |
|
self._set_table_widget(self.tab_information, info_table) |
|
|
|
|
|
def plot_spectrum(self): |
|
try: |
|
i = self.tab_reference.currentRow() |
|
self.figSpe.PlotSpectrum(self.current_spectrum, self.current_reference[i], loss = False) |
|
except: |
|
self.WarnMsg('Cannot plot Spectrum') |
|
self.plot_mol() |
|
|
|
|
|
def plot_loss(self): |
|
try: |
|
i = self.tab_reference.currentRow() |
|
reference = self.current_spectrum.metadata['reference'][i] |
|
self.figSpe.PlotSpectrum(self.current_spectrum, reference, loss = True) |
|
except: |
|
self.WarnMsg('Cannot plot Losses') |
|
|
|
|
|
def plot_mol(self, highlight = False): |
|
i = self.tab_structure.currentRow() |
|
header = [self.tab_structure.horizontalHeaderItem(i).text() for i in range(self.tab_structure.columnCount())] |
|
j = list(header).index('CanonicalSMILES') |
|
mol_anno = self.tab_structure.item(i, j).text() |
|
mol_anno = Chem.MolFromSmiles(mol_anno) |
|
|
|
i = self.tab_reference.currentRow() |
|
header = [self.tab_reference.horizontalHeaderItem(i).text() for i in range(self.tab_reference.columnCount())] |
|
j = list(header).index('smiles') |
|
mol_ref = self.tab_reference.item(i, j).text() |
|
mol_ref = Chem.MolFromSmiles(mol_ref) |
|
|
|
if highlight: |
|
mcs = rdFMCS.FindMCS([mol_anno, mol_ref], bondCompare=rdFMCS.BondCompare.CompareOrderExact, |
|
matchValences = True, ringMatchesRingOnly = True) |
|
mcs_str = mcs.smartsString |
|
mcs_mol = Chem.MolFromSmarts(mcs_str) |
|
allsubs_anno = tuple(chain.from_iterable(mol_anno.GetSubstructMatches(mcs_mol))) |
|
allsubs_ref = tuple(chain.from_iterable(mol_ref.GetSubstructMatches(mcs_mol))) |
|
else: |
|
allsubs_anno = () |
|
allsubs_ref = () |
|
|
|
if mol_anno is not None: |
|
file_name = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10)) |
|
Draw.MolToFile(mol_anno, 'temp/{}.png'.format(file_name), wedgeBonds=False, highlightAtoms=allsubs_anno) |
|
self.LabelAnno.setPixmap(QPixmap('temp/{}.png'.format(file_name))) |
|
|
|
if mol_ref is not None: |
|
file_name = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10)) |
|
Draw.MolToFile(mol_ref, 'temp/{}.png'.format(file_name), wedgeBonds=False, highlightAtoms=allsubs_ref) |
|
self.LabelRef.setPixmap(QPixmap('temp/{}.png'.format(file_name))) |
|
|
|
|
|
def plot_mol_with_highlight(self): |
|
self.plot_mol(highlight = True) |
|
self.InforMsg('Finished') |
|
|
|
|
|
def save_identification(self): |
|
options = QtWidgets.QFileDialog.Options() |
|
options |= QtWidgets.QFileDialog.DontUseNativeDialog |
|
savePath = QtWidgets.QFileDialog.getExistingDirectory(self, "Save", options=options) |
|
if savePath: |
|
if savePath == '': |
|
self.WarnMsg('Invalid path') |
|
return |
|
for s in self.identified_spectrums: |
|
name = s.metadata['compound_name'] |
|
name = re.sub(r'[^ \w+]', '', name) |
|
if 'annotation' in s.metadata.keys(): |
|
annotation = s.metadata['annotation'] |
|
else: |
|
annotation = pd.DataFrame(columns=['Title', 'MolecularFormula', 'CanonicalSMILES', 'InChIKey']) |
|
path = "{}/{}.csv".format(savePath, name) |
|
annotation.to_csv(path) |
|
self.InforMsg('Finished') |
|
|
|
|
|
class Thread_LoadReference(QThread): |
|
_i = QtCore.pyqtSignal(int) |
|
_reference_positive = QtCore.pyqtSignal(list) |
|
_reference_negative = QtCore.pyqtSignal(list) |
|
|
|
def __init__(self, positive, negative): |
|
super().__init__() |
|
self.positive = positive |
|
self.negative = negative |
|
|
|
def run(self): |
|
with open(self.negative, 'rb') as file: |
|
reference_negative = pickle.load(file) |
|
self._reference_negative.emit(list(reference_negative)) |
|
self._i.emit(88) |
|
|
|
with open(self.positive, 'rb') as file: |
|
reference_positive = pickle.load(file) |
|
self._reference_positive.emit(list(reference_positive)) |
|
self._i.emit(99) |
|
|
|
|
|
class Thread_LoadIndex(QThread): |
|
_index = QtCore.pyqtSignal(hnswlib.Index) |
|
|
|
def __init__(self, spec_path): |
|
super().__init__() |
|
self.spec_path = spec_path |
|
|
|
def run(self): |
|
if 'spec2vec' in self.spec_path: |
|
dim = 300 |
|
else: |
|
dim = 200 |
|
spec_bin = Index(space = 'l2', dim = dim) |
|
spec_bin.load_index(self.spec_path) |
|
self._index.emit(spec_bin) |
|
|
|
|
|
class Thread_Identification(QThread): |
|
_i = QtCore.pyqtSignal(int) |
|
_result = QtCore.pyqtSignal(Spectrum) |
|
|
|
def __init__(self, spectrums, p_positive, p_negative, model_positive, model_negative, reference_positive, reference_negative, database): |
|
super(Thread_Identification, self).__init__() |
|
self.p_positive = p_positive |
|
self.p_negative = p_negative |
|
self.spectrums = spectrums |
|
self.model_positive = model_positive |
|
self.model_negative = model_negative |
|
self.reference_positive = reference_positive |
|
self.reference_negative = reference_negative |
|
self.database = database |
|
|
|
def __del__(self): |
|
self.wait() |
|
self.working = False |
|
|
|
def run(self): |
|
for i, s in enumerate(self.spectrums): |
|
if 'ionmode' in s.metadata.keys(): |
|
if s.metadata['ionmode'] == 'negative': |
|
sn = identify_unknown(s, self.p_negative, self.model_negative, self.reference_negative, self.database) |
|
else: |
|
sn = identify_unknown(s, self.p_positive, self.model_positive, self.reference_positive, self.database) |
|
else: |
|
sn = identify_unknown(s, self.p_positive, self.model_positive, self.reference_positive, self.database) |
|
self._i.emit(int(100 * i / len(self.spectrums))) |
|
self._result.emit(sn) |
|
|
|
|
|
class Thread_Matching(QThread): |
|
_i = QtCore.pyqtSignal(int) |
|
_result = QtCore.pyqtSignal(Spectrum) |
|
|
|
def __init__(self, spectrums, precursors_positive, precursors_negative, reference_positive, reference_negative): |
|
super(Thread_Matching, self).__init__() |
|
self.spectrums = spectrums |
|
self.precursors_positive = precursors_positive |
|
self.precursors_negative = precursors_negative |
|
self.reference_positive = reference_positive |
|
self.reference_negative = reference_negative |
|
|
|
def __del__(self): |
|
self.wait() |
|
self.working = False |
|
|
|
def run(self): |
|
for i, s in enumerate(self.spectrums): |
|
if 'ionmode' in s.metadata.keys(): |
|
if s.metadata['ionmode'] == 'negative': |
|
sn = match_spectrum(s, self.precursors_negative, self.reference_negative) |
|
else: |
|
sn = match_spectrum(s, self.precursors_positive, self.reference_positive) |
|
else: |
|
sn = match_spectrum(s, self.precursors_positive, self.reference_positive) |
|
self._i.emit(int(100 * i / len(self.spectrums))) |
|
self._result.emit(sn) |
|
|
|
|
|
class MakeFigure(FigureCanvas): |
|
def __init__(self,width=5, height=5, dpi=300): |
|
self.fig = Figure(figsize=(width, height), dpi=dpi) |
|
self.fig.subplots_adjust(top=0.95,bottom=0.3,left=0.18,right=0.95) |
|
super(MakeFigure,self).__init__(self.fig) |
|
self.axes = self.fig.add_subplot(111) |
|
self.axes.spines['bottom'].set_linewidth(0.5) |
|
self.axes.spines['left'].set_linewidth(0.5) |
|
self.axes.spines['right'].set_linewidth(0.5) |
|
self.axes.spines['top'].set_linewidth(0.5) |
|
self.axes.tick_params(width=0.8,labelsize=3) |
|
FigureCanvas.setSizePolicy(self, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) |
|
FigureCanvas.updateGeometry(self) |
|
|
|
|
|
def PlotSpectrum(self, spectrum, reference, loss = False): |
|
self.axes.cla() |
|
mz, abunds = spectrum.peaks.mz, spectrum.peaks.intensities |
|
mz1, abunds1 = reference.peaks.mz, reference.peaks.intensities |
|
if loss: |
|
try: |
|
spectrum = msfilters.add_parent_mass(spectrum) |
|
spectrum = msfilters.add_losses(spectrum, loss_mz_from=10.0, loss_mz_to=2000.0) |
|
reference = msfilters.add_parent_mass(reference) |
|
reference = msfilters.add_losses(reference, loss_mz_from=10.0, loss_mz_to=2000.0) |
|
mz, abunds = spectrum.losses.mz, spectrum.losses.intensities |
|
mz1, abunds1 = reference.losses.mz, reference.losses.intensities |
|
except: |
|
print('Cannot Plot Losses') |
|
return |
|
abunds /= np.max(abunds) |
|
abunds1 /= np.max(abunds1) |
|
self.axes.vlines(mz, ymin=0, ymax=abunds, color='r', lw = 0.5) |
|
self.axes.vlines(mz1, ymin = 0, ymax = -abunds1, color='b', lw = 0.5) |
|
self.axes.axhline(y=0,color='black', lw = 0.5) |
|
self.axes.set_xlabel('m/z', fontsize = 3.5) |
|
self.axes.set_ylabel('abundance', fontsize = 3.5) |
|
self.draw() |
|
|
|
|
|
if __name__ == '__main__': |
|
import sys |
|
|
|
app = QApplication(sys.argv) |
|
ui = DeepMASS2() |
|
ui.show() |
|
sys.exit(app.exec_()) |