Skip to content
Snippets Groups Projects
Commit 3e2394d8 authored by Andreas Hellerschmied's avatar Andreas Hellerschmied
Browse files

Started to design the GUI.

parent 3b088150
No related branches found
No related tags found
No related merge requests found
# Current pgm:
## Input data (naive_peaks.py):
- raw data files: binary data (required)
- metadata: csv file that holds the information of the PanelData tab in the according .xlsm file
- jason file with settings:
- raw data folder
- processing settings
# Questions:
- Should there be the possibility to store the current GUI settings (data and processing parameters, etc.)
- Should there be the possibility to load default parameters and/or previously saved parameters (e.g. from json file)?
- Is the json file required in the current version, e.g. for documentation (processing parameters, etc.) or further analysis?
- Are there any default values for the processing parameters? Should they be stored anywhere (e.g. json file)?
## Processing:
- Is the input data (raw data) always organized in the same way, i.e.: Raw data folder that contains data files with the
file names containing the exper. name date and time?
- Where do we get the following parameters (listed in drop down menu) - from the filenames?
- Experiment name
- Date
- Time
- should directly the .xlsm file (PanelData tab) be used instead of an .csv file that holds identical information?
- What is the actual output of the lifescale devise?
- raw data?
- xlsm files with metadata?
## For plotting and analysis:
- Is additional data required from other sources, e.g. the .xlsm files?
- What should be plotted/analyzed/calculated?
......@@ -12,21 +12,150 @@ from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
MainWindow.resize(992, 616)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.tabWidget_Main = QtWidgets.QTabWidget(self.centralwidget)
self.tabWidget_Main.setObjectName("tabWidget_Main")
self.tab_peaks = QtWidgets.QWidget()
self.tab_peaks.setObjectName("tab_peaks")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.tab_peaks)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.groupBox_data = QtWidgets.QGroupBox(self.tab_peaks)
self.groupBox_data.setObjectName("groupBox_data")
self.formLayout = QtWidgets.QFormLayout(self.groupBox_data)
self.formLayout.setObjectName("formLayout")
self.label_data_rawData = QtWidgets.QLabel(self.groupBox_data)
self.label_data_rawData.setObjectName("label_data_rawData")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_data_rawData)
self.horizontalLayout_data_rawData = QtWidgets.QHBoxLayout()
self.horizontalLayout_data_rawData.setObjectName("horizontalLayout_data_rawData")
self.lineEdit_data_rawData = QtWidgets.QLineEdit(self.groupBox_data)
self.lineEdit_data_rawData.setObjectName("lineEdit_data_rawData")
self.horizontalLayout_data_rawData.addWidget(self.lineEdit_data_rawData)
self.pushButton_data_rawData = QtWidgets.QPushButton(self.groupBox_data)
self.pushButton_data_rawData.setObjectName("pushButton_data_rawData")
self.horizontalLayout_data_rawData.addWidget(self.pushButton_data_rawData)
self.formLayout.setLayout(0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.horizontalLayout_data_rawData)
self.label_data_metadataFile = QtWidgets.QLabel(self.groupBox_data)
self.label_data_metadataFile.setObjectName("label_data_metadataFile")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_data_metadataFile)
self.horizontalLayout_data_metadataFile = QtWidgets.QHBoxLayout()
self.horizontalLayout_data_metadataFile.setObjectName("horizontalLayout_data_metadataFile")
self.lineEdit_data_metadataFile = QtWidgets.QLineEdit(self.groupBox_data)
self.lineEdit_data_metadataFile.setObjectName("lineEdit_data_metadataFile")
self.horizontalLayout_data_metadataFile.addWidget(self.lineEdit_data_metadataFile)
self.pushButton_data_metadataFile = QtWidgets.QPushButton(self.groupBox_data)
self.pushButton_data_metadataFile.setObjectName("pushButton_data_metadataFile")
self.horizontalLayout_data_metadataFile.addWidget(self.pushButton_data_metadataFile)
self.formLayout.setLayout(1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.horizontalLayout_data_metadataFile)
self.label_data_outputFolder = QtWidgets.QLabel(self.groupBox_data)
self.label_data_outputFolder.setObjectName("label_data_outputFolder")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_data_outputFolder)
self.horizontalLayout_data_outputFolder = QtWidgets.QHBoxLayout()
self.horizontalLayout_data_outputFolder.setObjectName("horizontalLayout_data_outputFolder")
self.lineEdit_data_outputFolder = QtWidgets.QLineEdit(self.groupBox_data)
self.lineEdit_data_outputFolder.setObjectName("lineEdit_data_outputFolder")
self.horizontalLayout_data_outputFolder.addWidget(self.lineEdit_data_outputFolder)
self.pushButton_data_outputFolder = QtWidgets.QPushButton(self.groupBox_data)
self.pushButton_data_outputFolder.setObjectName("pushButton_data_outputFolder")
self.horizontalLayout_data_outputFolder.addWidget(self.pushButton_data_outputFolder)
self.formLayout.setLayout(2, QtWidgets.QFormLayout.ItemRole.FieldRole, self.horizontalLayout_data_outputFolder)
self.label_data_selectExperiment = QtWidgets.QLabel(self.groupBox_data)
self.label_data_selectExperiment.setObjectName("label_data_selectExperiment")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_data_selectExperiment)
self.comboBox_data_selectExperiment = QtWidgets.QComboBox(self.groupBox_data)
self.comboBox_data_selectExperiment.setObjectName("comboBox_data_selectExperiment")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.ItemRole.FieldRole, self.comboBox_data_selectExperiment)
self.verticalLayout_2.addWidget(self.groupBox_data)
self.groupBox_processingParameters = QtWidgets.QGroupBox(self.tab_peaks)
self.groupBox_processingParameters.setObjectName("groupBox_processingParameters")
self.formLayout_2 = QtWidgets.QFormLayout(self.groupBox_processingParameters)
self.formLayout_2.setObjectName("formLayout_2")
self.label_massTransformation = QtWidgets.QLabel(self.groupBox_processingParameters)
self.label_massTransformation.setObjectName("label_massTransformation")
self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_massTransformation)
self.doubleSpinBox_massTransformation = QtWidgets.QDoubleSpinBox(self.groupBox_processingParameters)
self.doubleSpinBox_massTransformation.setDecimals(6)
self.doubleSpinBox_massTransformation.setObjectName("doubleSpinBox_massTransformation")
self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.doubleSpinBox_massTransformation)
self.label_massCutoff = QtWidgets.QLabel(self.groupBox_processingParameters)
self.label_massCutoff.setObjectName("label_massCutoff")
self.formLayout_2.setWidget(1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_massCutoff)
self.doubleSpinBox_massCutoff = QtWidgets.QDoubleSpinBox(self.groupBox_processingParameters)
self.doubleSpinBox_massCutoff.setDecimals(1)
self.doubleSpinBox_massCutoff.setObjectName("doubleSpinBox_massCutoff")
self.formLayout_2.setWidget(1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.doubleSpinBox_massCutoff)
self.label_peakWidthCutoff = QtWidgets.QLabel(self.groupBox_processingParameters)
self.label_peakWidthCutoff.setObjectName("label_peakWidthCutoff")
self.formLayout_2.setWidget(2, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_peakWidthCutoff)
self.doubleSpinBox_peakWidthCutoff = QtWidgets.QDoubleSpinBox(self.groupBox_processingParameters)
self.doubleSpinBox_peakWidthCutoff.setDecimals(1)
self.doubleSpinBox_peakWidthCutoff.setObjectName("doubleSpinBox_peakWidthCutoff")
self.formLayout_2.setWidget(2, QtWidgets.QFormLayout.ItemRole.FieldRole, self.doubleSpinBox_peakWidthCutoff)
self.label_peakDistanceCutoff = QtWidgets.QLabel(self.groupBox_processingParameters)
self.label_peakDistanceCutoff.setObjectName("label_peakDistanceCutoff")
self.formLayout_2.setWidget(3, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_peakDistanceCutoff)
self.doubleSpinBox_peakDistanceCutoff = QtWidgets.QDoubleSpinBox(self.groupBox_processingParameters)
self.doubleSpinBox_peakDistanceCutoff.setDecimals(1)
self.doubleSpinBox_peakDistanceCutoff.setObjectName("doubleSpinBox_peakDistanceCutoff")
self.formLayout_2.setWidget(3, QtWidgets.QFormLayout.ItemRole.FieldRole, self.doubleSpinBox_peakDistanceCutoff)
self.verticalLayout_2.addWidget(self.groupBox_processingParameters)
self.pushButton_run = QtWidgets.QPushButton(self.tab_peaks)
self.pushButton_run.setObjectName("pushButton_run")
self.verticalLayout_2.addWidget(self.pushButton_run)
self.tabWidget_Main.addTab(self.tab_peaks, "")
self.tab_analysis = QtWidgets.QWidget()
self.tab_analysis.setObjectName("tab_analysis")
self.tabWidget_Main.addTab(self.tab_analysis, "")
self.verticalLayout.addWidget(self.tabWidget_Main)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
self.menubar.setGeometry(QtCore.QRect(0, 0, 992, 22))
self.menubar.setObjectName("menubar")
self.menuOptions = QtWidgets.QMenu(self.menubar)
self.menuOptions.setObjectName("menuOptions")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.actionSave_current_GUI_parameters_json = QtGui.QAction(MainWindow)
self.actionSave_current_GUI_parameters_json.setObjectName("actionSave_current_GUI_parameters_json")
self.actionLoad_GUI_parameters_json = QtGui.QAction(MainWindow)
self.actionLoad_GUI_parameters_json.setObjectName("actionLoad_GUI_parameters_json")
self.actionLoad_default_parameters = QtGui.QAction(MainWindow)
self.actionLoad_default_parameters.setObjectName("actionLoad_default_parameters")
self.menuOptions.addAction(self.actionSave_current_GUI_parameters_json)
self.menuOptions.addAction(self.actionLoad_GUI_parameters_json)
self.menuOptions.addAction(self.actionLoad_default_parameters)
self.menubar.addAction(self.menuOptions.menuAction())
self.retranslateUi(MainWindow)
self.tabWidget_Main.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "lifescale tools"))
self.groupBox_data.setTitle(_translate("MainWindow", "Data"))
self.label_data_rawData.setText(_translate("MainWindow", "Raw data folder"))
self.pushButton_data_rawData.setText(_translate("MainWindow", "Browse"))
self.label_data_metadataFile.setText(_translate("MainWindow", "Metadata file (optional)"))
self.pushButton_data_metadataFile.setText(_translate("MainWindow", "Browse"))
self.label_data_outputFolder.setText(_translate("MainWindow", "Output folder"))
self.pushButton_data_outputFolder.setText(_translate("MainWindow", "Browse"))
self.label_data_selectExperiment.setText(_translate("MainWindow", "Select Experiment"))
self.groupBox_processingParameters.setTitle(_translate("MainWindow", "Processing parameters"))
self.label_massTransformation.setText(_translate("MainWindow", "Mass transformation [fg/Hz]"))
self.label_massCutoff.setText(_translate("MainWindow", "Mass cutoff [fg]"))
self.label_peakWidthCutoff.setText(_translate("MainWindow", "Peak width cutoff [???]"))
self.label_peakDistanceCutoff.setText(_translate("MainWindow", "Peak distance cutoff [??]"))
self.pushButton_run.setText(_translate("MainWindow", "Run"))
self.tabWidget_Main.setTabText(self.tabWidget_Main.indexOf(self.tab_peaks), _translate("MainWindow", "Mass Peaks"))
self.tabWidget_Main.setTabText(self.tabWidget_Main.indexOf(self.tab_analysis), _translate("MainWindow", "Analysis"))
self.menuOptions.setTitle(_translate("MainWindow", "Options"))
self.actionSave_current_GUI_parameters_json.setText(_translate("MainWindow", "Save current GUI parameters (json)"))
self.actionLoad_GUI_parameters_json.setText(_translate("MainWindow", "Load GUI parameters (json)"))
self.actionLoad_default_parameters.setText(_translate("MainWindow", "Load default parameters"))
......@@ -6,25 +6,225 @@
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
<width>992</width>
<height>616</height>
</rect>
</property>
<property name="windowTitle">
<string>lifescale tools</string>
</property>
<widget class="QWidget" name="centralwidget"/>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTabWidget" name="tabWidget_Main">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab_peaks">
<attribute name="title">
<string>Mass Peaks</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox_data">
<property name="title">
<string>Data</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_data_rawData">
<property name="text">
<string>Raw data folder</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_data_rawData">
<item>
<widget class="QLineEdit" name="lineEdit_data_rawData"/>
</item>
<item>
<widget class="QPushButton" name="pushButton_data_rawData">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_data_metadataFile">
<property name="text">
<string>Metadata file (optional)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_data_metadataFile">
<item>
<widget class="QLineEdit" name="lineEdit_data_metadataFile"/>
</item>
<item>
<widget class="QPushButton" name="pushButton_data_metadataFile">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_data_outputFolder">
<property name="text">
<string>Output folder</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_data_outputFolder">
<item>
<widget class="QLineEdit" name="lineEdit_data_outputFolder"/>
</item>
<item>
<widget class="QPushButton" name="pushButton_data_outputFolder">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_data_selectExperiment">
<property name="text">
<string>Select Experiment</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="comboBox_data_selectExperiment"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_processingParameters">
<property name="title">
<string>Processing parameters</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_massTransformation">
<property name="text">
<string>Mass transformation [fg/Hz]</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_massTransformation">
<property name="decimals">
<number>6</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_massCutoff">
<property name="text">
<string>Mass cutoff [fg]</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_massCutoff">
<property name="decimals">
<number>1</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_peakWidthCutoff">
<property name="text">
<string>Peak width cutoff [???]</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_peakWidthCutoff">
<property name="decimals">
<number>1</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_peakDistanceCutoff">
<property name="text">
<string>Peak distance cutoff [??]</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_peakDistanceCutoff">
<property name="decimals">
<number>1</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_run">
<property name="text">
<string>Run</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_analysis">
<attribute name="title">
<string>Analysis</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<width>992</width>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuOptions">
<property name="title">
<string>Options</string>
</property>
<addaction name="actionSave_current_GUI_parameters_json"/>
<addaction name="actionLoad_GUI_parameters_json"/>
<addaction name="actionLoad_default_parameters"/>
</widget>
<addaction name="menuOptions"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="actionSave_current_GUI_parameters_json">
<property name="text">
<string>Save current GUI parameters (json)</string>
</property>
</action>
<action name="actionLoad_GUI_parameters_json">
<property name="text">
<string>Load GUI parameters (json)</string>
</property>
</action>
<action name="actionLoad_default_parameters">
<property name="text">
<string>Load default parameters</string>
</property>
</action>
</widget>
<resources/>
<connections/>
......
......@@ -22,7 +22,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
# Init models:
def main():
"""Main program to start the GUI."""
# Create the application
......
import os
import platform
import json
DEFAULT_CONFIG = {
"mass_transformation": 0.00574,
"mass_cutoff": 20,
"peak_width_cutoff": 5,
"peak_distance_cutoff": 5,
"raw_data_folder": "~/research/lifescale_raw_data_test/development_raw_data_folder"
}
LINUX_PATH = "./dev_config.json"
WINDOWS_PATH = r"C:\Users\LifeScale\Documents\peak_caller_config\peak_caller_config.json"
def load_config():
if platform.system() == "Linux":
try:
with open(LINUX_PATH, "r") as f:
config = json.load(f)
return config, None
except FileNotFoundError as e:
config = DEFAULT_CONFIG
with open(LINUX_PATH, "w") as f:
json.dump(config, f)
return config, LINUX_PATH
elif platform.system() == "Windows":
try:
with open(WINDOWS_PATH, "r") as f:
config = json.load(f)
return config, None
except FileNotFoundError as e:
config = DEFAULT_CONFIG
with open(WINDOWS_PATH, "w") as f:
json.dump(config, f)
return config, WINDOWS_PATH
def configure_peakcaller(raw_data_folder, mass_transformation, mass_cutoff, peak_width_cutoff, peak_distance_cutoff, config, command):
print(locals())
new_config = {k:v for k,v in locals().items() if k != "config" and k != "command" and v is not None}
print(new_config)
old_config = locals()["config"]
merged_config = {k:new_config[k] if k in new_config else old_config[k] for k in old_config}
if platform.system() == "Linux":
with open(LINUX_PATH, "w") as f:
json.dump(merged_config, f)
elif platform.system() == "Windows":
with open(WINDOWS_PATH, "w") as f:
json.dump(merged_config, f)
return merged_config
{"mass_transformation": 0.00574, "mass_cutoff": 20.0, "peak_width_cutoff": 5.0, "peak_distance_cutoff": 5.0, "raw_data_folder": "/home/heller/pyProjects/gooey_lifescale/LSdata/raw_data"}
\ No newline at end of file
""" GUI application for processing LifeScale data.
copyright 2019 Joseph Elsherbini
all rights reserved
"""
import os
import struct
import json
import re
import datetime
from itertools import chain
from operator import itemgetter
import numpy as np
import pandas as pd
import scipy.signal
NOW = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
def list_experiments(config):
raw_data_files = [f for f in os.listdir(os.path.expanduser(config["raw_data_folder"])) if re.search(r"(.+)_(\d{6})_(\d{6})", f) and os.path.splitext(f)[1] == ""]
unique_experiments = sorted(sorted(list(set([re.search(r"(.+)_(\d{6})_(\d{6})", f).groups() for f in raw_data_files])),
key=itemgetter(2), reverse=True), key=itemgetter(1), reverse=True)
return (["{} {}".format(e[0], get_date_time(e[1], e[2])) for e in unique_experiments], ["_".join(e) for e in unique_experiments])
def get_date_time(date, time):
fmt_string = "%m/%d/%Y %H:%M:%S"
return datetime.datetime(2000+int(date[0:2]), int(date[2:4]), int(date[4:6]), int(time[0:2]), int(time[2:4]), int(time[4:6])).strftime(fmt_string)
def call_peaks(experiment, output_folder, metadata_file, config, command):
update_now()
all_experiments= list_experiments(config)
exp_name = [e[1] for e in zip(all_experiments[0], all_experiments[1]) if e[0] == experiment][0]
exp_files = [os.path.join(os.path.expanduser(config["raw_data_folder"]), f) for f in os.listdir(os.path.expanduser(config["raw_data_folder"])) if exp_name in f and os.path.splitext(f)[1] == ""]
print(exp_name, exp_files)
peaks = write_peaks(exp_name, exp_files, output_folder, metadata_file, config)
write_summary(exp_name, peaks, output_folder)
# TODO write_plots(exp_name, peaks, output_folder, config)
write_config(exp_name, output_folder, config)
return config
def update_now():
global NOW
NOW = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
def parse_metadata(metadata_file):
return pd.read_csv(metadata_file)[["Id", "Well"]]
def load_raw_data(exp_name, exp_files):
for f_path in exp_files:
m = re.search(r"(.+)_(\d{6})_(\d{6})_c(\d+)_v(\d+)", f_path)
exp_date, exp_time, exp_cycle, exp_measurement = m.group(2,3,4,5)
print(exp_name, exp_date, exp_time, exp_cycle, exp_measurement)
n_datapoints = int(os.path.getsize(f_path) / 8)
with open(f_path, "rb") as f:
content = f.read()
a = np.array(struct.unpack("d"*n_datapoints, content))[10:]
yield dict(zip(["exp_name", "exp_date", "exp_time", "exp_cycle", "exp_measurement", "data_array"],
[exp_name, exp_date, exp_time, exp_cycle, exp_measurement, a]))
def generate_peaks(measurement, config):
filtered_signal = scipy.signal.savgol_filter(measurement["data_array"], window_length=5, polyorder=3)
peaks, _ = scipy.signal.find_peaks(-filtered_signal, width=config["peak_width_cutoff"], prominence=config["mass_cutoff"]*config["mass_transformation"], distance=config["peak_distance_cutoff"])
masses = scipy.signal.peak_prominences(-filtered_signal, peaks)[0]*(1/config["mass_transformation"])
for peak, mass in zip(peaks, masses):
yield dict(zip(["exp_name", "exp_date", "exp_time", "exp_cycle", "exp_measurement", "event_index","event_mass"],
[measurement["exp_name"], measurement["exp_date"],measurement["exp_time"],measurement["exp_cycle"],measurement["exp_measurement"], peak, mass]))
def write_peaks(exp_name, exp_files, output_folder, metadata_file, config):
peaks = pd.DataFrame(chain.from_iterable([generate_peaks(measurement, config) for measurement in load_raw_data(exp_name, exp_files)]))
if metadata_file:
metadata = parse_metadata(metadata_file)
peaks = peaks.astype({'exp_measurement':'int32'}).merge(metadata.astype({'Id':'int32'}), how='left', left_on='exp_measurement', right_on='Id')
peaks["Well"] = ["".join([w[0],w[1:].zfill(2)]) for w in peaks["Well"]]
out_path = os.path.join(os.path.expanduser(output_folder), "{}_{}_peaks.csv".format(NOW, exp_name))
peaks.to_csv(out_path, index=False)
return peaks
def write_summary(exp_name, peaks, output_folder):
print(peaks.columns)
if "Well" in peaks.columns:
summary = peaks.groupby(["Well", "exp_cycle"])["event_mass"].describe()
else:
summary = peaks.groupby(["exp_measurement", "exp_cycle"])["event_mass"].describe()
out_path = os.path.join(os.path.expanduser(output_folder), "{}_{}_summary.csv".format(NOW, exp_name))
summary.to_csv(out_path)
def write_config(exp_name, output_folder, config):
output_path = os.path.join(os.path.expanduser(output_folder), "{}_{}_config.json".format(NOW, exp_name))
with open(output_path, "w") as f:
json.dump(config, f)
import os
import re
from datetime import datetime
from functools import partial
from operator import itemgetter
from gooey import Gooey, GooeyParser
import naive_peaks
import configure_peakcaller
DISPATCHER = {
"call_peaks": naive_peaks.call_peaks,
"config": configure_peakcaller.configure_peakcaller
}
def show_error_modal(error_msg):
""" Spawns a modal with error_msg"""
# wx imported locally so as not to interfere with Gooey
import wx
app = wx.App()
dlg = wx.MessageDialog(None, error_msg, 'Error', wx.ICON_ERROR)
dlg.ShowModal()
dlg.Destroy()
def add_call_peak_gui(subs, config):
p = subs.add_parser('call_peaks', prog='Call Mass Peaks', help='Get Mass Peaks from Raw Lifescale Data')
p.add_argument(
'experiment',
metavar='Choose an Experiment',
help='Choose the name of an experiment',
widget='Dropdown',
choices=naive_peaks.list_experiments(config)[0])
p.add_argument('output_folder', widget="DirChooser")
p.add_argument('--metadata_file', '-f', widget="FileChooser", help="If provided, convert vial ids to sample names. Should be the exported csv file called PanelData.csv.")
def add_config_gui(subs, config):
p = subs.add_parser('config', prog="Configure Program", help="Options to change where this program looks for data, and the calibration used for frequency to mass conversion.")
p.add_argument('--raw_data_folder', widget="DirChooser", help="currently {}".format(config["raw_data_folder"]))
p.add_argument('--mass_transformation', type=float, help='currently {} Hz/fg'.format(config["mass_transformation"]))
p.add_argument('--mass_cutoff', '-m', type=float, default=20, help='currently {} fg - minimum mass of the peak (minimum 5fg recommended)'.format(config["mass_cutoff"]))
p.add_argument('--peak_width_cutoff', '-w', type=float, default=5, help='currently {} - width cutoff for peaks - minimum datapoints looking larger than noise'.format(config["peak_width_cutoff"]))
p.add_argument('--peak_distance_cutoff', '-d', type=float, default=5, help='currently {} - distance cutoff for peaks - minimum datapoints between peaks'.format(config["peak_distance_cutoff"]))
@Gooey(program_name='Mass Peak Caller', image_dir='./images', required_cols=1)
def main():
current_config, file_not_found = configure_peakcaller.load_config()
if file_not_found:
show_error_modal("No configuration file found at {}.\nWrote default configuration to that location.\nContinuing with default config.".format(file_not_found))
parser = GooeyParser(description='Get Mass Peaks from Raw Lifescale Data')
subs = parser.add_subparsers(help='commands', dest='command')
add_call_peak_gui(subs, current_config)
add_config_gui(subs, current_config)
args = parser.parse_args()
opts = vars(args)
func = partial(DISPATCHER[args.command], config=current_config)
current_config = func(**opts)
if __name__ == '__main__':
main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment