Skip to content

Commit f3b3dc4

Browse files
joeyshuttleworthJoseph Shuttleworthmjowen
authored
Increase test coverage (#10)
* update docstring. test leakcorrect * Output QC values as array. Add tests and fix get_onbard_QC_df * remove unused import * add line to test * Increase test coverage. Fix get_onboard_QC_df * Lint code * Update tests/test_trace_class.py Co-authored-by: Matt J Owen <matt.owen@nottingham.ac.uk> * Update test_trace_class.py * Fix whitespace * fix imports * test output of voltage protocol * fix whitespace * fix imports --------- Co-authored-by: Joseph Shuttleworth <joseph.shuttleworth@nottingham.ac.uk> Co-authored-by: Matt J Owen <matt.owen@nottingham.ac.uk>
1 parent ed4c08b commit f3b3dc4

3 files changed

Lines changed: 59 additions & 8 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
*.DS_Store
44
*__pycache__*
55
*.egg_info
6+
*__pycache__*

syncropatch_export/trace.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ def __init__(self, filepath, json_file: str):
4141
self.MeasurementLayout = TraceHeader['MeasurementLayout']
4242
self.FileInformation = TraceHeader['FileInformation']
4343

44-
self.WELL_ID = [
44+
self.WELL_ID = np.array([
4545
[lab + str(i).zfill(2) for lab in string.ascii_uppercase[:16]]
46-
for i in range(1, 25)]
46+
for i in range(1, 25)])
4747

4848
self.NofSweeps = self.MeasurementLayout['NofSweeps']
4949
self.WP_nRows = TraceHeader['Chiplayout']['WP_nRows']
@@ -73,6 +73,12 @@ def get_voltage_protocol(self, holding_potential=-80.0):
7373

7474
return voltage_protocol
7575

76+
def get_voltage_protocol_json(self):
77+
"""
78+
Returns the voltage protocol as a JSON object
79+
"""
80+
return self.meta['ExperimentConditions']['VoltageProtocol'][0]
81+
7682
def get_protocol_description(self, holding_potential=-80.0):
7783
"""Get the protocol as a numpy array describing the voltages and
7884
durations for each section
@@ -100,11 +106,10 @@ def get_all_traces(self, leakcorrect=False):
100106
'''
101107
102108
Params:
103-
leakcorrect: Bool. Set to true if onboard leak correction was used
109+
leakcorrect: Bool. Set to true if using onboard leak correction
104110
105111
Returns: all raw current traces from .dat files
106112
107-
TODO: Rename. Detect 'leakcorrect' flag automatically
108113
'''
109114
return self.get_trace_sweeps(leakcorrect=leakcorrect)
110115

@@ -245,6 +250,15 @@ def get_onboard_QC_values(self, sweeps=None):
245250
Capacitance[k, i, j],
246251
Rseries[k, i, j]))
247252

253+
# Convert values to np arrays taking care to remove handle None values
254+
for well in out_dict:
255+
vals = out_dict[well]
256+
if vals:
257+
shape = (len(vals), len(vals[0]))
258+
vals = [x if x is not None else np.nan for x in vals]
259+
vals = np.vstack(vals).reshape(shape).astype(np.float64)
260+
out_dict[well] = vals
261+
248262
return out_dict
249263

250264
def get_onboard_QC_df(self, sweeps=None):
@@ -263,9 +277,7 @@ def get_onboard_QC_df(self, sweeps=None):
263277

264278
df_rows = []
265279
for sweep in sweeps:
266-
for well in self.WELL_ID.values():
267-
if well <= len(QC_dict[well]):
268-
continue
280+
for well in self.WELL_ID.flatten():
269281
Rseal, Capacitance, Rseries = QC_dict[well][sweep]
270282
df_row = {'Rseal': Rseal,
271283
'Cm': Capacitance,
@@ -275,4 +287,4 @@ def get_onboard_QC_df(self, sweeps=None):
275287
}
276288
df_rows.append(df_row)
277289

278-
return pd.from_records(df_rows)
290+
return pd.DataFrame.from_records(df_rows)

tests/test_trace_class.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import json
12
import os
23
import unittest
34

45
import matplotlib.pyplot as plt
56
import numpy as np
7+
import pandas as pd
68

79
from syncropatch_export.trace import Trace as tr
810
from syncropatch_export.voltage_protocols import VoltageProtocol
@@ -40,6 +42,14 @@ def test_protocol_descriptions(self):
4042
self.assertLess(t_error, 1e-2)
4143
self.assertLess(v_error, 1e-4)
4244

45+
def test_protocol_export(self):
46+
protocol = self.test_trace.get_voltage_protocol()
47+
protocol.export_txt(os.path.join(self.output_dir, 'protocol.txt'))
48+
json_protocol = self.test_trace.get_voltage_protocol_json()
49+
50+
with open(os.path.join(self.output_dir, 'protocol.json'), 'w') as fin:
51+
json.dump(json_protocol, fin)
52+
4353
def test_protocol_timeseries(self):
4454
voltages = self.test_trace.get_voltage()
4555
times = self.test_trace.get_times()
@@ -59,10 +69,20 @@ def voltage_func(t):
5969
for t, v in zip(times, voltages):
6070
self.assertLess(voltage_func(t) - v, 1e-3)
6171

72+
def test_get_QC(self):
73+
tr = self.test_trace
74+
QC_values = tr.get_onboard_QC_values()
75+
self.assertGreater(len(QC_values), 0)
76+
df = tr.get_onboard_QC_df()
77+
78+
self.assertGreater(df.shape[0], 0)
79+
self.assertGreater(df.shape[1], 0)
80+
6281
def test_get_traces(self):
6382
tr = self.test_trace
6483
v = tr.get_voltage()
6584
ts = tr.get_times()
85+
all_traces = tr.get_all_traces(leakcorrect=True)
6686
all_traces = tr.get_all_traces()
6787

6888
self.assertTrue(np.all(np.isfinite(v)))
@@ -88,3 +108,21 @@ def test_get_traces(self):
88108
plt.savefig(os.path.join(self.output_dir,
89109
'example_trace'))
90110
plt.close(fig)
111+
112+
def test_qc_df(self):
113+
dfs = [self.test_trace.get_onboard_QC_df(sweeps=[0]),
114+
self.test_trace.get_onboard_QC_df(sweeps=None)]
115+
for res in dfs:
116+
# Check res is a pd.DataFrame
117+
self.assertIsInstance(res, pd.DataFrame)
118+
119+
# Check it contains data (number of rows>0)
120+
self.assertGreater(res.shape[0], 0)
121+
122+
# Check it contains all quality control parameters
123+
for qcParam in ['Rseal', 'Cm', 'Rseries', 'well', 'sweep']:
124+
self.assertIn(qcParam, res)
125+
126+
# Check restricting number of sweeps returns less data
127+
self.assertLess(dfs[0].shape[0], dfs[1].shape[0])
128+

0 commit comments

Comments
 (0)