Skip to content

Commit

Permalink
Add new selectors and change layout in AtomSelectionWidget
Browse files Browse the repository at this point in the history
  • Loading branch information
MBartkowiakSTFC committed Feb 14, 2025
1 parent d8604f9 commit edaedc7
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def select_labels(trajectory: Trajectory, **function_parameters: Dict[str, Any])
atom_labels = function_parameters.get("atom_labels", None)
for label in atom_labels:
if label in system._labels:
selection = selection.union(reduce(list.__add__, system._labels[label]))
selection = selection.union(system._labels[label])
return selection


Expand Down
57 changes: 25 additions & 32 deletions MDANSE_GUI/Src/MDANSE_GUI/InputWidgets/AtomSelectionWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
QPlainTextEdit,
QWidget,
QListView,
QAbstractItemView,
QScrollArea,
)
from MDANSE_GUI.InputWidgets.WidgetBase import WidgetBase
from MDANSE_GUI.Tabs.Visualisers.View3D import View3D
Expand All @@ -40,6 +42,9 @@
AllAtomSelection,
AtomSelection,
IndexSelection,
MoleculeSelection,
PatternSelection,
LabelSelection,
)


Expand Down Expand Up @@ -110,29 +115,9 @@ class SelectionHelper(QDialog):
----------
_helper_title : str
The title of the helper dialog window.
_cbox_text : dict
The dictionary that maps the selector settings to text used in
the helper dialog.
"""

_helper_title = "Atom selection helper"
_cbox_text = {
"all": "All atoms (excl. dummy atoms):",
"dummy": "All dummy atoms:",
"hs_on_heteroatom": "Hs on heteroatoms:",
"primary_amine": "Primary amine groups:",
"hydroxy": "Hydroxy groups:",
"methyl": "Methyl groups:",
"phosphate": "Phosphate groups:",
"sulphate": "Sulphate groups:",
"thiol": "Thiol groups:",
"water": "Water molecules:",
"hs_on_element": "Hs on elements:",
"element": "Elements:",
"name": "Atom name:",
"fullname": "Atom fullname:",
"index": "Indexes:",
}

def __init__(
self,
Expand Down Expand Up @@ -176,16 +161,19 @@ def __init__(
for button in self.create_buttons():
bottom.addWidget(button)

layouts[-1].addLayout(bottom)

helper_layout = QHBoxLayout()
for layout in layouts:
helper_layout.addLayout(layout)
sub_layout = QVBoxLayout()
helper_layout.addLayout(layouts[0])
helper_layout.addLayout(sub_layout)
for layout in layouts[1:]:
sub_layout.addLayout(layout)
sub_layout.addLayout(bottom)

self.setLayout(helper_layout)

self.all_selection = True
self.selected = set([])
self.reset()

def closeEvent(self, a0):
"""Hide the window instead of closing. Some issues occur in the
Expand Down Expand Up @@ -224,7 +212,7 @@ def create_layouts(self) -> list[QVBoxLayout]:
for widget in self.left_widgets():
left.addWidget(widget)

right = QVBoxLayout()
right = QHBoxLayout()
for widget in self.right_widgets():
right.addWidget(widget)

Expand All @@ -238,7 +226,7 @@ def right_widgets(self) -> list[QWidget]:
List of QWidgets to add to the right layout from
create_layouts.
"""
return [self.selection_textbox]
return [self.selection_operations_view, self.selection_textbox]

def left_widgets(self) -> list[QWidget]:
"""
Expand All @@ -251,11 +239,16 @@ def left_widgets(self) -> list[QWidget]:

select = QGroupBox("selection")
select_layout = QVBoxLayout()
scroll_area = QScrollArea()
scroll_area.setLayout(select_layout)

self.selection_widgets = [
AllAtomSelection(self),
AtomSelection(self, self.trajectory),
IndexSelection(self),
MoleculeSelection(self, self.trajectory),
PatternSelection(self),
LabelSelection(self, self.trajectory),
]

for widget in self.selection_widgets:
Expand All @@ -274,15 +267,15 @@ def left_widgets(self) -> list[QWidget]:

select.setLayout(select_layout)

preview = QGroupBox("Selection operations")
preview_layout = QVBoxLayout()
preview.setLayout(preview_layout)
self.selection_operations_view = QListView(preview)
self.selection_operations_view = QListView(self)
self.selection_operations_view.setDragEnabled(True)
self.selection_operations_view.setAcceptDrops(True)
self.selection_operations_view.setDragDropMode(
QAbstractItemView.DragDropMode.InternalMove
)
self.selection_operations_view.setModel(self.selection_model)
self.selection_model.selection_changed.connect(self.recalculate_selection)
preview_layout.addWidget(self.selection_operations_view)
return [select, preview]
return [select]

@Slot()
def recalculate_selection(self):
Expand Down
4 changes: 4 additions & 0 deletions MDANSE_GUI/Src/MDANSE_GUI/InputWidgets/CheckableComboBox.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ def __init__(self, *args, **kwargs):

def clear(self):
result = super().clear()
self.items = []
self.checked = []
self.text = []
self.select_all_item = None
self.addItem("select all", underline=True)
self.lineEdit().setText("")
return result
Expand Down
109 changes: 99 additions & 10 deletions MDANSE_GUI/Src/MDANSE_GUI/Widgets/SelectionWidgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@

from MDANSE_GUI.InputWidgets.CheckableComboBox import CheckableComboBox
from MDANSE.MolecularDynamics.Trajectory import Trajectory
from MDANSE.Framework.AtomSelector.general_selection import (
select_all,
select_none,
invert_selection,
)


class BasicSelectionWidget(QGroupBox):
Expand Down Expand Up @@ -143,7 +138,7 @@ def parameter_dictionary(self):


class IndexSelection(BasicSelectionWidget):
def __init__(self, parent=None, widget_label="Select atoms"):
def __init__(self, parent=None, widget_label="Index selection"):
super().__init__(parent, widget_label)
self.selection_keyword = "index_list"

Expand All @@ -170,18 +165,112 @@ def switch_mode(self, new_mode: str):
if new_mode == "list":
self.selection_field.setPlaceholderText("0,1,2")
self.selection_keyword = "index_list"
self.selection_separator = ','
self.selection_separator = ","
if new_mode == "range":
self.selection_field.setPlaceholderText("0-20")
self.selection_keyword = "index_range"
self.selection_separator = '-'
self.selection_separator = "-"
if new_mode == "slice":
self.selection_field.setPlaceholderText("first:last:step")
self.selection_keyword = "index_slice"
self.selection_separator = ':'
self.selection_separator = ":"

def parameter_dictionary(self):
function_parameters = {"function_name": "select_atoms"}
selection = self.selection_field.text()
function_parameters[self.selection_keyword] = [int(x) for x in selection.split(self.selection_separator)]
function_parameters[self.selection_keyword] = [
int(x) for x in selection.split(self.selection_separator)
]
return function_parameters


class MoleculeSelection(BasicSelectionWidget):
def __init__(
self,
parent=None,
trajectory: Trajectory = None,
widget_label="Select molecules",
):
self.molecule_names = []
if trajectory:
self.molecule_names = list(trajectory.chemical_system._clusters.keys())
super().__init__(parent, widget_label)

def add_specific_widgets(self):
layout = self.layout()
layout.addWidget(QLabel("Select molecules named: "))
self.selection_field = CheckableComboBox(self)
layout.addWidget(self.selection_field)
self.selection_field.addItems(self.molecule_names)

def parameter_dictionary(self):
function_parameters = {"function_name": "select_molecules"}
selection = self.selection_field.checked_values()
function_parameters["molecule_names"] = selection
return function_parameters


class LabelSelection(BasicSelectionWidget):
def __init__(
self,
parent=None,
trajectory: Trajectory = None,
widget_label="Select by label",
):
self.labels = []
if trajectory:
self.labels = list(trajectory.chemical_system._labels.keys())
super().__init__(parent, widget_label)

def add_specific_widgets(self):
layout = self.layout()
layout.addWidget(QLabel("Select atoms with label: "))
self.selection_field = CheckableComboBox(self)
layout.addWidget(self.selection_field)
self.selection_field.addItems(self.labels)

def parameter_dictionary(self):
function_parameters = {"function_name": "select_labels"}
selection = self.selection_field.checked_values()
function_parameters["atom_labels"] = selection
return function_parameters


class PatternSelection(BasicSelectionWidget):
def __init__(
self,
parent=None,
widget_label="SMARTS pattern matching",
):
self.pattern_dictionary = {
"primary amine": "[#7X3;H2;!$([#7][#6X3][!#6]);!$([#7][#6X2][!#6])](~[H])~[H]",
"hydroxy": "[#8;H1,H2]~[H]",
"methyl": "[#6;H3](~[H])(~[H])~[H]",
"phosphate": "[#15X4](~[#8])(~[#8])(~[#8])~[#8]",
"sulphate": "[#16X4](~[#8])(~[#8])(~[#8])~[#8]",
"thiol": "[#16X2;H1]~[H]",
}
super().__init__(parent, widget_label)

def add_specific_widgets(self):
layout = self.layout()
layout.addWidget(QLabel("Pick a group"))
self.selection_field = QComboBox(self)
layout.addWidget(self.selection_field)
self.selection_field.addItems(self.pattern_dictionary.keys())
layout.addWidget(QLabel("pattern:"))
self.input_field = QLineEdit("", self)
self.input_field.setPlaceholderText("can be edited")
layout.addWidget(self.input_field)
self.selection_field.currentTextChanged.connect(self.update_string)

@Slot(str)
def update_string(self, key_string: str):
if key_string in self.pattern_dictionary:
self.input_field.setText(self.pattern_dictionary[key_string])

def parameter_dictionary(self):
function_parameters = {"function_name": "select_pattern"}
selection = self.input_field.text()
function_parameters["rdkit_pattern"] = selection
return function_parameters

0 comments on commit edaedc7

Please sign in to comment.