import pylustrator pylustrator.start() import sys sys.path.insert(1, "../helperScripts") import matplotlib.pyplot as plt import numpy as np from tqdm import tqdm import pandas as pd import seaborn as sns from matplotlib.gridspec import GridSpec from matplotlib.collections import LineCollection import scikit_posthocs as sp import os # import subprocess from scipy import signal import expcells import features as fts import json import moose import pickle import scipy import MOOSEModel as mm import MOOSEModel_ as mm_ import pingouin as pg import efel from goMultiprocessing import Multiprocessthis_appendsave sns.set(style="ticks") sns.set_context("paper") # fig = plt.figure(figsize=(7, 10), constrained_layout=True) fig = plt.figure(constrained_layout=False, dpi=100, figsize=[8, 10]) gs_outer = GridSpec(4, 2, figure=fig, height_ratios=[2, 1, 1, 1], wspace=0.5, hspace=0.5) axA = fig.add_subplot(gs_outer[0, 0]) gs_inner = gs_outer[0, 1].subgridspec( 2, 1, height_ratios=[2, 1], wspace=0.1, hspace=0.5 ) gs_inner_inner = gs_inner[0].subgridspec( 2, 2, width_ratios=[9, 1], wspace=0.1, hspace=0.1 ) axB = [0] * 4 axB[0] = fig.add_subplot(gs_inner_inner[0, 0]) axB[1] = fig.add_subplot(gs_inner_inner[1, 0]) axB[2] = fig.add_subplot(gs_inner[1, 0]) axB[3] = fig.add_subplot(gs_inner_inner[:, 1]) gs_inner = gs_outer[1, 0].subgridspec(1, 2, wspace=0.5, hspace=0.2) axC = [0] * 4 axC[0] = fig.add_subplot(gs_inner[0, 0]) axC[1] = fig.add_subplot(gs_inner[0, 1]) axD = fig.add_subplot(gs_outer[1:3, 1]) axE = fig.add_subplot(gs_outer[2, 0]) axF = fig.add_subplot(gs_outer[3, 0]) axG = fig.add_subplot(gs_outer[3, 1]) # add a, b, c text to each subplot axis fig.transFigure.inverted().transform([0.5,0.5]) for i, ax in enumerate([axA, axB[0], axC[0], axD, axE, axF, axG]): x_infig, y_infig = ax.transAxes.transform([0,1]) x_infig = x_infig - 20 y_infig = y_infig + 20 x_ax, y_ax = ax.transAxes.inverted().transform([x_infig,y_infig]) ax.text( x_ax, y_ax, f"{chr(65+i)}", transform=ax.transAxes, fontsize=12, fontweight="bold", va="top", ha="right", ) def int_to_roman(n): val = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1] syms = ["m", "cm", "d", "cd", "c", "xc", "l", "xl", "x", "ix", "v", "iv", "i"] roman_numeral = "" for i, v in enumerate(val): while n >= v: roman_numeral += syms[i] n -= v return roman_numeral # add a, b, c text to each subplot axis fig.transFigure.inverted().transform([0.5,0.5]) for i, ax in enumerate([axB[0], axB[2]]): x_infig, y_infig = ax.transAxes.transform([0,1]) x_infig = x_infig y_infig = y_infig + 15 x_ax, y_ax = ax.transAxes.inverted().transform([x_infig,y_infig]) ax.text( x_ax, y_ax, f'({int_to_roman(i+1)})', transform=ax.transAxes, fontsize=12, fontweight="bold", va="top", ha="right", ) # add a, b, c text to each subplot axis fig.transFigure.inverted().transform([0.5,0.5]) for i, ax in enumerate([axC[0], axC[1]]): x_infig, y_infig = ax.transAxes.transform([0,1]) x_infig = x_infig y_infig = y_infig + 15 x_ax, y_ax = ax.transAxes.inverted().transform([x_infig,y_infig]) ax.text( x_ax, y_ax, f'({int_to_roman(i+1)})', transform=ax.transAxes, fontsize=12, fontweight="bold", va="top", ha="right", ) ############ Panel A ####################### image = plt.imread('ballandstick.png') position = axA.get_position() Aposition = axA.transAxes.transform(axA.get_children()[0].get_position()) Aposition[1] += 50 axA.imshow(image, aspect='equal') left, bottom, width, height = position.x0, position.y0, position.width, position.height zoom = 1.8 axA.set_position((left-0.08, bottom+height-zoom*height+0.06, width*image.shape[0]/image.shape[1]*zoom, height*zoom )) axA.get_children()[0].set_position(axA.transAxes.inverted().transform(Aposition)) ##Panel label postition axA.axis('off') ############################################ ############ Panel B ####################### cellname = '2023_01_04_cell_3' cell1 = expcells.expcell(cellname, f'../expdata/Chirp/{cellname}') cell1.ampphase_freq() cell1.chirpresponse(normalize=False) ti=1 stimamp = 30e-12 t = np.arange(0, 13, cell1.chirpdt[ti]) chirp = np.zeros(int(300e-3/cell1.chirpdt[ti])) chirp = np.concatenate([chirp, stimamp*np.sin(2*np.pi*t*t**2)]) chirp = np.concatenate([chirp, np.zeros(len(cell1.chirpV[ti]) - len(chirp))]) #Its in pA t = np.arange(0, len(chirp)*cell1.chirpdt[ti], cell1.chirpdt[ti]) analytic_signal = signal.hilbert(chirp) amplitude_envelope = np.abs(analytic_signal) instantaneous_phase = np.unwrap(np.angle(analytic_signal)) instantaneous_frequency = (np.diff(instantaneous_phase) / (2.0*np.pi) * 20000) segs_c = [[(t[j], chirp[j]*1e12), (t[j+1], chirp[j+1]*1e12)] for j in range(len(t)-1)] segs_v = [[(cell1.chirpT[ti][j], cell1.chirpV[ti][j]*1e3), (cell1.chirpT[ti][j+1], cell1.chirpV[ti][j+1]*1e3)] for j in range(len(cell1.chirpT[ti])-1)] line_segments_c = LineCollection(segs_c, cmap='viridis', norm=plt.Normalize(0, max(instantaneous_frequency)), array=instantaneous_frequency) line_segments_v = LineCollection(segs_v, cmap='viridis', norm=plt.Normalize(0, max(instantaneous_frequency)), array=instantaneous_frequency) axB[0].add_collection(line_segments_c) axB[1].add_collection(line_segments_v) plt.colorbar(line_segments_c, label='Frequency (Hz)', cax=axB[3]) # axB[0].plot(t, chirp*1e12) # axB[0].set_xlabel('Time (s)') axB[0].set_ylabel('Current\n(pA)') axB[0].set_xlim(min(t), max(t)) axB[0].set_ylim(min(chirp*1e12), max(chirp*1e12)) axB[0].tick_params(bottom=False, labelbottom=False) # axB[1].plot(cell1.chirpT[i], cell1.chirpV[i]*1e3) axB[1].set_xlabel('Time (s)') axB[1].set_ylabel('Voltage\n(mV)') axB[1].set_xlim(min(cell1.chirpT[ti]), max(cell1.chirpT[ti])) axB[1].set_ylim(min(cell1.chirpV[ti]*1e3), max(cell1.chirpV[ti]*1e3)) validcells = [ "2023_01_04_cell_1", "2023_01_04_cell_2", "2023_01_04_cell_3", "2023_01_04_cell_4", "2023_01_04_cell_5", #At 300pA, firing is not proper "2023_01_04_cell_6", # "2023_01_20_cell_1", #invalid exp "2023_01_20_cell_2", "2023_01_20_cell_3", "2023_01_20_cell_4", "2023_02_13_cell_1", "2023_02_13_cell_2", "2023_02_13_cell_3", "2023_02_13_cell_4", ] if os.path.exists("Impedance_exp.pkl"): freqdf = pd.read_pickle("Impedance_exp.pkl") else: expcell_list = [] for cell in tqdm(validcells): expcell_list.append(expcells.expcell(cell, f'../expdata/Chirp/{cell}')) for cell in tqdm(expcell_list): cell.ampphase_freq(True) freq_list = [] impedance_list = [] phase_list = [] for cell in tqdm(expcell_list): freq_list.append(np.round(np.mean([cell.freq[i] for i in range(len(cell.freq))], axis=0), 5)) impedance_list.append(np.mean([cell.impedance[i] for i in range(len(cell.freq))], axis=0)) phase_list.append(np.mean([cell.phase[i] for i in range(len(cell.freq))], axis=0)) freqdf = pd.DataFrame({"Frequency (Hz)": np.ravel(freq_list), 'Impedance ($\mathrm{M\Omega}$)': np.ravel(impedance_list)*1e-6, 'repeat': np.repeat(np.arange(0,len(freq_list)), len(freq_list[0]))}) freqdf.to_pickle("Impedance_exp.pkl") sns.lineplot(data=freqdf, x="Frequency (Hz)", y='Impedance ($\mathrm{M\Omega}$)', hue='repeat', errorbar=None, ax=axB[2], legend=False, palette=['grey'], alpha=0.2) sns.lineplot(data=freqdf, x="Frequency (Hz)", y='Impedance ($\mathrm{M\Omega}$)', errorbar='se', ax=axB[2], legend=False, color='black') axB[2].set_xscale('log') axB[2].set_xlim(1,500) ################################################################# ############ Panel C ####################### # Load model from the JSON file file_path = "../helperScripts/imp.json" with open(file_path, "r") as file: for line in file: model_ = json.loads(line) if model_["Parameters"]["notes"] == cellname: model = model_ break #### LJP = 15e-3 samplingrate = 20000 stimamp = 30e-12 stim_start_chirp = 0.3 stim_end_chirp = 13.3 stim_start = 0.5 stim_end = 1 tstop = 14.5 stimlist_chirp = [ "soma", "1", ".", "inject", f"(t>{stim_start_chirp} & t<{stim_end_chirp}) * sin(2*3.14159265359*(t-{stim_start_chirp})^3) * {stimamp}", ] tchirp, Ichirp, Vchirp, Cavec = mm.runModel( model, CurrInjection=stimlist_chirp, vClamp=None, refreshKin=False, Truntime=tstop, syn=False, synwg=0, synfq=5, ) freq_l, imp_l, ph_l = fts.calcImpedance(Ichirp, Vchirp, tchirp[1] - tchirp[0]) model["Features"] = {} ( model["Features"]["freq"], model["Features"]["impedance"], model["Features"]["phase"], ) = ( freq_l[(freq_l > 0.5) & (freq_l <= 500)].tolist(), imp_l[(freq_l > 0.5) & (freq_l <= 500)].tolist(), ph_l[(freq_l > 0.5) & (freq_l <= 500)].tolist(), ) cutoff_freq = 50 # Frequency below which to keep the signal normalized_cutoff = cutoff_freq / (0.5 * len(model["Features"]["freq"])) b, a = signal.butter(4, normalized_cutoff, btype='low', analog=False) filtered_signal = signal.filtfilt(b, a, model["Features"]["impedance"]) axC[0].plot(np.mean([cell1.freq[i] for i in range(len(cell1.freq))],axis=0), np.mean([cell1.impedance[i] for i in range(len(cell1.impedance))],axis=0)*1e-6, label=cellname, c='C0') axC[0].plot(model["Features"]["freq"], filtered_signal*1e-6, label=f'model', c='C2') axC[0].set_xlabel('Frequency (Hz)') axC[0].set_ylabel('Impedance\n($\mathrm{M\Omega}$)') # axC[0].legend(frameon=False) axC[0].set_xlim(1,500) axC[0].set_xscale('log') ########### tm25, Ivec, Vtracem25, Cavec = mm.runModel( model, CurrInjection=-25e-12, vClamp=None, refreshKin=False, Truntime=None, syn=False, synwg=0, synfq=5, ) stim_start_exp = 0.3469 modelT = tm25[(tm25>=0.5-stim_start_exp) & (tm25<0.5-stim_start_exp+1)] modelV = Vtracem25[(tm25>=0.5-stim_start_exp) & (tm25<0.5-stim_start_exp+1)] cellT, cellV = expcells.expdata(cell1.preFIfile, 3) cellV = cellV[(cellT>=0) & (cellT<1)] cellT = cellT[(cellT>=0) & (cellT<1)] axC[1].plot((cellT-stim_start_exp+0.5)*1e3, (cellV-LJP)*1e3, label='exp', c='C0') axC[1].plot(modelT*1e3, modelV*1e3, label=f'model', c='C2') axC[1].legend(frameon=False, loc='center left', bbox_to_anchor=(0.8, 0.5)) # axC[1].legend(frameon=False) axC[1].set_xlabel('Time (ms)') axC[1].set_ylabel('Voltage\n(mV)') ############################################################ ############# Panel D and E ############################################### basemodel_1compt_list = [] file_path = "../helperScripts/activemodels_1compt.json" with open(file_path, "r") as file: for line in tqdm(file): basemodel = json.loads(line) basemodel_1compt_list.append(basemodel) basemodel_imp_list = [] file_path = "../helperScripts/activemodels_imp.json" with open(file_path, "r") as file: for line in tqdm(file): basemodel = json.loads(line) basemodel_imp_list.append(basemodel) basemodel_pas_list = [] file_path = "../helperScripts/activemodels_pas.json" with open(file_path, "r") as file: for line in tqdm(file): basemodel = json.loads(line) basemodel_pas_list.append(basemodel) df = pd.DataFrame(columns=["modelID", "type", "DBLO150\n(mV)", "spikes"]) # df.loc[:,'notes'] = [a["Parameters"]["notes"] for a in basemodels_list] modelID = np.tile(np.arange(0,len(basemodel_1compt_list)), 3) modeltype = ( ["1compt"] * len(basemodel_1compt_list) + ["imp"] * len(basemodel_imp_list) + ["pas"] * len(basemodel_pas_list) ) DBLO150_1compt = [a["Features"]["DBLO_1.5e-10"]*1e3 for a in basemodel_1compt_list] DBLO150_imp = [a["Features"]["DBLO_1.5e-10"]*1e3 for a in basemodel_imp_list] DBLO150_pas = [a["Features"]["DBLO_1.5e-10"]*1e3 for a in basemodel_pas_list] DBLO150 = (DBLO150_1compt + DBLO150_imp + DBLO150_pas) spikes = ( [a["Features"]["freq_1.5e-10"] / 2 for a in basemodel_1compt_list] + [a["Features"]["freq_1.5e-10"] / 2 for a in basemodel_imp_list] + [a["Features"]["freq_1.5e-10"] / 2 for a in basemodel_pas_list] ) df.loc[:, "modelID"] = modelID df.loc[:, "type"] = modeltype df.loc[:, "DBLO150\n(mV)"] = DBLO150 df.loc[:, "spikes"] = spikes df = df.convert_dtypes() ### Stats ### impvs1comptvspas_anovaRM = pg.rm_anova(df, dv="DBLO150\n(mV)", within="modelID", subject="type") print('Repeated Measures ANOVA ', impvs1comptvspas_anovaRM) impvs1compt = pg.ttest(x=list(df[df["type"] == "1compt"].loc[:, "DBLO150\n(mV)"]), y=list(df[df["type"] == "imp"].loc[:, "DBLO150\n(mV)"]), paired=True) impvspas = pg.ttest(x=list(df[df["type"] == "pas"].loc[:, "DBLO150\n(mV)"]), y=list(df[df["type"] == "imp"].loc[:, "DBLO150\n(mV)"]), paired=True) pasvs1compt = pg.ttest(x=list(df[df["type"] == "1compt"].loc[:, "DBLO150\n(mV)"]), y=list(df[df["type"] == "pas"].loc[:, "DBLO150\n(mV)"]), paired=True) print("paired ttest", "Imp vs 1compt", impvs1compt["p-val"].values[0]) print("paired ttest", "Imp vs pas", impvspas["p-val"].values[0]) print("paired ttest", "pas vs 1compt", pasvs1compt["p-val"].values[0]) print('Mean DBLO at 150pA\n', df.groupby('type').mean()['DBLO150\n(mV)']) def statannotator(ax, xpair_list, y, d, pvalues_list): d_ = 0 for xpair, pvalue in zip(xpair_list, pvalues_list): ax.plot(xpair, [y + d_, y + d_], c="black") ax.text(np.mean(xpair), y + d_, pvalue, ha="center", va="bottom", c="black") d_ = d_ + d def convert_pvalue_to_asterisks(pvalue): if pvalue <= 0.0001: return "****" elif pvalue <= 0.001: return "***" elif pvalue <= 0.01: return "**" elif pvalue <= 0.05: return "*" return "ns" order = ["1compt", "pas", "imp"] palette = ["C3", "C8", "C2"] ax = sns.boxplot( ax=axD, data=df, x="type", y="DBLO150\n(mV)", order=order, palette=palette, showfliers=False, zorder=2 ) sns.stripplot( ax=ax, data=df, x="type", y="DBLO150\n(mV)", order=order, palette=palette, size=2, alpha=0.4, zorder=3 ) df_ = df[df["modelID"].isin(np.random.randint(0,len(basemodel_1compt_list), 100))] sns.lineplot( ax=ax, data=df_, x="type", y="DBLO150\n(mV)", units="modelID", color=".7", estimator=None, zorder=0, alpha=0.2, linewidth = 1 ) statannotator( axD, [[0, 2], [0, 1], [1, 2]], df["DBLO150\n(mV)"].max(), 2.5, [ convert_pvalue_to_asterisks(a) for a in [impvs1compt["p-val"].values[0], pasvs1compt["p-val"].values[0], impvspas["p-val"].values[0]] ], ) sns.lineplot( ax=axE, data=df, x="spikes", y="DBLO150\n(mV)", hue="type", hue_order=order, palette=palette, style="type", markers="o", markersize=5, err_style="bars", errorbar=("se", 1), ) axE.legend(frameon=False, loc='center left', bbox_to_anchor=(0.95, 0.5)) ########### Panel F ################################# def ourfunc(model): tvec, Ivec, Vmvec,Cavec, Vmvec_dend0 = mm_.runModel(model, refreshKin=False) # pprint(F) # plt.plot(tvec, Vmvec) # plt.show() trace = {} trace["T"] = tvec[(tvec>=stim_start) & ((tvec<stim_end))] * 1e3 trace["V"] = Vmvec[(tvec>=stim_start) & ((tvec<stim_end))] * 1e3 trace["stim_start"] = [trace["T"][0]] trace["stim_end"] = [trace["T"][-1]] trace["stimulus_current"] = [150e-3] traces_results = efel.getFeatureValues( [trace], ["peak_indices", "min_between_peaks_indices"], ) troughidx = traces_results[0]["min_between_peaks_indices"][0]*2 peak0idx = traces_results[0]["peak_indices"][0]*2 Vdiff = Vmvec - Vmvec_dend0 Iaxial_trace = Vdiff/((moose.element('model/elec/soma').Ra + moose.element('model/elec/dend0').Ra)/2) charge = np.trapz(Iaxial_trace[(tvec>=stim_start) & ((tvec<stim_end))][peak0idx:troughidx], trace["T"][peak0idx:troughidx]*1e-3) return [charge, charge] if os.path.exists("charge_impmodels.pkl"): charge_impmodels = [] with open("charge_impmodels.pkl", 'rb') as f: while True: try: charge_impmodels.append(pickle.load(f)) except Exception: break charge_impmodels = np.array(charge_impmodels) charge_pasmodels = [] with open("charge_pasmodels.pkl", 'rb') as f: while True: try: charge_pasmodels.append(pickle.load(f)) except Exception: break charge_pasmodels = np.array(charge_pasmodels) else: charge_impmodels = [] charge_pasmodels = [] charge_impmodels = np.array(Multiprocessthis_appendsave(ourfunc, basemodel_imp_list, [charge_impmodels], ["charge_impmodels.pkl"], seed=1213, npool=0.8)) charge_pasmodels = np.array(Multiprocessthis_appendsave(ourfunc, basemodel_pas_list, [charge_pasmodels], ["charge_pasmodels.pkl"], seed=1213, npool=0.8)) charge_impmodels = charge_impmodels[0] charge_pasmodels = charge_pasmodels[0] df["Backprop charge \n(pF)"] = np.concatenate([np.repeat(None, len(basemodel_1compt_list)),-1*charge_impmodels,-1*charge_pasmodels]) df_charge = df[df["type"] != "1compt"] df_charge.loc[:,"Backprop charge \n(pF)"] = df_charge.loc[:,"Backprop charge \n(pF)"]*1e12 order = ["pas", "imp"] palette = ["C8", "C2"] ax = sns.boxplot( ax=axF, data=df_charge, x="type", y="Backprop charge \n(pF)", order=order, palette=palette, showfliers=False, zorder=2 ) sns.stripplot( ax=ax, data=df_charge, x="type", y="Backprop charge \n(pF)", order=order, palette=palette, size=2, alpha=0.4, zorder=3 ) df_charge_ = df_charge[df_charge["modelID"].isin(np.random.randint(0,len(basemodel_pas_list), 100))] sns.lineplot( ax=ax, data=df_charge_, x="type", y="Backprop charge \n(pF)", units="modelID", color=".7", estimator=None, zorder=0, alpha=0.2, linewidth = 1 ) ### Stats impvspas = pg.ttest(x=list(df_charge[df_charge["type"] == "pas"].loc[:, "Backprop charge \n(pF)"]), y=list(df_charge[df_charge["type"] == "imp"].loc[:, "Backprop charge \n(pF)"]), paired=True) print("paired ttest", "Imp vs pas", impvspas["p-val"].values[0]) print('Mean Axial Charge', df_charge.groupby('type').mean()["Backprop charge \n(pF)"]) print('std Axial Charge', df_charge.groupby('type').std()["Backprop charge \n(pF)"]) statannotator( axF, [[0, 1]], df_charge["Backprop charge \n(pF)"].max(), 0, [ convert_pvalue_to_asterisks(a) for a in [impvs1compt["p-val"].values[0], pasvs1compt["p-val"].values[0], pasvs1compt["p-val"].values[0]] ], ) ################### Panel G ########################## highestDBLOdiffidx = np.argmax(np.array(DBLO150_imp)- np.array(DBLO150_pas)) tvec_imp, Ivec_imp, Vmvec_imp,Cavec_imp, Vmvec_dend0_imp = mm_.runModel(basemodel_imp_list[highestDBLOdiffidx], refreshKin=False) Vdiff_imp = Vmvec_imp - Vmvec_dend0_imp Iaxial_imp_trace = Vdiff_imp/((moose.element('model/elec/soma').Ra + moose.element('model/elec/dend0').Ra)/2) axG.plot(tvec_imp*1e3, Vmvec_imp*1e3, label='imp', color="C2") tvec_pas, Ivec_pas, Vmvec_pas,Cavec_pas, Vmvec_dend0_pas = mm_.runModel(basemodel_pas_list[highestDBLOdiffidx], refreshKin=False) Vdiff_pas = Vmvec_pas - Vmvec_dend0_pas Iaxial_pas_trace = Vdiff_pas/((moose.element('model/elec/soma').Ra + moose.element('model/elec/dend0').Ra)/2) axG.plot(tvec_pas*1e3, Vmvec_pas*1e3, label='pas', color="C8") axG.set_xlim(530,570) axG.set_ylim(-95,-65) axG.set_xlabel('Time (ms)') axG.set_ylabel('Voltage\n(mV)') axG.legend(frameon=False, loc='upper center') axG_ = axG.twinx() axG_.plot(tvec_imp*1e3, Iaxial_imp_trace*-1e9, label='imp', color="C2", linestyle='--') axG_.plot(tvec_imp*1e3, Iaxial_pas_trace*-1e9, label='pas', color="C8", linestyle='--') axG_inset = fig.add_axes([0.73, 0.12, 0.08, 0.035]) axG_inset.plot(tvec_imp*1e3, Vmvec_imp*1e3, color="C2") axG_inset.plot(tvec_pas*1e3, Vmvec_pas*1e3, color="C8") axG_inset.set_xlim(530,570) axG_inset.tick_params(bottom=False, labelbottom=False, left=False, labelleft=False) axG_inset.set_facecolor('none') axG_.set_ylabel('Axial current (nA)') axG_.set_ylim(-11,3) ################################################################# ## show plot ## sns.despine(fig=fig) axB[0].spines["bottom"].set_visible(False) axG.spines["right"].set_visible(True) axG_inset.spines["bottom"].set_visible(False) axG_inset.spines["left"].set_visible(False) plt.savefig('Fig5.png', dpi=300) # plt.savefig('Fig5.svg', dpi=300) # plt.savefig('Fig5.pdf', dpi=300) #% start: automatic generated code from pylustrator plt.figure(1).ax_dict = {ax.get_label(): ax for ax in plt.figure(1).axes} import matplotlib as mpl getattr(plt.figure(1), '_pylustrator_init', lambda: ...)() plt.figure(1).axes[10].legend(loc=(0.6577, 0.352), frameon=False) plt.figure(1).axes[12].set(position=[0.5996, 0.1161, 0.08, 0.035]) #% end: automatic generated code from pylustrator plt.show() ########################### Some analysis ###################### print('1compt', np.sum(df[df["type"]=="1compt"]["DBLO150\n(mV)"]<10), len(df[df["type"]=="1compt"]["DBLO150\n(mV)"]) - np.sum(df[df["type"]=="1compt"]["DBLO150\n(mV)"]<10) - np.sum(df[df["type"]=="1compt"]["DBLO150\n(mV)"]>=14.3), np.sum(df[df["type"]=="1compt"]["DBLO150\n(mV)"]>=14.3) ) print('pas', np.sum(df[df["type"]=="pas"]["DBLO150\n(mV)"]<10), len(df[df["type"]=="pas"]["DBLO150\n(mV)"]) - np.sum(df[df["type"]=="pas"]["DBLO150\n(mV)"]<10) - np.sum(df[df["type"]=="pas"]["DBLO150\n(mV)"]>=14.3), np.sum(df[df["type"]=="pas"]["DBLO150\n(mV)"]>=14.3) ) print('imp', np.sum(df[df["type"]=="imp"]["DBLO150\n(mV)"]<10), len(df[df["type"]=="imp"]["DBLO150\n(mV)"]) - np.sum(df[df["type"]=="imp"]["DBLO150\n(mV)"]<10) - np.sum(df[df["type"]=="imp"]["DBLO150\n(mV)"]>=14.3), np.sum(df[df["type"]=="imp"]["DBLO150\n(mV)"]>=14.3) ) print(np.min(np.array(df[df["type"]=="imp"]["DBLO150\n(mV)"]) - np.array(df[df["type"]=="1compt"]["DBLO150\n(mV)"]))) print(np.mean(np.array(df[df["type"]=="imp"]["DBLO150\n(mV)"]) - np.array(df[df["type"]=="1compt"]["DBLO150\n(mV)"]))) print(np.max(np.array(df[df["type"]=="imp"]["DBLO150\n(mV)"]) - np.array(df[df["type"]=="1compt"]["DBLO150\n(mV)"]))) _ = list(df[df["type"] == "imp"].loc[:, "DBLO150\n(mV)"]) print(f'Max DBLO in imp models - {max(_)}')