OSDN Git Service

File system path for statndalone version
[minimpy2/mp2.git] / enrol_form.py
1 from PySide2 import QtWidgets as qtw
2 from PySide2 import QtCore as qtc
3
4
5 class EnrolForm(qtw.QDialog):
6     def __init__(self, parent, factors, treatment, edit=False, identifier=None):
7         super().__init__()
8         self.m_treatment = None
9         self.p_treatment = None
10         self.m_index = None
11         self.p_index = None
12         self.selected_probs = None
13         self.parent = parent
14         self.setGeometry(100, 100, 400, -1)
15         self.factors = factors
16         self.treatment = treatment
17         form_layout = qtw.QFormLayout()
18         if edit:
19             self.setWindowTitle(self.tr('Editing subject "{}"').format(identifier))
20             treatment_combo = qtw.QComboBox()
21             treatment_titles = []
22             treatment_ids = []
23             selected_treatment_index = -1
24             for i, t in enumerate(treatment['treatments']):
25                 treatment_titles.append(t['title'])
26                 treatment_ids.append(t['id'])
27                 if treatment['selected_treatment_id'] == t['id']:
28                     selected_treatment_index = i
29             treatment_combo.addItems(treatment_titles)
30             treatment_combo.setCurrentIndex(selected_treatment_index)
31             treatment_combo.currentIndexChanged.connect(self.get_treatment_combo_events(treatment_ids))
32             form_layout.addRow(self.tr('Treatment'), treatment_combo)
33         else:
34             self.setWindowTitle(self.tr('Subject enrol'))
35
36         for f, factor in enumerate(factors):
37             factor_title = factor['title']
38             levels_combo = qtw.QComboBox()
39             level_titles = []
40             level_ids = []
41             selected_index = -1
42             for i, level in enumerate(factor['levels']):
43                 level_titles.append(level['title'])
44                 level_ids.append(level['id'])
45                 if factor['selected_level_id'] == level['id']:
46                     selected_index = i
47             levels_combo.addItems(level_titles)
48             levels_combo.setCurrentIndex(selected_index)
49             levels_combo.currentIndexChanged.connect(self.get_levels_combo_event(f, level_ids))
50             form_layout.addRow(factor_title, levels_combo)
51         self.result_label = qtw.QLabel(self.tr('Select factors, click enrol'))
52         self.enrol_button = qtw.QPushButton(self.tr('Enrol'))
53         close_button = qtw.QPushButton(self.tr('Close'))
54         if edit:
55             self.enrol_button.setText(self.tr('Save'))
56             form_layout.addRow(self.enrol_button)
57             close_button.setText(self.tr('Cancel'))
58             self.enrol_button.clicked.connect(self.save_subject)
59         else:
60             form_layout.addRow(self.enrol_button, self.result_label)
61             self.enrol_button.clicked.connect(self.enrol_subject)
62         clickable(self.result_label).connect(self.on_detail)
63         close_button.clicked.connect(self.close)
64         form_layout.addRow(close_button)
65         self.setLayout(form_layout)
66
67     def on_detail(self):
68         trial_id = self.parent.settings.value('last_trial_id', 0, type=int)
69         if trial_id == 0:
70             return
71         ns = self.parent.database.get_subject_count(trial_id)
72         if ns == 1:
73             qtw.QMessageBox.information(self.parent, self.tr('Minimisation detail'), self.tr('Enrolled by randomisation'))
74             return
75         final_group = self.tr('preferred')
76         prob = self.selected_probs[self.p_index]
77         if self.m_treatment != self.p_treatment:
78             final_group = self.tr('non-preferred')
79             prob = self.selected_probs[self.m_index]
80         msg = self.tr('Preferred treatment = {}\n').format(self.p_treatment)
81         msg += self.tr('Minimised treatment = {}\n').format(self.m_treatment)
82         msg += self.tr('Subject assigned to {} treatment with a probability of {:4.2f}').format(final_group, prob)
83         qtw.QMessageBox.information(self.parent, self.tr('Minimisation detail'), msg)
84
85     def save_subject(self):
86         self.close()
87         self.setResult(qtw.QDialog.Accepted)
88
89     def enrol_subject(self):
90         selected_indices = []
91         selected_ids = []
92         for factor in self.factors:
93             if factor['selected_level_id'] == -1:
94                 self.result_label.setText(self.tr('Select {} level').format(factor['title']))
95                 return
96             for i, level in enumerate(factor['levels']):
97                 if factor['selected_level_id'] == level['id']:
98                     selected_indices.append(i)
99                     selected_ids.append((factor['id'], factor['selected_level_id']))
100                     break
101         mt, mt_index, pt, pt_index, identifier, probs = self.parent.enrol_one(selected_indices, selected_ids)
102         self.m_index = mt_index
103         self.p_index = pt_index
104         self.m_treatment = mt
105         self.p_treatment = pt
106         self.selected_probs = probs
107         style = 'color: blue;'
108         if mt != pt:
109             style = 'color: red;'
110         self.result_label.setStyleSheet(style)
111         self.result_label.setText(self.tr('Subject "{}", Enrolled to {}').format(identifier, mt))
112         self.enrol_button.setEnabled(False)
113
114
115     def get_treatment_combo_events(self, treatment_ids):
116         def on_treatment_combo_index_changed(index):
117             self.treatment['selected_treatment_id'] = treatment_ids[index]
118         return on_treatment_combo_index_changed
119
120     def get_levels_combo_event(self, f, level_ids):
121         def on_levels_combo_index_changed(index):
122             self.factors[f]['selected_level_id'] = level_ids[index]
123         return on_levels_combo_index_changed
124
125 def clickable(widget):
126     class Filter(qtc.QObject):
127         clicked = qtc.Signal()
128         def eventFilter(self, obj, event):
129             if obj == widget:
130                 if event.type() == qtc.QEvent.MouseButtonRelease:
131                     if obj.rect().contains(event.pos()):
132                         self.clicked.emit()
133                         # The developer can opt for .emit(obj) to get the object within the slot.
134                         return True
135             return False
136     filter = Filter(widget)
137     widget.installEventFilter(filter)
138     return filter.clicked