Skip to content

Commit c7d8879

Browse files
committed
Merge branch 'main' into 21-fine-grained-testing
2 parents bfe9047 + e520c88 commit c7d8879

File tree

5 files changed

+69
-51
lines changed

5 files changed

+69
-51
lines changed

.github/workflows/pytest.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
eval `ssh-agent -s`
2828
ssh-add - <<< '${{ secrets.syncropatch_export_key }}'
2929
python -m pip install --upgrade pip
30-
python -m pip install .[test]
30+
python -m pip install -e .[test]
3131
- name: Extract test data
3232
run: |
3333
wget https://cardiac.nottingham.ac.uk/syncropatch_export/test_data.tar.xz -P tests/

pcpostprocess/hergQC.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class hERGQC(object):
2020
no_QC = len(QCnames)
2121

2222
def __init__(self, sampling_rate=5, plot_dir=None, voltage=np.array([]),
23-
n_sweeps=None, removal_time=2):
23+
n_sweeps=None, removal_time=5):
2424
# TODO docstring
2525

2626
if plot_dir is not None:

pcpostprocess/leak_correct.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,9 @@ def fit_linear_leak(current, voltage, times, ramp_start_index, ramp_end_index,
168168
I_leak[ramp_start_index:ramp_end_index+1], '--')
169169

170170
ax4.plot(times, I_obs, label=r'$I_\mathrm{obs}$')
171-
ax4.plot(times, I_leak, linestyle='--', label=r'$I_\mathrm{l}$')
171+
ax4.plot(times, I_leak, linestyle='--', label=r'$I_\mathrm{L}$')
172172
ax4.plot(times, I_obs - I_leak,
173-
linestyle='--', alpha=0.5, label=r'$I_\mathrm{obs} - I_\mathrm{l}$')
173+
linestyle='--', alpha=0.5, label=r'$I_\mathrm{obs} - I_\mathrm{L}$')
174174
ax4.legend(frameon=False)
175175

176176
if not os.path.exists(output_dir):

pcpostprocess/scripts/run_herg_qc.py

+31-28
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,6 @@ def main():
229229
fout.write(well)
230230
fout.write('\n')
231231

232-
logfile = os.path.join(savedir, 'table-%s.txt' % saveID)
233-
with open(logfile, 'a') as f:
234-
f.write('\\end{table}\n')
235-
236232
# Export all protocols
237233
savenames, readnames, times_list = [], [], []
238234
for protocol in res_dict:
@@ -670,7 +666,8 @@ def extract_protocol(readname, savename, time_strs, selected_wells, args):
670666
row_dict['R_leftover'] =\
671667
np.sqrt(np.sum((after_corrected)**2)/(np.sum(before_corrected**2)))
672668

673-
row_dict['QC.R_leftover'] = row_dict['R_leftover'] < 0.5
669+
QC_R_leftover = np.all(row_dict['R_leftover'] < 0.5)
670+
row_dict['QC.R_leftover'] = QC_R_leftover
674671

675672
row_dict['E_rev'] = E_rev
676673
row_dict['E_rev_before'] = E_rev_before
@@ -739,7 +736,7 @@ def extract_protocol(readname, savename, time_strs, selected_wells, args):
739736
'debug',
740737
'-120mV time constant',
741738
f"{savename}-{well}-sweep"
742-
"{sweep}-time-constant-fit.png"))
739+
"{sweep}-time-constant-fit.pdf"))
743740

744741
row_dict['-120mV decay time constant 1'] = res[0][0]
745742
row_dict['-120mV decay time constant 2'] = res[0][1]
@@ -758,13 +755,6 @@ def extract_protocol(readname, savename, time_strs, selected_wells, args):
758755
before_current_all = before_trace.get_trace_sweeps()
759756
after_current_all = after_trace.get_trace_sweeps()
760757

761-
# Convert everything to nA...
762-
before_current_all = {key: value * 1e-3 for key, value in before_current_all.items()}
763-
after_current_all = {key: value * 1e-3 for key, value in after_current_all.items()}
764-
765-
before_leak_current_dict = {key: value * 1e-3 for key, value in before_leak_current_dict.items()}
766-
after_leak_current_dict = {key: value * 1e-3 for key, value in after_leak_current_dict.items()}
767-
768758
for well in selected_wells:
769759
before_current = before_current_all[well]
770760
after_current = after_current_all[well]
@@ -869,12 +859,11 @@ def run_qc_for_protocol(readname, savename, time_strs, args):
869859

870860
# Check if any cell first!
871861
if (None in qc_before[well][0]) or (None in qc_after[well][0]):
872-
# no_cell = True
862+
no_cell = True
873863
continue
874864

875865
else:
876-
# no_cell = False
877-
pass
866+
no_cell = False
878867

879868
nsweeps = before_trace.NofSweeps
880869
assert after_trace.NofSweeps == nsweeps
@@ -928,19 +917,21 @@ def run_qc_for_protocol(readname, savename, time_strs, args):
928917
logging.info(f"{well} {savename}\n----------")
929918
logging.info(f"sampling_rate is {sampling_rate}")
930919

931-
voltage_steps = [tstart
920+
voltage_steps = [tend
932921
for tstart, tend, vstart, vend in
933922
voltage_protocol.get_all_sections() if vend == vstart]
934923

935924
# Run QC with raw currents
936-
selected, QC = hergqc.run_qc(voltage_steps, times,
937-
before_currents,
938-
after_currents,
939-
np.array(qc_before[well])[0, :],
940-
np.array(qc_after[well])[0, :], nsweeps)
941-
942-
df_rows.append([well] + [all([x for x, _ in qc]) for qc in QC.values()])
943-
925+
_, QC = hergqc.run_qc(voltage_steps, times,
926+
before_currents_corrected,
927+
after_currents_corrected,
928+
np.array(qc_before[well])[0, :],
929+
np.array(qc_after[well])[0, :], nsweeps)
930+
931+
passed_qc = [all([x for x, _ in qc]) for qc in QC.values()]
932+
df_rows.append([well] + passed_qc)
933+
934+
selected = np.all(QC) and not no_cell
944935
if selected:
945936
selected_wells.append(well)
946937

@@ -1048,9 +1039,20 @@ def qc3_bookend(readname, savename, time_strs, args):
10481039
last_before_current = last_before_current_dict[well][-1, :]
10491040
last_after_current = last_after_current_dict[well][-1, :]
10501041

1042+
output_directory = os.path.join(args.output_dir, "leak_correction")
1043+
save_fname = f"{well}_{savename}_before0.pdf"
1044+
1045+
#  Plot subtraction
1046+
get_leak_corrected(first_before_current,
1047+
voltage, times,
1048+
*ramp_bounds,
1049+
save_fname=save_fname,
1050+
output_dir=output_directory)
1051+
10511052
before_traces_first[well] = get_leak_corrected(first_before_current,
10521053
voltage, times,
10531054
*ramp_bounds)
1055+
10541056
before_traces_last[well] = get_leak_corrected(last_before_current,
10551057
voltage, times,
10561058
*ramp_bounds)
@@ -1201,11 +1203,12 @@ def fit_func(x, args=None):
12011203
for ax in axs:
12021204
ax.spines[['top', 'right']].set_visible(False)
12031205
ax.set_ylabel(r'$I_\mathrm{obs}$ (pA)')
1204-
ax.set_xlabel(r'$t$ (ms)')
1206+
1207+
axs[-1].set_xlabel(r'$t$ (ms)')
12051208

12061209
protocol_ax, fit_ax = axs
1207-
protocol_ax.set_title('a', fontweight='bold')
1208-
fit_ax.set_title('b', fontweight='bold')
1210+
protocol_ax.set_title('a', fontweight='bold', loc='left')
1211+
fit_ax.set_title('b', fontweight='bold', loc='left')
12091212
fit_ax.plot(peak_time, peak_current, marker='x', color='red')
12101213

12111214
a, b, c, d = res1.x

pcpostprocess/subtraction_plots.py

+34-19
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ def setup_subtraction_grid(fig, nsweeps):
2626
# Long axis for protocol on the bottom (full width)
2727
long_protocol_ax = fig.add_subplot(gs[5, :])
2828

29+
for ax, cap in zip(list(protocol_axs) + list(before_axs)
30+
+ list(after_axs) + list(corrected_axs)
31+
+ [subtracted_ax] + [long_protocol_ax],
32+
'abcdefghijklm'):
33+
ax.spines[['top', 'right']].set_visible(False)
34+
ax.set_title(cap, loc='left', fontweight='bold')
35+
2936
return protocol_axs, before_axs, after_axs, corrected_axs, subtracted_ax, long_protocol_ax
3037

3138

@@ -40,9 +47,9 @@ def do_subtraction_plot(fig, times, sweeps, before_currents, after_currents,
4047
subtracted_ax, long_protocol_ax = axs
4148

4249
for ax in protocol_axs:
43-
ax.plot(times, voltages, color='black')
50+
ax.plot(times*1e-3, voltages, color='black')
4451
ax.set_xlabel('time (s)')
45-
ax.set_ylabel(r'$V_\mathrm{command}$ (mV)')
52+
ax.set_ylabel(r'$V_\mathrm{cmd}$ (mV)')
4653

4754
all_leak_params_before = []
4855
all_leak_params_after = []
@@ -62,17 +69,22 @@ def do_subtraction_plot(fig, times, sweeps, before_currents, after_currents,
6269
np.nan)
6370
for i, sweep in enumerate(sweeps):
6471

65-
gleak, Eleak = all_leak_params_before[i]
72+
b0, b1 = all_leak_params_before[i]
73+
gleak = b1
74+
Eleak = -b1/b0
6675
before_leak_currents[i, :] = gleak * (voltages - Eleak)
6776

68-
gleak, Eleak = all_leak_params_after[i]
77+
b0, b1 = all_leak_params_after[i]
78+
gleak = b1
79+
Eleak = -b1/b0
80+
6981
after_leak_currents[i, :] = gleak * (voltages - Eleak)
7082

7183
for i, (sweep, ax) in enumerate(zip(sweeps, before_axs)):
7284
gleak, Eleak = all_leak_params_before[i]
73-
ax.plot(times, before_currents[i, :], label=f"pre-drug raw, sweep {sweep}")
74-
ax.plot(times, before_leak_currents[i, :],
75-
label=r'$I_\mathrm{leak}$.' f"g={gleak:1E}, E={Eleak:.1e}")
85+
ax.plot(times*1e-3, before_currents[i, :], label=f"pre-drug raw, sweep {sweep}")
86+
ax.plot(times*1e-3, before_leak_currents[i, :],
87+
label=r'$I_\mathrm{L}$.' f"g={gleak:1E}, E={Eleak:.1e}")
7688
# ax.legend()
7789

7890
if ax.get_legend():
@@ -84,9 +96,9 @@ def do_subtraction_plot(fig, times, sweeps, before_currents, after_currents,
8496

8597
for i, (sweep, ax) in enumerate(zip(sweeps, after_axs)):
8698
gleak, Eleak = all_leak_params_before[i]
87-
ax.plot(times, after_currents[i, :], label=f"post-drug raw, sweep {sweep}")
88-
ax.plot(times, after_leak_currents[i, :],
89-
label=r"$I_\mathrm{leak}$." f"g={gleak:1E}, E={Eleak:.1e}")
99+
ax.plot(times*1e-3, after_currents[i, :], label=f"post-drug raw, sweep {sweep}")
100+
ax.plot(times*1e-3, after_leak_currents[i, :],
101+
label=r"$I_\mathrm{L}$." f"g={gleak:1E}, E={Eleak:.1e}")
90102
# ax.legend()
91103
if ax.get_legend():
92104
ax.get_legend().remove()
@@ -98,12 +110,12 @@ def do_subtraction_plot(fig, times, sweeps, before_currents, after_currents,
98110
for i, (sweep, ax) in enumerate(zip(sweeps, corrected_axs)):
99111
corrected_before_currents = before_currents[i, :] - before_leak_currents[i, :]
100112
corrected_after_currents = after_currents[i, :] - after_leak_currents[i, :]
101-
ax.plot(times, corrected_before_currents,
102-
label=f"leak corrected before drug trace, sweep {sweep}")
103-
ax.plot(times, corrected_after_currents,
104-
label=f"leak corrected after drug trace, sweep {sweep}")
113+
ax.plot(times*1e-3, corrected_before_currents,
114+
label=f"leak-corrected pre-drug trace, sweep {sweep}")
115+
ax.plot(times*1e-3, corrected_after_currents,
116+
label=f"leak-corrected post-drug trace, sweep {sweep}")
105117
ax.set_xlabel(r'$t$ (s)')
106-
ax.set_ylabel(r'leak corrected traces')
118+
ax.set_ylabel(r'leak-corrected traces')
107119
# ax.tick_params(axis='y', rotation=90)
108120
# ax.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1e'))
109121

@@ -118,13 +130,16 @@ def do_subtraction_plot(fig, times, sweeps, before_currents, after_currents,
118130

119131
subtracted_currents = before_currents[i, :] - before_leak_currents[i, :] - \
120132
(after_currents[i, :] - after_leak_currents[i, :])
121-
ax.plot(times, subtracted_currents, label=f"sweep {sweep}")
133+
ax.plot(times*1e-3, subtracted_currents, label=f"sweep {sweep}", alpha=.5)
134+
135+
#  Cycle to next colour
136+
ax.plot([np.nan], [np.nan], label=f"sweep {sweep}", alpha=.5)
122137

123-
ax.set_ylabel(r'$I_\mathrm{obs} - I_\mathrm{l}$ (mV)')
138+
ax.set_ylabel(r'$I_\mathrm{obs} - I_\mathrm{L}$ (mV)')
124139
ax.set_xlabel('$t$ (s)')
125140

126-
long_protocol_ax.plot(times, voltages, color='black')
141+
long_protocol_ax.plot(times*1e-3, voltages, color='black')
127142
long_protocol_ax.set_xlabel('time (s)')
128-
long_protocol_ax.set_ylabel(r'$V_\mathrm{command}$ (mV)')
143+
long_protocol_ax.set_ylabel(r'$V_\mathrm{cmd}$ (mV)')
129144
long_protocol_ax.tick_params(axis='y', rotation=90)
130145

0 commit comments

Comments
 (0)