diff --git a/src/_version.py b/src/_version.py index 5021151..d7ec603 100644 --- a/src/_version.py +++ b/src/_version.py @@ -1,4 +1,4 @@ """version.py Version of the software """ -__version__ = "0.6.5" +__version__ = "0.7.0" diff --git a/src/plot.py b/src/plot.py index 8e27d60..c0b0d1f 100644 --- a/src/plot.py +++ b/src/plot.py @@ -1321,7 +1321,7 @@ def argparser(): parser.add_argument('--no_samples', required=False, action='store_false', help="hide sample points") parser.add_argument('--save_svg', required=False, action='store_true', help="save as svg. tweak --region and --xrange to capture the necessary part of the plot") parser.add_argument('--xrange', required=False, type=int, default=PLOT_X_RANGE, help="initial x range") - parser.add_argument('-o', '--output_dir', required=True, type=str, default="", help="output dir") + parser.add_argument('-o', '--output_dir', required=False, type=str, default="", help="output dir") return parser if __name__ == "__main__": diff --git a/src/plot_signal.py b/src/plot_signal.py index 396080b..204fa56 100644 --- a/src/plot_signal.py +++ b/src/plot_signal.py @@ -46,7 +46,7 @@ def plot_function(args, p, read_id, signal_tuple, draw_data): p.line('x', 'y', name="sig_plot_line", line_width=2, source=source) # add a circle renderer with a size, color, and alpha sample_labels = p.circle(x, y, radius=draw_data["point_size"], color="red", alpha=0.5, visible=draw_data['no_samples']) - toggle_samples = Toggle(label="samples", button_type="danger", active=True, height=30, width=60) + toggle_samples = Toggle(label="samples", button_type="default", active=draw_data['no_samples'], height=30, width=60) toggle_samples.js_link('active', sample_labels, 'visible') # show the tooltip @@ -101,7 +101,7 @@ def run(args): indt = "\t\t\t\t\t\t\t\t" draw_data = {} draw_data["point_size"] = args.point_size - draw_data["no_samples"] = args.no_samples + draw_data["no_samples"] = args.show_samples draw_data["xrange"] = args.xrange draw_data["sig_dir"] = "->" if args.reverse_signal: @@ -112,6 +112,12 @@ def run(args): end_index = int(end_index) # keep it 1-based for slicing x, x_real, y = plot_utils.load_signal(args, args.read_id, s5, start_index, end_index, scale_params) + # resolve -1 sentinel to actual signal length + if end_index == -1: + end_index = x_real[-1] if len(x_real) > 0 else start_index + 1 + if draw_data["xrange"] == -1: + draw_data["xrange"] = len(x) + if args.reverse_signal: # reverse the signal y = np.flip(y) @@ -163,10 +169,10 @@ def argparser(): parser.add_argument('--no_pa', required=False, action='store_false', help="skip converting the signal to pA values") parser.add_argument('--remove_signal_outliers', required=False, action='store_true', help="remove signal outliers that are outside the raw value range [0, 2000]") parser.add_argument('--point_size', required=False, type=int, default=0.5, help="signal point radius [0.5]") - parser.add_argument('--sig_plot_limit', required=False, type=int, default=SIG_PLOT_LENGTH, help="maximum number of signal samples to plot") - parser.add_argument('--no_samples', required=False, action='store_false', help="hide sample points") + parser.add_argument('--sig_plot_limit', required=False, type=int, default=-1, help="maximum number of signal samples to plot (-1 for full signal)") + parser.add_argument('--show_samples', required=False, action='store_true', help="show sample points (default: hidden)") parser.add_argument('--save_svg', required=False, action='store_true', help="save as svg. tweak --region and --xrange to capture the necessary part of the plot") - parser.add_argument('--xrange', required=False, type=int, default=PLOT_X_RANGE, help="initial x range") + parser.add_argument('--xrange', required=False, type=int, default=-1, help="initial x range to display (-1 for full signal)") parser.add_argument('-o', '--output_dir', required=True, type=str, default="", help="output dir") return parser diff --git a/src/plot_utils.py b/src/plot_utils.py index e45105f..8f431f2 100644 --- a/src/plot_utils.py +++ b/src/plot_utils.py @@ -14,6 +14,7 @@ from bokeh.io.export import export_svgs import os +import sys PLOT_X_RANGE = 300 PLOT_HEIGHT = 600 @@ -91,20 +92,17 @@ def read_readid_color_file(filepath, default_color='#1f77b4'): def svg_export_works(output_dir): try: - # Create dummy Bokeh plot p = figure(title="SVG test") p.line([0, 1], [0, 1]) p.output_backend = "svg" - - # Fixed test file name temp_svg_path = output_dir + "/__svg_test.svg" - export_svgs(p, filename=temp_svg_path) - - # Optionally clean up os.remove(temp_svg_path) - except Exception as e: - raise RuntimeError(f"SVG export requires a headless browser. None (Firefox+geckodriver or Chromium+chromedriver) found in the PATH : {e}") + except Exception: + print("Error: --save_svg requires a headless browser which was not found on PATH.") + print(" Install Firefox + geckodriver: conda install -c conda-forge firefox geckodriver") + print(" Install Chromium + chromedriver: apt install chromium-browser chromium-driver") + sys.exit(1) def get_base_color_map(): base_color_map = {'A': '#d6f5d6', 'C': '#ccccff', 'T': '#ffcccc', 'G': '#ffedcc', 'U': '#ffcccc', 'N': '#fafafe', 'M': '#000000', 'R': '#000000', 'W': '#000000', 'S': '#000000', 'Y': '#000000', 'K': '#000000', 'V': '#000000', 'H': '#000000', 'D': '#000000', 'B': '#000000'}