Skip to content

Commit 343dc6d

Browse files
authored
Merge pull request #80 from tgrbrooks/condition-replicates
Condition replicates
2 parents e48f750 + d2df153 commit 343dc6d

7 files changed

Lines changed: 214 additions & 87 deletions

File tree

ada/components/data_list_item.py

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ def __init__(self, text, index, parent=None):
1717
del_button.clicked.connect(parent.remove_item)
1818
add_button = AddButton()
1919
add_button.clicked.connect(parent.add_to_item)
20-
add_button.clicked.connect(parent.update_data_list)
2120
label = QLabel(text)
2221
label.setStyleSheet(styles.default_font_bold)
2322

@@ -31,25 +30,24 @@ def __init__(self, text, index, parent=None):
3130
hwidget.setLayout(layout)
3231
vlayout = QVBoxLayout()
3332
vlayout.addWidget(hwidget)
34-
if(data_manager.num_replicates(index) > 1):
35-
for j in range(1, data_manager.num_replicates(index), 1):
36-
hlayout = QHBoxLayout()
37-
hlayout.addWidget(QLabel('-'))
38-
sub_del_button = DeleteButton()
39-
hlayout.addWidget(sub_del_button)
40-
sub_del_button.clicked.connect(
41-
lambda: parent.remove_replicate(j)
42-
)
43-
inner_label = QLabel(
44-
data_manager.growth_data.replicate_files[index][j].label
45-
)
46-
inner_label.setStyleSheet(styles.small_font)
47-
hlayout.addWidget(inner_label)
48-
hlayout.addStretch()
49-
hlayout.setSizeConstraint(QLayout.SetFixedSize)
50-
subwidget = QWidget()
51-
subwidget.setLayout(hlayout)
52-
vlayout.addWidget(subwidget)
33+
for j in range(1, data_manager.num_replicates(index), 1):
34+
hlayout = QHBoxLayout()
35+
hlayout.addWidget(QLabel('-'))
36+
sub_del_button = DeleteButton()
37+
hlayout.addWidget(sub_del_button)
38+
sub_del_button.clicked.connect(
39+
lambda: parent.remove_replicate(j)
40+
)
41+
inner_label = QLabel(
42+
data_manager.growth_data.replicate_files[index][j].label
43+
)
44+
inner_label.setStyleSheet(styles.small_font)
45+
hlayout.addWidget(inner_label)
46+
hlayout.addStretch()
47+
hlayout.setSizeConstraint(QLayout.SetFixedSize)
48+
subwidget = QWidget()
49+
subwidget.setLayout(hlayout)
50+
vlayout.addWidget(subwidget)
5351
vlayout.setSpacing(0)
5452
vlayout.setContentsMargins(0, 0, 0, 0)
5553
vlayout.addStretch()
@@ -61,23 +59,47 @@ def __init__(self, text, index, parent=None):
6159

6260
class ConditionListItem():
6361

64-
def __init__(self, text, parent=None):
62+
def __init__(self, text, index, parent=None):
6563
self.item = QListWidgetItem()
6664
self.widget = QWidget()
6765
del_button = DeleteButton()
6866
del_button.clicked.connect(parent.remove_condition_item)
6967
label = QLabel(text)
7068
label.setStyleSheet(styles.default_font_bold)
7169

70+
hwidget = QWidget()
7271
layout = QHBoxLayout()
7372
layout.addWidget(del_button)
7473
layout.addWidget(label)
7574
layout.addStretch()
7675
layout.setSizeConstraint(QLayout.SetFixedSize)
77-
layout.setSpacing(5)
78-
layout.setContentsMargins(10, 10, 5, 5)
76+
hwidget.setLayout(layout)
77+
vlayout = QVBoxLayout()
78+
vlayout.addWidget(hwidget)
79+
for j in range(1, data_manager.num_condition_replicates(index), 1):
80+
hlayout = QHBoxLayout()
81+
hlayout.addWidget(QLabel('-'))
82+
sub_del_button = DeleteButton()
83+
hlayout.addWidget(sub_del_button)
84+
sub_del_button.clicked.connect(
85+
lambda: parent.remove_condition_replicate(j)
86+
)
87+
inner_label = QLabel(
88+
data_manager.condition_data.replicate_files[index][j].label
89+
)
90+
inner_label.setStyleSheet(styles.small_font)
91+
hlayout.addWidget(inner_label)
92+
hlayout.addStretch()
93+
hlayout.setSizeConstraint(QLayout.SetFixedSize)
94+
subwidget = QWidget()
95+
subwidget.setLayout(hlayout)
96+
vlayout.addWidget(subwidget)
97+
vlayout.setSpacing(0)
98+
vlayout.setContentsMargins(0, 0, 0, 0)
99+
vlayout.addStretch()
100+
vlayout.setSizeConstraint(QLayout.SetFixedSize)
79101

80-
self.widget.setLayout(layout)
102+
self.widget.setLayout(vlayout)
81103
self.item.setSizeHint(self.widget.sizeHint())
82104

83105

ada/data/data_manager.py

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Local includes
55
from ada.data.algae_data import AlgaeData
66
from ada.data.data_holder import DataHolder
7-
from ada.data.processor import process_data, time_average, average_data
7+
from ada.data.processor import process_data, time_average, time_average_arrays, average_data
88
from ada.data.models import get_model
99
import ada.configuration as config
1010
from ada.logger import logger
@@ -71,6 +71,9 @@ def has_replicates(self, index):
7171
def num_replicates(self, index):
7272
return len(self.growth_data.replicate_files[index])
7373

74+
def num_condition_replicates(self, index):
75+
return len(self.condition_data.replicate_files[index])
76+
7477
def get_replicate_data(self, i, j, xvar, yvar):
7578
xdata = self.growth_data.replicate_files[i][j].get_xdata(xvar)
7679
ydata = self.growth_data.replicate_files[i][j].get_ydata(
@@ -156,13 +159,15 @@ def get_growth_legend(self, i, label_names=None, extra_info=None, only_extra=Fal
156159
legend_label = self.growth_data.data_files[i].get_header_info(extra_info)
157160
return legend_label
158161

159-
def get_condition_xy_data(self, i, cond_name, xvar=None, condition_average=None):
162+
def get_condition_xy_data(self, i, cond_name, xvar=None, condition_average=None, std_err=False):
160163
if xvar is None:
161164
xvar = config.xvar
162165
if condition_average is None:
163166
condition_average = config.condition_average
167+
if config.std_err:
168+
std_err = True
164169

165-
for cond in self.condition_data.data_files:
170+
for j, cond in enumerate(self.condition_data.data_files):
166171
if self.growth_data.data_files[i].reactor != cond.reactor:
167172
continue
168173
if self.growth_data.data_files[i].sub_reactor != cond.sub_reactor:
@@ -171,12 +176,7 @@ def get_condition_xy_data(self, i, cond_name, xvar=None, condition_average=None)
171176
continue
172177
if self.growth_data.data_files[i].time != cond.time:
173178
continue
174-
xdata = cond.get_xdata(xvar)
175-
ydata = cond.get_signal(cond_name)
176-
if condition_average != -1:
177-
xdata, ydata, _ = time_average(
178-
xdata, ydata, condition_average)
179-
return xdata, ydata
179+
return self.get_condition_data(j, xvar, cond_name, condition_average, std_err)
180180
raise RuntimeError('No condition data found for %s'
181181
% (self.growth_data.data_files[i].name))
182182

@@ -188,16 +188,29 @@ def get_condition_data(self, i, xvar=None, yvar=None, condition_average=None, st
188188
if condition_average is None:
189189
condition_average = config.condition_average
190190
if config.std_err:
191-
std_err = True
191+
std_err = config.std_err
192192

193-
xdata = self.condition_data.data_files[i].get_xdata(xvar)
194-
ydata = self.condition_data.data_files[i].get_signal(yvar)
193+
xdatas = []
194+
ydatas = []
195+
for rep in self.condition_data.replicate_files[i]:
196+
xdata = rep.get_xdata(xvar)
197+
ydata = rep.get_ydata(yvar)
198+
xdatas.append(xdata)
199+
ydatas.append(ydata)
195200
yerr = None
196201
# Average condition data over time
197-
if(condition_average != -1):
198-
# Do something
202+
if len(xdatas) > 1 and condition_average != -1:
203+
xdata, ydata, yerr = \
204+
time_average_arrays(xdatas, ydatas, condition_average, std_err)
205+
elif len(xdatas) > 1:
206+
xdata, ydata, yerr = average_data(xdatas, ydatas, std_err)
207+
elif len(xdatas) == 1 and condition_average != -1:
199208
xdata, ydata, yerr = \
200-
time_average(xdata, ydata, condition_average, std_err)
209+
time_average(xdatas[0], ydatas[0], condition_average, std_err)
210+
elif len(xdatas) == 1:
211+
return xdatas[0], ydatas[0], None
212+
else:
213+
raise RuntimeError('No condition data found at index %i' % i)
201214
return xdata, ydata, yerr
202215

203216
def get_condition_ytitle(self, i, yvar=None, yname=None, yunit=None):
@@ -279,7 +292,7 @@ def get_averages(self, cond_name, start_t, end_t):
279292
averages = []
280293
errors = []
281294
for i, _ in enumerate(self.growth_data.data_files):
282-
xdata, ydata = self.get_condition_xy_data(i, cond_name)
295+
xdata, ydata, _ = self.get_condition_xy_data(i, cond_name)
283296
dat = np.array([])
284297
for i, x in enumerate(xdata):
285298
if x >= start_t and x <= end_t:
@@ -300,7 +313,7 @@ def get_condition_at(self, cond_name, time):
300313
logger.debug('Getting condition %s at time %.2f' % (cond_name, time))
301314
values = []
302315
for i, _ in enumerate(self.growth_data.data_files):
303-
xdata, ydata = self.get_condition_xy_data(i, cond_name)
316+
xdata, ydata, _ = self.get_condition_xy_data(i, cond_name)
304317
values.append(np.interp(time, xdata, ydata))
305318
return values
306319

ada/data/processor.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def time_average(xdata, ydata, window, show_err=False):
165165
while(i < len(xdata)):
166166
data_x = np.array([])
167167
data_y = np.array([])
168-
while(i < len(xdata) and xdata[i] < w_i*window):
168+
while(i < len(xdata) and xdata[i] < w_i * window):
169169
data_x = np.append(data_x, xdata[i])
170170
data_y = np.append(data_y, ydata[i])
171171
i = i + 1
@@ -186,6 +186,44 @@ def time_average(xdata, ydata, window, show_err=False):
186186
w_i = w_i + 1
187187
return new_xdata, new_ydata, new_yerr
188188

189+
# Function to average arrays of data over time period
190+
def time_average_arrays(xdatas, ydatas, window, show_err=False):
191+
logger.debug('Averaging data over time window of %i' % window)
192+
new_xdata = np.array([])
193+
new_ydata = np.array([])
194+
new_yerr = np.array([])
195+
w_i = 1
196+
data_remaining = True
197+
while data_remaining:
198+
window_x = np.array([])
199+
window_y = np.array([])
200+
finished = True
201+
for i, xdata in enumerate(xdatas):
202+
# Check if there's any data in the next window
203+
if len(xdata[xdata >= (w_i) * window]) > 0:
204+
finished = False
205+
mask = ((xdata >= (w_i - 1) * window) & (xdata < w_i * window))
206+
window_x = np.append(window_x, xdata[mask])
207+
window_y = np.append(window_y, ydatas[i][mask])
208+
if finished:
209+
data_remaining = False
210+
if(window_y.size == 0):
211+
w_i = w_i + 1
212+
continue
213+
mean_x = np.mean(window_x)
214+
mean_y = np.mean(window_y)
215+
std_dev = np.std(window_y, ddof=1)
216+
if(show_err):
217+
std_dev = std_dev/np.sqrt(window_y.size)
218+
new_xdata = np.append(new_xdata, mean_x)
219+
new_ydata = np.append(new_ydata, mean_y)
220+
if(window_y.size == 1):
221+
new_yerr = np.append(new_yerr, 0)
222+
else:
223+
new_yerr = np.append(new_yerr, std_dev)
224+
w_i = w_i + 1
225+
return new_xdata, new_ydata, new_yerr
226+
189227

190228
def get_exponent(value):
191229
return np.floor(np.log10(np.abs(value))).astype(int)

ada/gui/load_window.py

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@ def initUI(self):
5656

5757
# Dropdown list of available file types
5858
if self.row == -1:
59-
self.file_type = DropDown('File type:', config.replicate_types, self)
60-
else:
6159
self.file_type = DropDown('File type:', config.file_types, self)
60+
else:
61+
self.file_type = DropDown('File type:', config.replicate_types, self)
62+
self.file_type.entry.currentTextChanged.connect(self.update_options)
6263
layout.addWidget(self.file_type)
6364

6465
# Button for selecting files to import
@@ -134,7 +135,7 @@ def update_options(self):
134135
self.details_file_list.show()
135136
self.merge_replicates.show()
136137
# Allow condition files to be added if not dealing with replicates
137-
if (file_type == 'Algem HT24' or file_type == 'Algem Pro') and self.row == -1:
138+
if file_type == 'Algem HT24' or file_type == 'Algem Pro':
138139
self.select_conditions_button.show()
139140
self.conditions_file_list.show()
140141
self.downsample.show()
@@ -190,6 +191,16 @@ def load_algem_pro(self, file_name):
190191
else:
191192
data_manager.growth_data.add_replicate(algem_data, self.row)
192193

194+
def load_algem_pro_conditions(self, file_name, downsample):
195+
logger.info('Loading Algem-Pro condition file %s, downsample %i' %
196+
(file_name, downsample))
197+
# Read in conditions files from Algem Pro
198+
algem_conditions = read_algem_pro(file_name, downsample)
199+
if self.row == -1:
200+
data_manager.condition_data.add_data(algem_conditions)
201+
else:
202+
data_manager.condition_data.add_replicate(algem_conditions, self.row)
203+
193204
def load_algem_ht24_txt(self, file_name):
194205
downsample = self.downsample.get_int()
195206

@@ -232,6 +243,30 @@ def load_algem_ht24(self, file_name):
232243
else:
233244
data_manager.growth_data.add_data(replicate[0])
234245

246+
def load_algem_ht24_conditions(self, file_name, downsample):
247+
logger.info('Loading HT-24 condition file %s, downsample %i' %
248+
(file_name, downsample))
249+
# Read in files from Algem HT24 if details file is provided
250+
if len(self.details) == 0:
251+
algem_conditions_list = read_algem_ht24(file_name,
252+
downsample)
253+
for algem_conditions in algem_conditions_list:
254+
data_manager.condition_data.add_data(algem_conditions)
255+
256+
# Read in files from Algem HT24 without details file
257+
else:
258+
algem_conditions_list, replicate_conditions_list = \
259+
read_algem_ht24_details(file_name, self.details[0],
260+
downsample)
261+
for algem_conditions in algem_conditions_list:
262+
data_manager.condition_data.add_data(algem_conditions)
263+
for replicate in replicate_conditions_list:
264+
if self.merge_replicates.isChecked():
265+
data_manager.condition_data.add_replicate(replicate[0],
266+
replicate[1])
267+
else:
268+
data_manager.condition_data.add_data(replicate[0])
269+
235270
def load_ip(self, file_name):
236271
logger.info('Loading IP file %s' % file_name)
237272
# Read in files from Industrial Plankton
@@ -245,6 +280,7 @@ def load_ip(self, file_name):
245280
data_manager.condition_data.add_data(condition_data)
246281
else:
247282
data_manager.growth_data.add_replicate(ip_data, self.row)
283+
data_manager.condition_data.add_replicate(condition_data, self.row)
248284

249285
def load_psi(self, file_name):
250286
logger.info('Loading PSI file %s' % file_name)
@@ -259,6 +295,7 @@ def load_psi(self, file_name):
259295
data_manager.condition_data.add_data(condition_data)
260296
else:
261297
data_manager.growth_data.add_replicate(psi_data, self.row)
298+
data_manager.condition_data.add_replicate(condition_data, self.row)
262299

263300
def load_ada(self, file_name):
264301
logger.info('Loading ADA file %s' % file_name)
@@ -269,37 +306,8 @@ def load_ada(self, file_name):
269306
data_manager.condition_data.add_data(condition_data)
270307
else:
271308
data_manager.growth_data.add_replicate(ada_data, self.row)
272-
273-
def load_algem_pro_conditions(self, file_name, downsample):
274-
logger.info('Loading Algem-Pro condition file %s, downsample %i' %
275-
(file_name, downsample))
276-
# Read in conditions files from Algem Pro
277-
algem_conditions = read_algem_pro(file_name, downsample)
278-
data_manager.condition_data.add_data(algem_conditions)
279-
280-
def load_algem_ht24_conditions(self, file_name, downsample):
281-
logger.info('Loading HT-24 condition file %s, downsample %i' %
282-
(file_name, downsample))
283-
# Read in files from Algem HT24 if details file is provided
284-
if len(self.details) == 0:
285-
algem_conditions_list = read_algem_ht24(file_name,
286-
downsample)
287-
for algem_conditions in algem_conditions_list:
288-
data_manager.condition_data.add_data(algem_conditions)
289-
290-
# Read in files from Algem HT24 without details file
291-
else:
292-
algem_conditions_list, replicate_conditions_list = \
293-
read_algem_ht24_details(file_name, self.details[0],
294-
downsample)
295-
for algem_conditions in algem_conditions_list:
296-
data_manager.condition_data.add_data(algem_conditions)
297-
for replicate in replicate_conditions_list:
298-
if self.merge_replicates.isChecked():
299-
data_manager.condition_data.add_replicate(replicate[0],
300-
replicate[1])
301-
else:
302-
data_manager.condition_data.add_data(replicate[0])
309+
if condition_data is not None:
310+
data_manager.condition_data.add_replicate(condition_data, self.row)
303311

304312
@error_wrapper
305313
def load(self):

0 commit comments

Comments
 (0)