From f99c49994736f69970b9fb6921283a14c14da9f4 Mon Sep 17 00:00:00 2001 From: Max Pietsch Date: Wed, 28 Oct 2020 12:07:03 +0100 Subject: [PATCH 1/9] mrpeek: added no text mode (key [t] and cmd line option) --- cmd/mrpeek.cpp | 48 +++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/cmd/mrpeek.cpp b/cmd/mrpeek.cpp index 1ac33c8..0212f8c 100644 --- a/cmd/mrpeek.cpp +++ b/cmd/mrpeek.cpp @@ -119,7 +119,11 @@ void usage () + Option ("zoom", "scale the image size by the supplied factor") - + Argument ("factor").type_float(); + + Argument ("factor").type_float() + + + Option ("text", + "optionally omit text output to show only the sixel image") + + Argument ("yesno").type_bool(); } @@ -138,7 +142,7 @@ int levels = 32; int x_axis, y_axis, slice_axis = 2, plot_axis = slice_axis, vol_axis = -1; value_type pmin = DEFAULT_PMIN, pmax = DEFAULT_PMAX, zoom = 1.0; bool crosshair = true, colorbar = true, orthoview = true, interactive = true; -bool do_plot = false, show_image = true, interpolate = false; +bool do_plot = false, show_image = true, interpolate = false, show_text = true; vector focus (3, 0); // relative to original image grid ArrowMode x_arrow_mode = ARROW_SLICEVOL, arrow_mode = x_arrow_mode; Sixel::ColourMaps colourmaps; @@ -467,9 +471,9 @@ std::string plot (ImageType& image, int plot_axis) // encode buffer and print out: std::string out = move_down (2); - out += CarriageReturn + str(vmax) + move_down(1) + CarriageReturn - + encoder.write() - + ClearLine + str(vmin) + if (show_text) out += CarriageReturn + str(vmax) + move_down(1) + CarriageReturn; + out += encoder.write(); + if (show_text) out += ClearLine + str(vmin) + move_down(1) + CarriageReturn + ClearLine + "plot axis: " + str(plot_axis) + " | x range: [ 0 " + str(plotslice.size() - 1) + " ]"; @@ -500,7 +504,7 @@ std::string display_image (ImageType& image, const Sixel::CMap& cmap, int colour Sixel::Encoder encoder (colourbar_offset + regrid[0].size(1)+regrid[1].size(0)+regrid[2].size(0), panel_y_dim, colourmaps); - draw_colourbar (encoder.viewport (0, 0, COLOURBAR_WIDTH), cmap); + if (colorbar) draw_colourbar (encoder.viewport (0, 0, COLOURBAR_WIDTH), cmap); int x_pos = colourbar_offset; @@ -538,7 +542,7 @@ std::string display_image (ImageType& image, const Sixel::CMap& cmap, int colour const int y_dim = regrid.size (y_axis); Sixel::Encoder encoder (colourbar_offset+x_dim, y_dim, colourmaps); - draw_colourbar (encoder.viewport (0, 0, COLOURBAR_WIDTH), cmap); + if (colorbar) draw_colourbar (encoder.viewport (0, 0, COLOURBAR_WIDTH), cmap); auto view = encoder.viewport(colourbar_offset, 0); display_slice (image, regrid, view, cmap); @@ -580,23 +584,26 @@ std::string display (ImageType& image, Sixel::ColourMaps& colourmaps) if (!cmap.scaling_set()) autoscale (image, cmap); - - out += ClearLine; - if (arrow_mode == ARROW_COLOUR) - out += TextForegroundYellow; - out += str(cmap.max(),4) + TextReset + move_down(1) + position_cursor_at_col (2); + if (show_text) { + out += ClearLine; + if (arrow_mode == ARROW_COLOUR) + out += TextForegroundYellow; + out += str(cmap.max(),4) + TextReset + move_down(1) + position_cursor_at_col (2); + } out += display_image (image, cmap, 2*COLOURBAR_WIDTH) + CarriageReturn + ClearLine; - if (arrow_mode == ARROW_COLOUR) - out += TextForegroundYellow; - out += str(cmap.min(), 4) + TextReset + move_down(1) + CarriageReturn; + if (show_text) { + if (arrow_mode == ARROW_COLOUR) + out += TextForegroundYellow; + out += str(cmap.min(), 4) + TextReset + move_down(1) + CarriageReturn; + } } - out += show_focus(image); + if (show_text) out += show_focus(image); - if (orthoview) { + if (interactive and orthoview and show_text) { out += " | active: "; switch (slice_axis) { case (0): out += std::string (TextUnderscore) + "s" + TextReset + "agittal"; break; @@ -606,7 +613,7 @@ std::string display (ImageType& image, Sixel::ColourMaps& colourmaps) }; } - if (interactive) + if (interactive and show_text) out += std::string(" | help: ") + TextUnderscore + "?" + TextReset; if (do_plot) out += plot (image, plot_axis); @@ -643,6 +650,7 @@ void show_help () + key ("a / s / c", "axial / sagittal / coronal projection") + key ("o", "toggle orthoview") + key ("m", "toggle image display") + + key ("t", "toggle text overlay") + key ("v", "choose volume dimension") + key ("- / +", "zoom out / in") + key ("x / ", "toggle arrow key crosshairs control") @@ -741,7 +749,6 @@ class CallBack : public EventLoop::CallBack if (need_update) { need_update = false; std::cout << CursorHome << display (image, colourmaps); - //std::cout << "UPDATE "; std::cout.flush(); } return true;; @@ -826,6 +833,7 @@ class CallBack : public EventLoop::CallBack case 's': slice_axis = 0; if (!orthoview) std::cout << ClearScreen; break; case 'c': slice_axis = 1; if (!orthoview) std::cout << ClearScreen; break; case 'o': orthoview = !orthoview; std::cout << ClearScreen; break; + case 't': show_text = colorbar = !show_text; std::cout << ClearScreen; break; case 'm': show_image = !show_image; std::cout << ClearScreen; break; case 'r': focus[x_axis] = std::round (image.size(x_axis)/2); focus[x_axis] = std::round (image.size(x_axis)/2); focus[slice_axis] = std::round (image.size(slice_axis)/2); break; @@ -944,6 +952,8 @@ void run () INFO("zoom: " + str(zoom)); zoom /= std::min (std::min (image.spacing(0), image.spacing(1)), image.spacing(2)); + colorbar = show_text = get_option_value ("text", true); + #ifndef MRTRIX_WINDOWS //CONF option: MRPeekInteractive if (!interactive or !get_option_value ("interactive", File::Config::get_bool ("MRPeekInteractive", true))) { From d194bd6f8d4659cf82ac9b927766253bb68de0eb Mon Sep 17 00:00:00 2001 From: Max Pietsch Date: Wed, 28 Oct 2020 12:33:06 +0100 Subject: [PATCH 2/9] mrpeek: added command line option to disable main image --- cmd/mrpeek.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/mrpeek.cpp b/cmd/mrpeek.cpp index 0212f8c..99fa87f 100644 --- a/cmd/mrpeek.cpp +++ b/cmd/mrpeek.cpp @@ -123,6 +123,10 @@ void usage () + Option ("text", "optionally omit text output to show only the sixel image") + + Argument ("yesno").type_bool() + + + Option ("image", + "render the main image. Default: true") + Argument ("yesno").type_bool(); } @@ -430,7 +434,7 @@ std::string plot (ImageType& image, int plot_axis) assert(y < y_dim); assert(y >= 0); - if ((plot_axis < 3 && index == focus[plot_axis]) || (plot_axis > 2 && index == current_index)) { + if (crosshair && ((plot_axis < 3 && index == focus[plot_axis]) || (plot_axis > 2 && index == current_index))) { // focus position: draw line for (int r = 0; r < y_offset; ++r) canvas (x_offset+x, r) = CROSSHAIR_COLOUR; @@ -953,6 +957,7 @@ void run () zoom /= std::min (std::min (image.spacing(0), image.spacing(1)), image.spacing(2)); colorbar = show_text = get_option_value ("text", true); + show_image = get_option_value ("image", true); #ifndef MRTRIX_WINDOWS //CONF option: MRPeekInteractive From dfd100357c91b2c742192295fab2a9cb41ded700 Mon Sep 17 00:00:00 2001 From: Max Pietsch Date: Thu, 29 Oct 2020 09:53:38 +0100 Subject: [PATCH 3/9] mrpeek: remove alternative tokens --- cmd/mrpeek.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/mrpeek.cpp b/cmd/mrpeek.cpp index 99fa87f..9714bad 100644 --- a/cmd/mrpeek.cpp +++ b/cmd/mrpeek.cpp @@ -607,7 +607,7 @@ std::string display (ImageType& image, Sixel::ColourMaps& colourmaps) if (show_text) out += show_focus(image); - if (interactive and orthoview and show_text) { + if (interactive && orthoview && show_text) { out += " | active: "; switch (slice_axis) { case (0): out += std::string (TextUnderscore) + "s" + TextReset + "agittal"; break; @@ -617,7 +617,7 @@ std::string display (ImageType& image, Sixel::ColourMaps& colourmaps) }; } - if (interactive and show_text) + if (interactive && show_text) out += std::string(" | help: ") + TextUnderscore + "?" + TextReset; if (do_plot) out += plot (image, plot_axis); From e9dcfda975db99645382b29886ce67410b3f8318 Mon Sep 17 00:00:00 2001 From: Max Pietsch Date: Thu, 29 Oct 2020 10:33:03 +0100 Subject: [PATCH 4/9] mrpeek: simplify options - removed axis and orthoview options. - interactive y/n --> batch - added sagittal, coronal, axial options which deactivate orthoview - image y/n and text y/n --> noimage notext --- cmd/mrpeek.cpp | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/cmd/mrpeek.cpp b/cmd/mrpeek.cpp index 9714bad..82055e1 100644 --- a/cmd/mrpeek.cpp +++ b/cmd/mrpeek.cpp @@ -67,23 +67,22 @@ void usage () OPTIONS #ifndef MRTRIX_WINDOWS - + Option ("interactive", - "interactive mode. Default is true.") - + Argument ("yesno").type_bool() + + Option ("batch", + "disables interactive mode") #endif - + Option ("axis", - "specify projection of slice, as an integer representing the slice normal: " - "0: L/R (sagittal); 1: A/P (coronal); 2 I/S (axial). Default is 2 (axial). ") - + Argument ("index").type_integer (0) + + Option ("sagittal", + "view sagittal projection only. Default: orthoview") + + + Option ("coronal", + "view coronal projection only. Default: orthoview") + + + Option ("axial", + "view axial projection only. Default: orthoview") + Option ("slice", "select slice to display") + Argument ("number").type_integer(0) - + Option ("orthoview", - "display three orthogonal or a single plane. Default is true.") - + Argument ("yesno").type_bool() - + Option ("plot", "specify plot dimension: " "0: L/R (sagittal); 1: A/P (coronal); 2 I/S (axial); 3 volumes... ") @@ -121,13 +120,11 @@ void usage () "scale the image size by the supplied factor") + Argument ("factor").type_float() - + Option ("text", - "optionally omit text output to show only the sixel image") - + Argument ("yesno").type_bool() + + Option ("notext", + "omit text output to show only the sixel image") - + Option ("image", - "render the main image. Default: true") - + Argument ("yesno").type_bool(); + + Option ("noimage", + "do not render the main image"); } @@ -898,7 +895,13 @@ void run () { auto image = Image::open (argument[0]); - slice_axis = get_option_value ("axis", slice_axis); + size_t projection_axes[3] = {get_options("sagittal").size(), get_options("coronal").size(), get_options("axial").size()}; + size_t psum = 0; + for (int i = 0; i < 3; ++i) { + if (projection_axes[i]) { ++psum; slice_axis = i; } + if (psum > 1) throw Exception("Projection axes options are mutually exclusive."); + } + orthoview = psum == 0; vol_axis = image.ndim() > 3 ? 3 : -1; focus[slice_axis] = get_option_value ("slice", image.size(slice_axis)/2); set_axes(); @@ -946,9 +949,6 @@ void run () } } - //CONF option: MRPeekOrthoView - orthoview = get_option_value ("orthoview", File::Config::get_bool ("MRPeekOrthoView", orthoview)); - //CONF option: MRPeekScaleImage zoom = get_option_value ("zoom", MR::File::Config::get_float ("MRPeekZoom", zoom)); if (zoom <= 0) @@ -956,12 +956,12 @@ void run () INFO("zoom: " + str(zoom)); zoom /= std::min (std::min (image.spacing(0), image.spacing(1)), image.spacing(2)); - colorbar = show_text = get_option_value ("text", true); - show_image = get_option_value ("image", true); + colorbar = show_text = !get_options ("notext").size(); + show_image = !get_options ("noimage").size(); #ifndef MRTRIX_WINDOWS //CONF option: MRPeekInteractive - if (!interactive or !get_option_value ("interactive", File::Config::get_bool ("MRPeekInteractive", true))) { + if (!interactive or get_options("batch").size()) { #endif interactive = false; std::cout << display (image, colourmaps) << "\n"; From a843561463930651c5d203fd8197a94e3d0fe587 Mon Sep 17 00:00:00 2001 From: J-Donald Tournier Date: Thu, 29 Oct 2020 12:50:05 +0000 Subject: [PATCH 5/9] mrpeek: use non-interactive mode if stdout is not TTY --- cmd/mrpeek.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cmd/mrpeek.cpp b/cmd/mrpeek.cpp index 82055e1..934d50d 100644 --- a/cmd/mrpeek.cpp +++ b/cmd/mrpeek.cpp @@ -959,17 +959,19 @@ void run () colorbar = show_text = !get_options ("notext").size(); show_image = !get_options ("noimage").size(); -#ifndef MRTRIX_WINDOWS - //CONF option: MRPeekInteractive - if (!interactive or get_options("batch").size()) { -#endif +#ifdef MRTRIX_WINDOWS + interactive = false; + std::cout << display (image, colourmaps) << "\n"; +#else + interactive = isatty (STDOUT_FILENO); + if (get_options ("batch").size()) interactive = false; + + if (!interactive) { std::cout << display (image, colourmaps) << "\n"; return; -#ifndef MRTRIX_WINDOWS } - try { // start loop enter_raw_mode(); From 5f78ff7fea6a72c5ab063e4f57b98d221720fec8 Mon Sep 17 00:00:00 2001 From: J-Donald Tournier Date: Thu, 29 Oct 2020 15:25:09 +0000 Subject: [PATCH 6/9] mrpeek: alternate -focus option to set focus position and -nocrosshairs option to hide crosshairs --- cmd/mrpeek.cpp | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/cmd/mrpeek.cpp b/cmd/mrpeek.cpp index 934d50d..53e2e73 100644 --- a/cmd/mrpeek.cpp +++ b/cmd/mrpeek.cpp @@ -79,10 +79,6 @@ void usage () + Option ("axial", "view axial projection only. Default: orthoview") - + Option ("slice", - "select slice to display") - + Argument ("number").type_integer(0) - + Option ("plot", "specify plot dimension: " "0: L/R (sagittal); 1: A/P (coronal); 2 I/S (axial); 3 volumes... ") @@ -107,10 +103,12 @@ void usage () ". Default is " + colourmap_choices_std[0] + ".") + Argument ("name").type_choice (colourmap_choices_cstr.data()) - + Option ("crosshairs", - "draw crosshairs at specified position. Set to negative position to hide.") - + Argument ("x").type_integer() - + Argument ("y").type_integer() + + Option ("focus", + "set focus (crosshairs) at specified position, as a comma-separated " + "list of values. Use empty entries to leave as default (e.g. '-focus ,,100' " + "to place the focus on slice 100 along the z-axis, or '-focus ,,,4' to " + "select volume 4).") + + Argument ("pos").type_sequence_float() + Option ("levels", "number of intensity levels in the colourmap. Default is 32.") @@ -123,6 +121,9 @@ void usage () + Option ("notext", "omit text output to show only the sixel image") + + Option ("nocrosshairs", + "do not render crosshairs at the focus") + + Option ("noimage", "do not render the main image"); } @@ -903,13 +904,9 @@ void run () } orthoview = psum == 0; vol_axis = image.ndim() > 3 ? 3 : -1; - focus[slice_axis] = get_option_value ("slice", image.size(slice_axis)/2); set_axes(); - focus[x_axis] = std::round (image.size(x_axis)/2); - focus[y_axis] = std::round (image.size(y_axis)/2); - - if (focus[slice_axis] >= image.size(slice_axis)) - throw Exception("slice " + str(focus[slice_axis]) + " exceeds image size (" + str(image.size(slice_axis)) + ") in axis " + str(slice_axis)); + for (int a = 0; a < 3; ++a) + focus[a] = std::round (image.size(a)/2.0); int colourmap_ID = get_option_value ("colourmap", 0); @@ -937,18 +934,26 @@ void run () pmax = opt[0][1]; } - opt = get_options ("crosshairs"); + opt = get_options ("focus"); if (opt.size()) { - int x = opt[0][0]; - int y = opt[0][1]; - if (x<0 || y<0) { - crosshair = false; - } else { - focus[x_axis] = opt[0][0]; - focus[y_axis] = opt[0][1]; + vector p = opt[0][0]; + if (p.size() > image.ndim()) + throw Exception ("number of indices passed to -focus option exceeds image dimensions"); + for (unsigned int n = 0; n < p.size(); ++n) { + if (std::isfinite (p[n])) { + if (p[n] < 0 || p[n] > image.size(n)-1) + throw Exception ("position passed to -focus option is out of bounds for axis "+str(n)); + if (n < 3) + focus[n] = p[n]; + else + image.index(n) = p[n]; + } } } + if (get_options ("nocrosshairs").size()) + crosshair = false; + //CONF option: MRPeekScaleImage zoom = get_option_value ("zoom", MR::File::Config::get_float ("MRPeekZoom", zoom)); if (zoom <= 0) From fb17b8938ebd462fedd175d45dfcaa9cbe0a8a6b Mon Sep 17 00:00:00 2001 From: Max Pietsch Date: Fri, 30 Oct 2020 10:50:30 +0100 Subject: [PATCH 7/9] mrpeek: focus is explicitly integer valued --- cmd/mrpeek.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/mrpeek.cpp b/cmd/mrpeek.cpp index 53e2e73..cca1c43 100644 --- a/cmd/mrpeek.cpp +++ b/cmd/mrpeek.cpp @@ -105,10 +105,10 @@ void usage () + Option ("focus", "set focus (crosshairs) at specified position, as a comma-separated " - "list of values. Use empty entries to leave as default (e.g. '-focus ,,100' " + "list of integer-valued voxel indices. Use empty entries to leave as default (e.g. '-focus ,,100' " "to place the focus on slice 100 along the z-axis, or '-focus ,,,4' to " "select volume 4).") - + Argument ("pos").type_sequence_float() + + Argument ("pos").type_sequence_int() + Option ("levels", "number of intensity levels in the colourmap. Default is 32.") @@ -936,7 +936,7 @@ void run () opt = get_options ("focus"); if (opt.size()) { - vector p = opt[0][0]; + vector p = opt[0][0]; if (p.size() > image.ndim()) throw Exception ("number of indices passed to -focus option exceeds image dimensions"); for (unsigned int n = 0; n < p.size(); ++n) { From 0b73d2d1aa9de6b0adf3c48cf95862f3b5b6caca Mon Sep 17 00:00:00 2001 From: Max Pietsch Date: Fri, 30 Oct 2020 11:19:23 +0100 Subject: [PATCH 8/9] Revert "mrpeek: focus is explicitly integer valued" This reverts commit fb17b8938ebd462fedd175d45dfcaa9cbe0a8a6b. --- cmd/mrpeek.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/mrpeek.cpp b/cmd/mrpeek.cpp index cca1c43..53e2e73 100644 --- a/cmd/mrpeek.cpp +++ b/cmd/mrpeek.cpp @@ -105,10 +105,10 @@ void usage () + Option ("focus", "set focus (crosshairs) at specified position, as a comma-separated " - "list of integer-valued voxel indices. Use empty entries to leave as default (e.g. '-focus ,,100' " + "list of values. Use empty entries to leave as default (e.g. '-focus ,,100' " "to place the focus on slice 100 along the z-axis, or '-focus ,,,4' to " "select volume 4).") - + Argument ("pos").type_sequence_int() + + Argument ("pos").type_sequence_float() + Option ("levels", "number of intensity levels in the colourmap. Default is 32.") @@ -936,7 +936,7 @@ void run () opt = get_options ("focus"); if (opt.size()) { - vector p = opt[0][0]; + vector p = opt[0][0]; if (p.size() > image.ndim()) throw Exception ("number of indices passed to -focus option exceeds image dimensions"); for (unsigned int n = 0; n < p.size(); ++n) { From c3fddd29b49cc6a38cf49d91bd9d6a4dc1b22fb1 Mon Sep 17 00:00:00 2001 From: Max Pietsch Date: Fri, 30 Oct 2020 11:25:24 +0100 Subject: [PATCH 9/9] mrpeek: focus: round instead of truncate to integer --- cmd/mrpeek.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/mrpeek.cpp b/cmd/mrpeek.cpp index 53e2e73..ab2d9de 100644 --- a/cmd/mrpeek.cpp +++ b/cmd/mrpeek.cpp @@ -941,6 +941,7 @@ void run () throw Exception ("number of indices passed to -focus option exceeds image dimensions"); for (unsigned int n = 0; n < p.size(); ++n) { if (std::isfinite (p[n])) { + p[n] = Math::round(p[n]); if (p[n] < 0 || p[n] > image.size(n)-1) throw Exception ("position passed to -focus option is out of bounds for axis "+str(n)); if (n < 3)