From 775d91db40393a6ecc8bce99f750207d0587ee31 Mon Sep 17 00:00:00 2001 From: pedrodevog Date: Fri, 23 May 2025 16:26:52 +0200 Subject: [PATCH 1/3] Added a save_as_pdf function --- ecg_plot/__init__.py | 2 +- ecg_plot/ecg_plot.py | 25 ++++++++++++++++++++++++- ecg_plot_test.py | 3 ++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/ecg_plot/__init__.py b/ecg_plot/__init__.py index 8cbcfc5..98ab894 100644 --- a/ecg_plot/__init__.py +++ b/ecg_plot/__init__.py @@ -1 +1 @@ -from .ecg_plot import plot_12, plot_1, show, show_svg, save_as_png, save_as_svg, save_as_jpg, plot \ No newline at end of file +from .ecg_plot import plot_12, plot_1, show, show_svg, save_as_png, save_as_svg, save_as_jpg, save_as_pdf, plot \ No newline at end of file diff --git a/ecg_plot/ecg_plot.py b/ecg_plot/ecg_plot.py index e7d1e31..1c8ec86 100644 --- a/ecg_plot/ecg_plot.py +++ b/ecg_plot/ecg_plot.py @@ -51,6 +51,9 @@ def plot_12( speed : signal speed on display, defaults to 50 mm / sec voltage : signal voltage on display, defaults to 20 mm / mV line_width : line width, default to 0.6 + + # Returns + fig : figure object """ if not lead_order: lead_order = list(range(0,len(ecg))) @@ -88,6 +91,7 @@ def plot_12( t_ax.tick_params(axis='x',rotation=90) _ax_plot(t_ax, np.arange(0, len(ecg[t_lead])*step, step), ecg[t_lead], seconds) + return fig def plot( ecg, @@ -116,6 +120,9 @@ def plot( show_lead_name : show lead name show_grid : show grid show_separate_line : show separate line + + # Returns + fig : figure object """ if not lead_order: @@ -193,6 +200,7 @@ def plot( linewidth=line_width * display_factor, color=color_line ) + return fig def plot_1(ecg, sample_rate=500, title = 'ECG', fig_width = 15, fig_height = 2, line_w = 0.5, ecg_amp = 1.8, timetick = 0.2): @@ -203,8 +211,11 @@ def plot_1(ecg, sample_rate=500, title = 'ECG', fig_width = 15, fig_height = 2, title : Title which will be shown on top off chart fig_width : The width of the plot fig_height : The height of the plot + + # Returns + fig : figure object """ - plt.figure(figsize=(fig_width,fig_height)) + fig = plt.figure(figsize=(fig_width,fig_height)) plt.suptitle(title) plt.subplots_adjust( hspace = 0, @@ -220,6 +231,7 @@ def plot_1(ecg, sample_rate=500, title = 'ECG', fig_width = 15, fig_height = 2, #plt.rcParams['lines.linewidth'] = 5 step = 1.0/sample_rate _ax_plot(ax,np.arange(0,len(ecg)*step,step),ecg, seconds, line_w, ecg_amp,timetick) + return fig DEFAULT_PATH = './' show_counter = 1 @@ -270,3 +282,14 @@ def save_as_jpg(file_name, path = DEFAULT_PATH): plt.ioff() plt.savefig(path + file_name + '.jpg') plt.close() + +def save_as_pdf(file_name, fig, path = DEFAULT_PATH): + """Plot multi lead ECG chart. + # Arguments + file_name: file_name + path : path to save image, defaults to current folder + """ + plt.ioff() + fig.savefig(os.path.join(path, file_name + '.pdf'), + format='pdf') + plt.close(fig) diff --git a/ecg_plot_test.py b/ecg_plot_test.py index 094c38d..23056b2 100644 --- a/ecg_plot_test.py +++ b/ecg_plot_test.py @@ -23,6 +23,7 @@ def load_ecg_from_mat(file_path): # ecg_plot.plot(test_ecg, sample_rate = 500, title = '', columns = 1,show_grid = False, show_lead_name = False, style='bw') # ecg_plot.plot(test_ecg, sample_rate = 500, title = '', columns = 3) -ecg_plot.plot(test_ecg, title='test') +ecg = ecg_plot.plot(test_ecg, title='test') ecg_plot.save_as_png('example_ecg_1','tmp/') +ecg_plot.save_as_pdf('example_ecg_1', ecg,'tmp/') ecg_plot.show() From fc58d37feafe6f7462970e6a2d4f10bf26bd945d Mon Sep 17 00:00:00 2001 From: pedrodevog Date: Fri, 23 May 2025 16:48:11 +0200 Subject: [PATCH 2/3] tight layout (cut off pdf borders) + fix xticks for show grid --- ecg_plot/ecg_plot.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/ecg_plot/ecg_plot.py b/ecg_plot/ecg_plot.py index 1c8ec86..f024faf 100644 --- a/ecg_plot/ecg_plot.py +++ b/ecg_plot/ecg_plot.py @@ -161,8 +161,25 @@ def plot( color_line = (0,0,0.7) if(show_grid): - ax.set_xticks(np.arange(x_min,x_max,0.2)) - ax.set_yticks(np.arange(y_min,y_max,0.5)) + ax.set_xticks(np.arange(x_min, x_max, 0.2)) + ax.set_yticks(np.arange(y_min, y_max, 0.5)) + + # Set tick labels only at every 1.0 interval + xtick_labels = [] + for val in np.arange(x_min, x_max, 0.2): + if np.isclose(val % 1.0, 0, atol=1e-8): + xtick_labels.append(f"{val:g}") + else: + xtick_labels.append("") + ax.set_xticklabels(xtick_labels) + + ytick_labels = [] + for val in np.arange(y_min, y_max, 0.5): + if np.isclose((val - y_min) % 1.0, 0, atol=1e-8): + ytick_labels.append(f"{val:g}") + else: + ytick_labels.append("") + ax.set_yticklabels(ytick_labels) ax.minorticks_on() @@ -291,5 +308,6 @@ def save_as_pdf(file_name, fig, path = DEFAULT_PATH): """ plt.ioff() fig.savefig(os.path.join(path, file_name + '.pdf'), - format='pdf') + format='pdf', + bbox_inches='tight') plt.close(fig) From 99a70a6180ccd0e811c5186a53cbff5c9653a71d Mon Sep 17 00:00:00 2001 From: pedrodevog Date: Fri, 23 May 2025 16:54:26 +0200 Subject: [PATCH 3/3] update readme --- README.md | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4d24131..f660ee8 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## Plot standard ECG chart from data. * Support both direct plotting and plotting SVG preview in browser (currently only works on mac) -* Support saving PNG and SVG to disk +* Support saving PNG, JPG, SVG or PDF to disk * Support customer defined lead order * Support customer defined column count @@ -44,7 +44,7 @@ params: import ecg_plot ecg = load_data() # load data should be implemented by yourself -ecg_plot.plot(ecg, sample_rate = 500, title = 'ECG 12') +ecg_plot.plot(ecg, sample_rate=500, title='ECG 12') ecg_plot.show() ``` @@ -55,7 +55,7 @@ ecg_plot.show() import ecg_plot ecg = load_data() # load data should be implemented by yourself -ecg_plot.plot_1(ecg[1], sample_rate=500, title = 'ECG') +ecg_plot.plot_1(ecg[1], sample_rate=500, title='ECG') ecg_plot.show() ``` @@ -65,8 +65,19 @@ ecg_plot.show() import ecg_plot ecg = load_data() # load data should be implemented by yourself -ecg_plot.plot_12(ecg, sample_rate = 500, title = 'ECG 12') -ecg_plot.save_as_png('example_ecg','tmp/') +ecg_plot.plot_12(ecg, sample_rate=500, title='ECG 12') +ecg_plot.save_as_png('example_ecg', 'tmp/') + +``` + +#### Save result as pdf + +``` +import ecg_plot + +ecg = load_data() # load data should be implemented by yourself +fig = ecg_plot.plot_12(ecg, sample_rate = 500, title = 'ECG 12') +ecg_plot.save_as_pdf('example_ecg', fig, 'tmp/') ```