From 5a2b40b2e24f8455f701accd2dde59e84c945c5b Mon Sep 17 00:00:00 2001 From: twagner9 Date: Tue, 12 Aug 2025 13:45:34 -0400 Subject: [PATCH 01/12] Fix multiple instances of display if there is an existing one -Makes the first display instance a server with a listening socket in /tmp. Subsequent attempts to open a display (with arguments) will instead be opened in the existing instance of the display. It is possible to still have multiple displays by opening a new instance of the program without any arguments. --- src/Makefile.am | 2 +- src/gui/DisplayFrame.cpp | 11 + src/gui/DisplayFrame.h | 1 + src/programs/cisTEM_display/DisplayFrame.cpp | 643 ++++++++++++++++++ src/programs/cisTEM_display/DisplayServer.cpp | 88 +++ src/programs/cisTEM_display/DisplayServer.h | 57 ++ .../cisTEM_display/cisTEM_display.cpp | 53 ++ 7 files changed, 854 insertions(+), 1 deletion(-) create mode 100644 src/programs/cisTEM_display/DisplayFrame.cpp create mode 100644 src/programs/cisTEM_display/DisplayServer.cpp create mode 100644 src/programs/cisTEM_display/DisplayServer.h diff --git a/src/Makefile.am b/src/Makefile.am index 50851c3e8..d87f5d469 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -773,7 +773,7 @@ cisTEM_CPPFLAGS = $(WX_CPPFLAGS) cisTEM_LDADD = libguicore.a libcore.a $(WX_LIBS) $(MKL_LIBS) cisTEM_LIBTOOLFLAGS = $(LIBTOOL_FLAGS) -cisTEM_display_SOURCES = programs/cisTEM_display/cisTEM_display.cpp programs/cisTEM_display/display_gui.cpp gui/DisplayPanel.cpp gui/DisplayFrame.cpp +cisTEM_display_SOURCES = programs/cisTEM_display/cisTEM_display.cpp programs/cisTEM_display/display_gui.cpp gui/DisplayPanel.cpp gui/DisplayFrame.cpp programs/cisTEM_display/DisplayServer.cpp cisTEM_display_CXXFLAGS = $(WX_CPPFLAGS) cisTEM_display_CPPFLAGS = $(WX_CPPFLAGS) cisTEM_display_LDADD = libguicore.a libcore.a $(WX_LIBS) $(MKL_LIBS) diff --git a/src/gui/DisplayFrame.cpp b/src/gui/DisplayFrame.cpp index 55a405aeb..93f91f70d 100644 --- a/src/gui/DisplayFrame.cpp +++ b/src/gui/DisplayFrame.cpp @@ -1,4 +1,5 @@ #include "../core/gui_core_headers.h" +#include "../programs/cisTEM_display/DisplayServer.h" // includes wxEVT_SERVER_OPEN_FILE DisplayFrame::DisplayFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : DisplayFrameParent(NULL, wxID_ANY, title, pos, size, style) { @@ -36,6 +37,7 @@ DisplayFrame::DisplayFrame(wxWindow* parent, wxWindowID id, const wxString& titl } Bind(wxEVT_CHAR_HOOK, &DisplayFrame::OnCharHook, this); + Bind(EVT_SERVER_OPEN_FILE, &DisplayFrame::OnServerOpenFile, this); } DisplayFrame::~DisplayFrame( ) { @@ -59,6 +61,15 @@ void DisplayFrame::OnFileOpenClick(wxCommandEvent& event) { cisTEMDisplayPanel->OnOpen(event); } +void DisplayFrame::OnServerOpenFile(wxCommandEvent& event) { + wxString filename = event.GetString( ); + if ( cisTEMDisplayPanel ) { + cisTEMDisplayPanel->OpenFile(filename, filename); + this->Raise( ); + this->SetFocus( ); + } +} + void DisplayFrame::OnCloseTabClick(wxCommandEvent& event) { if ( cisTEMDisplayPanel->ReturnCurrentPanel( ) != NULL ) { cisTEMDisplayPanel->my_notebook->DeletePage(cisTEMDisplayPanel->my_notebook->GetSelection( )); diff --git a/src/gui/DisplayFrame.h b/src/gui/DisplayFrame.h index ef38cd609..5c8cf1423 100644 --- a/src/gui/DisplayFrame.h +++ b/src/gui/DisplayFrame.h @@ -13,6 +13,7 @@ class DisplayFrame : public DisplayFrameParent { //Additional functions void DisableAllToolbarButtons( ); void EnableAllToolbarButtons( ); + void OnServerOpenFile(wxCommandEvent& event); // GUI event functions void OnCharHook(wxKeyEvent& event); diff --git a/src/programs/cisTEM_display/DisplayFrame.cpp b/src/programs/cisTEM_display/DisplayFrame.cpp new file mode 100644 index 000000000..93f91f70d --- /dev/null +++ b/src/programs/cisTEM_display/DisplayFrame.cpp @@ -0,0 +1,643 @@ +#include "../core/gui_core_headers.h" +#include "../programs/cisTEM_display/DisplayServer.h" // includes wxEVT_SERVER_OPEN_FILE + +DisplayFrame::DisplayFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) + : DisplayFrameParent(NULL, wxID_ANY, title, pos, size, style) { + + is_fullscreen = false; + remember_path = wxGetCwd( ); + + cisTEMDisplayPanel->EnableCanChangeFile( ); + cisTEMDisplayPanel->EnableCanCloseTabs( ); + cisTEMDisplayPanel->EnableCanMoveTabs( ); + cisTEMDisplayPanel->EnableCanFFT( ); + cisTEMDisplayPanel->Initialise( ); + + // Set this bool to true so that DisplayPanel knows that this frame's panel is from the cisTEM_display program + this->cisTEMDisplayPanel->is_from_display_program = true; + + int screen_x_size = wxSystemSettings::GetMetric(wxSYS_SCREEN_X); + int screen_y_size = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y); + int x_offset; + int y_offset; + + if ( screen_x_size > 1920 && screen_y_size > 1080 ) { + x_offset = (screen_x_size - 1920) / 2; + y_offset = (screen_y_size - 1080) / 2; + + if ( x_offset < 0 ) + x_offset = 0; + if ( y_offset < 0 ) + y_offset = 0; + + SetSize(x_offset, y_offset, 1920, 1080); + } + else { + Maximize(true); + } + + Bind(wxEVT_CHAR_HOOK, &DisplayFrame::OnCharHook, this); + Bind(EVT_SERVER_OPEN_FILE, &DisplayFrame::OnServerOpenFile, this); +} + +DisplayFrame::~DisplayFrame( ) { +} + +void DisplayFrame::OnCharHook(wxKeyEvent& event) { + if ( event.GetKeyCode( ) == WXK_F11 ) { + if ( is_fullscreen == true ) { + ShowFullScreen(false); + is_fullscreen = false; + } + else { + ShowFullScreen(true); + is_fullscreen = true; + } + } + event.Skip( ); +} + +void DisplayFrame::OnFileOpenClick(wxCommandEvent& event) { + cisTEMDisplayPanel->OnOpen(event); +} + +void DisplayFrame::OnServerOpenFile(wxCommandEvent& event) { + wxString filename = event.GetString( ); + if ( cisTEMDisplayPanel ) { + cisTEMDisplayPanel->OpenFile(filename, filename); + this->Raise( ); + this->SetFocus( ); + } +} + +void DisplayFrame::OnCloseTabClick(wxCommandEvent& event) { + if ( cisTEMDisplayPanel->ReturnCurrentPanel( ) != NULL ) { + cisTEMDisplayPanel->my_notebook->DeletePage(cisTEMDisplayPanel->my_notebook->GetSelection( )); + } + if ( cisTEMDisplayPanel->my_notebook->GetSelection( ) == wxNOT_FOUND ) { + DisableAllToolbarButtons( ); + } +} + +void DisplayFrame::OnExitClick(wxCommandEvent& event) { + this->Destroy( ); +} + +void DisplayFrame::OnLocationNumberClick(wxCommandEvent& event) { + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->show_label ) + cisTEMDisplayPanel->ReturnCurrentPanel( )->show_label = false; + else + cisTEMDisplayPanel->ReturnCurrentPanel( )->show_label = true; + + cisTEMDisplayPanel->ReturnCurrentPanel( )->ReDrawPanel( ); +} + +void DisplayFrame::OnImageSelectionModeClick(wxCommandEvent& event) { + // if we are already in selections mode, we don't want to do anything, so + // make a check. + if ( ! cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->number_of_coords > 0 ) { + wxMessageDialog question_dialog(this, "By switching the selection mode, you will lose your current coordinates selections if they are unsaved.\nDo you want to continue?", "Swtich Selection Modes?", wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION); + + if ( question_dialog.ShowModal( ) == wxID_YES ) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->Clear( ); + cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled = true; + SelectInvertSelection->Enable(true); + } + + // User does not want to switch; do nothing + else + return; + } + else + cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled = true; + + ClearTextFileFromPanel( ); + Refresh( ); + Update( ); + } +} + +void DisplayFrame::OnCoordsSelectionModeClick(wxCommandEvent& event) { + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->number_of_selections > 0 ) { + wxMessageDialog question_dialog(this, "By switching the selection mode, you will lose your current image selections.\nDo you want to continue?", "Switch Selection Modes?", wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION); + if ( question_dialog.ShowModal( ) == wxID_YES ) { + cisTEMDisplayPanel->ClearSelection(false); + cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled = false; + + SelectInvertSelection->Enable(false); + } + // User doesn't want to lose selections; do nothing + else + return; + } + + // No selections + else + cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled = false; + + ClearTextFileFromPanel( ); + Refresh( ); + Update( ); + } +} + +void DisplayFrame::OnOpenTxtClick(wxCommandEvent& event) { + bool valid_file = true; + wxString name_of_file; + wxString caption; + wxString wildcard; + wxString default_dir; + wxString default_filename; + wxString path; + + // We want to open image selections if we're in IMAGES_PICK mode + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->number_of_selections > 0 ) { + wxMessageDialog open_without_saving_selections_dialog(this, "To open image selections, all current selections must be cleared. Do you want to continue without saving?", "Proceed without Saving Current Selections?", wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION); + if ( open_without_saving_selections_dialog.ShowModal( ) == wxID_YES ) { + cisTEMDisplayPanel->ClearSelection(true); + ClearTextFileFromPanel( ); + } + // User does not want to switch; do nothing + else + return; + } + + caption = wxT("Open selections from text file"); + wildcard = wxT("TXT files (*.txt)|*.txt"); + default_dir = remember_path; + default_filename = wxEmptyString; + wxFileDialog* open_dialog = new wxFileDialog(this, caption, default_dir, default_filename, wildcard, wxFD_OPEN); + if ( open_dialog->ShowModal( ) == wxID_OK ) { + //Start with setting up the file info + path = open_dialog->GetPath( ); + remember_path = open_dialog->GetDirectory( ); + name_of_file = open_dialog->GetFilename( ); + wxTextFile* file_to_open = new wxTextFile(path); + + // Start reading from the file + file_to_open->Open( ); + wxString current_line; + + // Continue reading until through the file + size_t line_counter = 0; + while ( valid_file && line_counter < file_to_open->GetLineCount( ) ) { + current_line = file_to_open->GetLine(line_counter); + valid_file = LoadImageSelections(current_line); + line_counter++; + } + } + } + // Otherwise, we're in coords mode + else { + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->number_of_coords > 0 ) { + wxMessageDialog question_dialog(this, "Opening a text file with coordinates selected will clear any currently selected coordinates, so if they are needed, it is recommended to save them first. Do you want to continue without saving?", "Clear Coordinates?", wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION); + if ( question_dialog.ShowModal( ) == wxID_YES ) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->Clear( ); // Clear out any selections before adding new ones. + ClearTextFileFromPanel( ); + } + // User wants to save first, so do nothing + else + return; + } + + // Now we're definitely in coords mode with no coords selected; let user select file + caption = wxT("Open coordinates from text file"); + wildcard = wxT("TXT files (*.txt)|*.txt"); + default_dir = remember_path; + default_filename = wxEmptyString; + wxFileDialog* open_dialog = new wxFileDialog(this, caption, default_dir, default_filename, wildcard, wxFD_OPEN); + if ( open_dialog->ShowModal( ) == wxID_OK ) { + //Start with setting up the file info + path = open_dialog->GetPath( ); + remember_path = open_dialog->GetDirectory( ); + name_of_file = open_dialog->GetFilename( ); + wxTextFile* file_to_open = new wxTextFile(path); + + // Start reading from the file + file_to_open->Open( ); + wxString current_line; + long x, y, image_number; + + // Continue reading until through the file + size_t line_counter = 0; + while ( valid_file && line_counter < file_to_open->GetLineCount( ) ) { + current_line = file_to_open->GetLine(line_counter); + valid_file = LoadCoords(current_line, x, y, image_number); + line_counter++; + } + } + } + if ( valid_file ) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->short_txt_filename = name_of_file; + cisTEMDisplayPanel->ReturnCurrentPanel( )->current_file_path = path; + cisTEMDisplayPanel->ReturnCurrentPanel( )->have_txt_filename = true; + cisTEMDisplayPanel->SetTabNameSaved( ); + } + + Refresh( ); + Update( ); +} + +void DisplayFrame::OnSaveTxtClick(wxCommandEvent& event) { + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->have_txt_filename && cisTEMDisplayPanel->ReturnCurrentPanel( )->txt_is_saved ) { + cisTEMDisplayPanel->SetTabNameSaved( ); // Just make sure it's saved and tab name is up to date + return; + } + // Have unsaved file; update the file with current selections + else if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->have_txt_filename && ! cisTEMDisplayPanel->ReturnCurrentPanel( )->txt_is_saved ) { + wxTextFile file_to_update(cisTEMDisplayPanel->ReturnCurrentPanel( )->current_file_path); // Get a wxTextFile from extant file + if ( ! file_to_update.Exists( ) ) { + wxMessageDialog nonexistent_dialog(this, "The text file you're attempting to overwrite does not exist.", "Error: File to save does not exist.", wxOK | wxOK_DEFAULT | wxICON_EXCLAMATION); + return; + } + else { + // Just open, clear, and re-fill + file_to_update.Open( ); + file_to_update.Clear( ); + + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { + for ( long i = 0; i <= cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( ); i++ ) { + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_is_selected[i] ) + file_to_update.AddLine(wxString::Format("%li", i)); + } + } + + // coords mode + else { + for ( int i = 0; i < cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->number_of_coords; i++ ) { + file_to_update.AddLine(wxString::Format("%li %li %li", cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->coords[i].x_pos, cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->coords[i].y_pos, cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->coords[i].image_number)); + } + } + file_to_update.Write( ); + file_to_update.Close( ); + } + cisTEMDisplayPanel->SetTabNameSaved( ); + } +} + +void DisplayFrame::OnSaveTxtAsClick(wxCommandEvent& event) { + wxString caption; + wxString wildcard; + wxString default_dir; + wxString default_filename; + wxString path; + wxFileName mrc_name; + wxFileName temp_filename; + int temp_int; + + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { + caption = wxT("Save image selections as text file"); + wildcard = wxT("TXT files (*.txt)|*.txt"); + default_dir = remember_path; + mrc_name = cisTEMDisplayPanel->ReturnCurrentPanel( )->filename; + default_filename = "selections_" + mrc_name.GetName( ) + ".txt"; + temp_filename = default_filename; + temp_int = 1; + + // If the default filename already exists, apppend an integer to default name + if ( temp_filename.Exists( ) ) { + while ( temp_filename.Exists( ) ) { + temp_filename = default_filename; + temp_filename = wxString::Format("%i_" + default_filename, temp_int); + temp_int++; + } + } + default_filename = temp_filename.GetFullName( ); + + wxFileDialog* save_dialog = new wxFileDialog(this, caption, default_dir, default_filename, wildcard, wxFD_SAVE); + if ( save_dialog->ShowModal( ) == wxID_OK ) { + default_filename = save_dialog->GetFilename( ); + path = save_dialog->GetPath( ); + remember_path = save_dialog->GetDirectory( ); + wxTextFile* new_selections_file = new wxTextFile(path); + for ( long i = 0; i <= cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( ); i++ ) { + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_is_selected[i] ) + new_selections_file->AddLine(wxString::Format("%li", i)); + } + new_selections_file->Write( ); + new_selections_file->Close( ); + } + } + + // coords mode + else { + caption = wxT("Save coordinates as text file"); + wildcard = wxT("TXT files (*.txt)|*.txt"); + default_dir = remember_path; + mrc_name = cisTEMDisplayPanel->ReturnCurrentPanel( )->filename; + default_filename = "coords_" + mrc_name.GetName( ) + ".txt"; + temp_filename = default_filename; + int temp_int = 1; + + // If the filename already exists, apppend an integer to default name + if ( temp_filename.Exists( ) ) { + while ( temp_filename.Exists( ) ) { + temp_filename = default_filename; + temp_filename = wxString::Format("%i_" + default_filename, temp_int); + temp_int++; + } + } + default_filename = temp_filename.GetFullName( ); + + // Now set up the file with the new name and then open the dialog for saving + wxFileDialog* save_dialog = new wxFileDialog(NULL, caption, default_dir, default_filename, wildcard, wxFD_SAVE); + if ( save_dialog->ShowModal( ) == wxID_OK ) { + default_filename = save_dialog->GetFilename( ); + path = save_dialog->GetPath( ); + remember_path = save_dialog->GetDirectory( ); + wxTextFile* new_coords_file = new wxTextFile(path); + for ( int i = 0; i < cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->number_of_coords; i++ ) { + new_coords_file->AddLine(wxString::Format("%li %li %li", cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->coords[i].x_pos, cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->coords[i].y_pos, cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->coords[i].image_number)); + } + new_coords_file->Write( ); + new_coords_file->Close( ); + } + } + // Track the currently opened file for saving in case user makes further selections + cisTEMDisplayPanel->ReturnCurrentPanel( )->short_txt_filename = default_filename; + cisTEMDisplayPanel->ReturnCurrentPanel( )->current_file_path = path; + cisTEMDisplayPanel->ReturnCurrentPanel( )->have_txt_filename = true; + cisTEMDisplayPanel->SetTabNameSaved( ); +} + +void DisplayFrame::OnInvertSelectionClick(wxCommandEvent& event) { + for ( long image_counter = 1; image_counter <= cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( ); image_counter++ ) { + cisTEMDisplayPanel->ToggleImageSelected(image_counter, false); + } + cisTEMDisplayPanel->RefreshCurrentPanel( ); + cisTEMDisplayPanel->SetTabNameUnsaved( ); +} + +void DisplayFrame::OnClearSelectionClick(wxCommandEvent& event) { + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { + for ( int image_counter = 0; image_counter < cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( ); image_counter++ ) { + cisTEMDisplayPanel->ClearSelection(false); + } + } + else if ( ! cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->Clear( ); + } + ClearTextFileFromPanel( ); + cisTEMDisplayPanel->RefreshCurrentPanel( ); +} + +void DisplayFrame::OnSize3(wxCommandEvent& event) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size = 3; + Refresh( ); + Update( ); +} + +void DisplayFrame::OnSize5(wxCommandEvent& event) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size = 5; + Refresh( ); + Update( ); +} + +void DisplayFrame::OnSize7(wxCommandEvent& event) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size = 7; + Refresh( ); + Update( ); +} + +void DisplayFrame::OnSize10(wxCommandEvent& event) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size = 10; + Refresh( ); + Update( ); +} + +void DisplayFrame::OnSingleImageModeClick(wxCommandEvent& event) { + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image ) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image = false; + } + else { + cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image = true; + cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled = false; + } + + cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image_has_correct_greys = false; + cisTEMDisplayPanel->ReturnCurrentPanel( )->ReDrawPanel( ); + Refresh( ); + Update( ); +} + +void DisplayFrame::OnShowSelectionDistancesClick(wxCommandEvent& event) { + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->show_selection_distances ) + cisTEMDisplayPanel->ReturnCurrentPanel( )->show_selection_distances = false; + else + cisTEMDisplayPanel->ReturnCurrentPanel( )->show_selection_distances = true; + Refresh( ); + Update( ); +} + +void DisplayFrame::OnShowResolution(wxCommandEvent& event) { + double wanted_pixel_size; + + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->resolution_instead_of_radius ) + cisTEMDisplayPanel->ReturnCurrentPanel( )->resolution_instead_of_radius = false; + else { + wxTextEntryDialog text_dialog(this, wxT("Pixel Size (Angstroms)"), wxT("Select Pixel Size"), wxString::Format(wxT("%.2f"), cisTEMDisplayPanel->ReturnCurrentPanel( )->pixel_size), wxOK | wxCANCEL | wxCENTRE, wxDefaultPosition); + text_dialog.ShowModal( ); + + wxString current_value = text_dialog.GetValue( ); + text_dialog.Destroy( ); + if ( current_value.ToDouble(&wanted_pixel_size) == true ) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->pixel_size = wanted_pixel_size; + cisTEMDisplayPanel->ReturnCurrentPanel( )->resolution_instead_of_radius = true; + } + } +} + +void DisplayFrame::OnDocumentationClick(wxCommandEvent& event) { + wxLaunchDefaultBrowser("http://www.cistem.org/documentation"); +} + +// This prevents using buttons when an image or stack is not open to act on +void DisplayFrame::DisableAllToolbarButtons( ) { + + // Open menu only needs close tab disabled + DisplayCloseTab->Enable(false); + + // Label menu + LabelLocationNumber->Enable(false); + + // Select menu + SelectImageSelectionMode->Enable(false); + SelectCoordsSelectionMode->Enable(false); + SelectOpenTxt->Enable(false); + SelectSaveTxt->Enable(false); + SelectSaveTxtAs->Enable(false); + SelectInvertSelection->Enable(false); + SelectClearSelection->Enable(false); + + // Options menu + OptionsSingleImageMode->Enable(false); + OptionsShowSelectionDistances->Enable(false); + OptionsShowResolution->Enable(false); +} + +// Call when an image is opened to activate all toolbar buttons +void DisplayFrame::EnableAllToolbarButtons( ) { + // Open menu only needs close tab disabled + DisplayCloseTab->Enable( ); + + // Label menu + LabelLocationNumber->Enable( ); + + // Select menu + SelectImageSelectionMode->Enable(true); + SelectCoordsSelectionMode->Enable(true); + SelectOpenTxt->Enable(true); + SelectSaveTxt->Enable(true); + SelectSaveTxtAs->Enable(true); + SelectInvertSelection->Enable(true); + SelectClearSelection->Enable(true); + + // Options menu + OptionsSingleImageMode->Enable(true); + OptionsShowSelectionDistances->Enable(true); + OptionsShowResolution->Enable(true); +} + +void DisplayFrame::OnUpdateUI(wxUpdateUIEvent& event) { + // First, do we have an image open? + if ( cisTEMDisplayPanel->my_notebook->GetSelection( ) != wxNOT_FOUND ) { + EnableAllToolbarButtons( ); + + // Check that there are coords selected + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->number_of_coords > 0 || cisTEMDisplayPanel->ReturnCurrentPanel( )->number_of_selections > 0 ) { + SelectSaveTxtAs->Enable(true); + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->have_txt_filename ) + SelectSaveTxt->Enable(true); + else + SelectSaveTxt->Enable(false); + } + else { + SelectSaveTxtAs->Enable(false); + SelectSaveTxt->Enable(false); + } + + // Keep picking mode radio buttons visually current + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { + SelectImageSelectionMode->Check(true); + SelectInvertSelection->Enable(true); + } + else { + SelectCoordsSelectionMode->Check(true); + SelectInvertSelection->Enable(false); + } + + // Make sure correct radio is checked for point size selection submenu + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size == 3 ) + CoordSize3->Check(true); + else if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size == 5 ) + CoordSize5->Check(true); + else if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size == 7 ) + CoordSize7->Check(true); + else if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size == 10 ) + CoordSize10->Check(true); + + // Make sure single image mode is checked/unchecked based on current panel + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image ) { + if ( ! OptionsSingleImageMode->IsChecked( ) ) + OptionsSingleImageMode->Check(true); + SelectImageSelectionMode->Enable(false); + } + else if ( ! cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image ) { + if ( OptionsSingleImageMode->IsChecked( ) ) + OptionsSingleImageMode->Check(false); + SelectImageSelectionMode->Enable(true); + } + + // Repeat above for res instead of radius + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->resolution_instead_of_radius ) { + if ( ! OptionsShowResolution->IsChecked( ) ) { + OptionsShowResolution->Check(true); + } + } + else if ( ! cisTEMDisplayPanel->ReturnCurrentPanel( )->resolution_instead_of_radius ) { + if ( OptionsShowResolution->IsChecked( ) ) { + OptionsShowResolution->Check(false); + } + } + + // Repeat again for selection distance option + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->show_selection_distances ) { + if ( ! OptionsShowSelectionDistances->IsChecked( ) ) { + OptionsShowSelectionDistances->Check(true); + } + } + else if ( ! cisTEMDisplayPanel->ReturnCurrentPanel( )->show_selection_distances ) { + if ( OptionsShowSelectionDistances->IsChecked( ) ) { + OptionsShowSelectionDistances->Check(false); + } + } + } + // No image -- don't want buttons active + else + DisableAllToolbarButtons( ); +} + +bool DisplayFrame::LoadCoords(wxString current_line, long& x, long& y, long& image_number) { + // Parse the string for x, y, and the image number + int index_of_whitespace = current_line.find(' '); + int prev_whitespace_position = 0; + if ( index_of_whitespace == wxNOT_FOUND ) { + wxMessageDialog wrong_file_format(this, "Cannot open Image Selection text file in Coordinate Selection mode.", "Incorrect File Format", wxOK | wxOK_DEFAULT | wxICON_EXCLAMATION); + wrong_file_format.ShowModal( ); + return false; + } + current_line.SubString(prev_whitespace_position, index_of_whitespace - 1).ToLong(&x); + prev_whitespace_position = index_of_whitespace; + index_of_whitespace = current_line.find(' ', index_of_whitespace + 1); + current_line.SubString(prev_whitespace_position + 1, index_of_whitespace - 1).ToLong(&y); + prev_whitespace_position = index_of_whitespace; + index_of_whitespace = current_line.find('\n', index_of_whitespace + 1); + current_line.SubString(prev_whitespace_position + 1, index_of_whitespace - 1).ToLong(&image_number); + + // First, check that all coordinates and image numbers are valid for the open image + if ( x < cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnImageXSize( ) && y < cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnImageYSize( ) && image_number <= cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( ) ) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->ToggleCoord(image_number, x, y); + return true; + } + else { + wxMessageDialog invalid_file_dialog(this, wxString::Format("The selected coordinates exceed the dimensions of the currently opened *.mrc file. Cannot open selected coordinates.\nSelected x: %li, selected y: %li, image num: %li for image(s) with dimensions x: %i, y: %i, num images: %i).\nTry checking the selection mode and/or the text file contents.", x, y, image_number, cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnImageXSize( ), cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnImageYSize( ), cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( )), "Invalid Coordinates for Current Image(s)", wxOK | wxOK_DEFAULT | wxICON_EXCLAMATION); + if ( invalid_file_dialog.ShowModal( ) == wxID_OK ) + cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->Clear( ); + return false; + } +} + +bool DisplayFrame::LoadImageSelections(wxString current_line) { + // Quick check of file format + int index_of_whitespace = current_line.find(' '); + if ( index_of_whitespace != wxNOT_FOUND ) { + wxMessageDialog wrong_file_format(this, "Cannot open Coordinate Selection text file in Image Selection mode.", "Incorrect File Format", wxOK | wxOK_DEFAULT | wxICON_EXCLAMATION); + wrong_file_format.ShowModal( ); + return false; + } + + // Get the value that's selected + long image_number; + current_line.ToLong(&image_number); + + if ( image_number <= cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( ) ) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->SetImageSelected(image_number, false); + return true; + } + // If the value exceeds the possible dimensions don't try to access the index for setting selected + else { + wxMessageDialog invalid_file_dialog(this, wxString::Format("The file being opened contains selected images that exceed the number of images in the current file. Cannot open the selections.(Images in open file: %i. Image index sought: %li)", cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( ), image_number), "Invalid Selection(s) for Current Image(s)", wxOK | wxOK_DEFAULT | wxICON_EXCLAMATION); + cisTEMDisplayPanel->ClearSelection(false); + return false; + } +} + +void DisplayFrame::ClearTextFileFromPanel( ) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->have_txt_filename = false; + cisTEMDisplayPanel->ReturnCurrentPanel( )->short_txt_filename = wxEmptyString; + cisTEMDisplayPanel->ReturnCurrentPanel( )->current_file_path = wxEmptyString; + cisTEMDisplayPanel->SetTabNameSaved( ); +} \ No newline at end of file diff --git a/src/programs/cisTEM_display/DisplayServer.cpp b/src/programs/cisTEM_display/DisplayServer.cpp new file mode 100644 index 000000000..1d1a62f34 --- /dev/null +++ b/src/programs/cisTEM_display/DisplayServer.cpp @@ -0,0 +1,88 @@ +#include "DisplayServer.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include "DisplayConfig.h" + +wxDEFINE_EVENT(EVT_SERVER_OPEN_FILE, wxCommandEvent); + +DisplayServer& DisplayServer::GetInstance( ) { + static DisplayServer instance; + return instance; +} + +bool DisplayServer::Start( ) { + unlink(SOCKET_PATH.c_str( )); + socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if ( socket_fd < 0 ) + return false; + + sockaddr_un addr{ }; + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, SOCKET_PATH.c_str( ), sizeof(addr.sun_path) - 1); + unlink(SOCKET_PATH.c_str( )); + + if ( bind(socket_fd, (sockaddr*)&addr, sizeof(addr)) < 0 ) { + perror("bind"); + return false; + } + + if ( listen(socket_fd, 5) < 0 ) { + perror("listen"); + return false; + } + std::thread([this]( ) { ServerLoop( ); }).detach( ); + return true; +} + +void DisplayServer::ServerLoop( ) { + while ( true ) { + int client_fd = accept(socket_fd, nullptr, nullptr); + if ( client_fd < 0 ) { + perror("accept"); + continue; + } + + std::string buffer; + char tmp[512]; + ssize_t len; + while ( (len = read(client_fd, tmp, sizeof(tmp))) > 0 ) { + buffer.append(tmp, len); + } + close(client_fd); + size_t start = 0; + while ( true ) { + size_t pos = buffer.find('\n', start); + if ( pos == std::string::npos ) + break; + + std::string filename = buffer.substr(start, pos - start); + start = pos + 1; + + + if ( ! filename.empty( ) ) { + wxString message = wxString::FromUTF8(filename.c_str( )).Trim( ); + wxCommandEvent evt(EVT_SERVER_OPEN_FILE, 1000); + evt.SetString(message); + wxQueueEvent(wxTheApp->GetTopWindow( )->GetEventHandler( ), new wxCommandEvent(evt)); + } + } + close(client_fd); + } +} + +void DisplayServer::Stop( ) { + if ( socket_fd != -1 ) { + close(socket_fd); + unlink(SOCKET_PATH.c_str( )); + } +} diff --git a/src/programs/cisTEM_display/DisplayServer.h b/src/programs/cisTEM_display/DisplayServer.h new file mode 100644 index 000000000..0865b8f70 --- /dev/null +++ b/src/programs/cisTEM_display/DisplayServer.h @@ -0,0 +1,57 @@ +#ifndef _src_programs_cisTEM_display_IpcServer_h_ +#define _src_programs_cisTEM_display_IpcServer_h_ + +#pragma once +#include +#include +#include +#include +#include +#include +#include + +wxDECLARE_EVENT(EVT_SERVER_OPEN_FILE, wxCommandEvent); + +class DisplayServer { + public: + static DisplayServer& GetInstance( ); + + bool Start( ); + void Stop( ); + + private: + int socket_fd = -1; + void ServerLoop( ); +}; + +// These two functions will ensure that no matter how the display program +// is closed, the existing socket in /tmp will be deleted + +inline const std::string GetUserSocketPath( ) { + const char* username = getenv("USER"); + if ( ! username ) { + struct passwd* pw = getpwuid(getuid( )); + if ( pw ) + username = pw->pw_name; + else + username = "unknown"; + } + return username; +}; + +inline std::string SOCKET_PATH = ("/tmp/cisTEM_display_ipc_socket_" + GetUserSocketPath( )).c_str( ); + +inline void CleanupSocketFile(int sig_num) { + unlink(SOCKET_PATH.c_str( )); + signal(sig_num, SIG_DFL); + raise(sig_num); +}; + +inline void SetupSignalHandlers( ) { + signal(SIGINT, CleanupSocketFile); + signal(SIGTERM, CleanupSocketFile); + signal(SIGQUIT, CleanupSocketFile); + signal(SIGTSTP, CleanupSocketFile); +}; + +#endif \ No newline at end of file diff --git a/src/programs/cisTEM_display/cisTEM_display.cpp b/src/programs/cisTEM_display/cisTEM_display.cpp index de1bc3c5f..d58739d90 100644 --- a/src/programs/cisTEM_display/cisTEM_display.cpp +++ b/src/programs/cisTEM_display/cisTEM_display.cpp @@ -1,4 +1,14 @@ #include "../../core/gui_core_headers.h" +#include "DisplayServer.h" +#include +#include +#include +#include + +// #define IPC_PORT 3456 +// #define IPC_SERVICE_NAME "CistemDisplayService" + +class MyServer; class DisplayApp : public wxApp { public: @@ -6,13 +16,55 @@ class DisplayApp : public wxApp { virtual int OnExit( ); virtual void OnInitCmdLine(wxCmdLineParser& parser); virtual bool OnCmdLineParsed(wxCmdLineParser& parser); + ~DisplayApp( ); + + private: + wxSingleInstanceChecker* m_checker; }; IMPLEMENT_APP(DisplayApp) DisplayFrame* display_frame; +DisplayApp::~DisplayApp( ) { + DisplayServer::GetInstance( ).Stop( ); +} + bool DisplayApp::OnInit( ) { + + const wxString name = wxString::Format("cisTEM_Display-%s", wxGetUserId( )); + m_checker = new wxSingleInstanceChecker(name); + if ( m_checker->IsAnotherRunning( ) ) { + if ( argc > 1 ) { + int sock = socket(AF_UNIX, SOCK_STREAM, 0); + if ( sock != -1 ) { + struct sockaddr_un addr; + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, SOCKET_PATH.c_str( )); + if ( connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0 ) { + for ( int i = 1; i < argc; i++ ) { + wxFileName filename(argv[i]); + filename.Normalize(wxPATH_NORM_LONG | wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_ABSOLUTE); + wxString cmd_full_filename = filename.GetFullPath( ); + wxScopedCharBuffer buffer = cmd_full_filename.ToUTF8( ); + write(sock, buffer.data( ), buffer.length( )); + write(sock, "\n", 1); + } + } + else { + perror("client connect failed\n"); + } + close(sock); + } + return false; + } + } + else { + SetupSignalHandlers( ); + DisplayServer::GetInstance( ).Start( ); + } + wxInitAllImageHandlers( ); display_frame = new DisplayFrame(NULL, wxID_ANY, "cisTEM Display", wxPoint(-1, -1), wxSize(-1, -1), wxDEFAULT_FRAME_STYLE); @@ -44,5 +96,6 @@ bool DisplayApp::OnCmdLineParsed(wxCmdLineParser& parser) { } int DisplayApp::OnExit( ) { + DisplayServer::GetInstance( ).Stop( ); return 0; } From b690667e93e2836b59637c1119df3412636483da Mon Sep 17 00:00:00 2001 From: twagner9 Date: Tue, 12 Aug 2025 15:11:57 -0400 Subject: [PATCH 02/12] Allow saving binned angular distribution map It can sometimes be useful for creating figures to used the binned form of the angular distribution plot. This adds a button to give that option. --- src/gui/MyRefinementResultsPanel.cpp | 24 ++++++- src/gui/MyRefinementResultsPanel.h | 1 + src/gui/ProjectX_gui_refine3d.cpp | 9 ++- src/gui/ProjectX_gui_refine3d.h | 2 + src/gui/wxformbuilder/ProjectX_refine3d.fbp | 80 ++++++++++++++++++++- 5 files changed, 110 insertions(+), 6 deletions(-) diff --git a/src/gui/MyRefinementResultsPanel.cpp b/src/gui/MyRefinementResultsPanel.cpp index c42b07dac..a4372e492 100644 --- a/src/gui/MyRefinementResultsPanel.cpp +++ b/src/gui/MyRefinementResultsPanel.cpp @@ -25,11 +25,15 @@ MyRefinementResultsPanel::MyRefinementResultsPanel(wxWindow* parent) #include "icons/show_angles.cpp" #include "icons/show_text.cpp" +#include "icons/small_save_icon.cpp" - wxBitmap angles_popup_bmp = wxBITMAP_PNG_FROM_DATA(show_angles); - wxBitmap parameters_popup_bmp = wxBITMAP_PNG_FROM_DATA(show_text); + wxBitmap angles_popup_bmp = wxBITMAP_PNG_FROM_DATA(show_angles); + wxBitmap parameters_popup_bmp = wxBITMAP_PNG_FROM_DATA(show_text); + wxBitmap binned_angles_save_bmp = wxBITMAP_PNG_FROM_DATA(small_save_icon); AngularPlotDetailsButton->SetBitmap(angles_popup_bmp); ParametersDetailButton->SetBitmap(parameters_popup_bmp); + SaveBinnedAngularPlotButton->SetBitmap(binned_angles_save_bmp); + Layout( ); // FSCPlotPanel->ClassComboBox->Connect( wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler( MyRefinementResultsPanel::OnClassComboBoxChange ), NULL, this ); } @@ -329,6 +333,22 @@ void MyRefinementResultsPanel::AngularPlotPopupClick(wxCommandEvent& event) { } } +void MyRefinementResultsPanel::SaveBinnedPlotClick(wxCommandEvent& event) { + ProperOverwriteCheckSaveDialog* saveFileDialog; + saveFileDialog = new ProperOverwriteCheckSaveDialog(this, _("Save png image"), "PNG files (*.png)|*.png", ".png"); + if ( saveFileDialog->ShowModal( ) == wxID_CANCEL ) { + saveFileDialog->Destroy( ); + return; + } + + // save the file then.. + + // TODO: this would likely be the only difference; change the source of data + // for the saving of the file + AngularPlotPanel->buffer_bitmap.SaveFile(saveFileDialog->ReturnProperPath( ), wxBITMAP_TYPE_PNG); + saveFileDialog->Destroy( ); +} + void MyRefinementResultsPanel::PopupParametersClick(wxCommandEvent& event) { if ( RefinementPackageComboBox->GetSelection( ) >= 0 && OrthPanel->my_notebook->GetPageCount( ) > 0 ) { UpdateBufferedFullRefinement( ); diff --git a/src/gui/MyRefinementResultsPanel.h b/src/gui/MyRefinementResultsPanel.h index eee092119..c24b59afe 100644 --- a/src/gui/MyRefinementResultsPanel.h +++ b/src/gui/MyRefinementResultsPanel.h @@ -26,6 +26,7 @@ class MyRefinementResultsPanel : public RefinementResultsPanel { void OnClassComboBoxChange(wxCommandEvent& event); void AngularPlotPopupClick(wxCommandEvent& event); void PopupParametersClick(wxCommandEvent& event); + void SaveBinnedPlotClick(wxCommandEvent& event); void UpdateCachedRefinement( ); void UpdateBufferedFullRefinement( ); diff --git a/src/gui/ProjectX_gui_refine3d.cpp b/src/gui/ProjectX_gui_refine3d.cpp index a69b1fffa..41e395628 100644 --- a/src/gui/ProjectX_gui_refine3d.cpp +++ b/src/gui/ProjectX_gui_refine3d.cpp @@ -102,12 +102,15 @@ RefinementResultsPanel::RefinementResultsPanel( wxWindow* parent, wxWindowID id, ParametersDetailButton = new NoFocusBitmapButton( m_panel125, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); ParametersDetailButton->SetDefault(); - bSizer497->Add( ParametersDetailButton, 0, wxLEFT|wxTOP, 5 ); + bSizer497->Add( ParametersDetailButton, 0, wxEXPAND|wxTOP, 5 ); AngularPlotDetailsButton = new NoFocusBitmapButton( m_panel125, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); AngularPlotDetailsButton->SetDefault(); - bSizer497->Add( AngularPlotDetailsButton, 0, wxRIGHT|wxTOP, 5 ); + bSizer497->Add( AngularPlotDetailsButton, 0, wxEXPAND|wxTOP, 5 ); + + SaveBinnedAngularPlotButton = new NoFocusBitmapButton( m_panel125, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); + bSizer497->Add( SaveBinnedAngularPlotButton, 0, wxEXPAND|wxTOP, 5 ); bSizer495->Add( bSizer497, 0, wxEXPAND, 5 ); @@ -614,6 +617,7 @@ RefinementResultsPanel::RefinementResultsPanel( wxWindow* parent, wxWindowID id, this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( RefinementResultsPanel::OnUpdateUI ) ); ParametersDetailButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( RefinementResultsPanel::PopupParametersClick ), NULL, this ); AngularPlotDetailsButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( RefinementResultsPanel::AngularPlotPopupClick ), NULL, this ); + SaveBinnedAngularPlotButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( RefinementResultsPanel::SaveBinnedPlotClick ), NULL, this ); JobDetailsToggleButton->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( RefinementResultsPanel::OnJobDetailsToggle ), NULL, this ); } @@ -623,6 +627,7 @@ RefinementResultsPanel::~RefinementResultsPanel() this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( RefinementResultsPanel::OnUpdateUI ) ); ParametersDetailButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( RefinementResultsPanel::PopupParametersClick ), NULL, this ); AngularPlotDetailsButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( RefinementResultsPanel::AngularPlotPopupClick ), NULL, this ); + SaveBinnedAngularPlotButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( RefinementResultsPanel::SaveBinnedPlotClick ), NULL, this ); JobDetailsToggleButton->Disconnect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( RefinementResultsPanel::OnJobDetailsToggle ), NULL, this ); } diff --git a/src/gui/ProjectX_gui_refine3d.h b/src/gui/ProjectX_gui_refine3d.h index 7e42a48a3..cf3cd19cf 100644 --- a/src/gui/ProjectX_gui_refine3d.h +++ b/src/gui/ProjectX_gui_refine3d.h @@ -169,6 +169,7 @@ class RefinementResultsPanel : public wxPanel virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); } virtual void PopupParametersClick( wxCommandEvent& event ) { event.Skip(); } virtual void AngularPlotPopupClick( wxCommandEvent& event ) { event.Skip(); } + virtual void SaveBinnedPlotClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnJobDetailsToggle( wxCommandEvent& event ) { event.Skip(); } @@ -177,6 +178,7 @@ class RefinementResultsPanel : public wxPanel RefinementPickerComboPanel* InputParametersComboBox; NoFocusBitmapButton* ParametersDetailButton; NoFocusBitmapButton* AngularPlotDetailsButton; + NoFocusBitmapButton* SaveBinnedAngularPlotButton; RefinementResultsPanel( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 1007,587 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString ); diff --git a/src/gui/wxformbuilder/ProjectX_refine3d.fbp b/src/gui/wxformbuilder/ProjectX_refine3d.fbp index 1f78f29cc..bb2dc7fe3 100644 --- a/src/gui/wxformbuilder/ProjectX_refine3d.fbp +++ b/src/gui/wxformbuilder/ProjectX_refine3d.fbp @@ -814,7 +814,7 @@ 5 - wxLEFT|wxTOP + wxEXPAND|wxTOP 0 1 @@ -888,7 +888,7 @@ 5 - wxRIGHT|wxTOP + wxEXPAND|wxTOP 0 1 @@ -960,6 +960,80 @@ AngularPlotPopupClick + + 5 + wxEXPAND|wxTOP + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + MyButton + + 0 + + 0 + + + 0 + + 1 + SaveBinnedAngularPlotButton + 1 + + + public + 1 + + + + Resizable + 1 + + + NoFocusBitmapButton; my_controls.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + SaveBinnedPlotClick + + @@ -6642,6 +6716,7 @@ 952,539 + 0 wxTAB_TRAVERSAL @@ -7514,6 +7589,7 @@ 500,300 + 0 wxTAB_TRAVERSAL From 8481bd84ee58c9c2da8d4b8a56cf7332ba38ba46 Mon Sep 17 00:00:00 2001 From: twagner9 Date: Wed, 13 Aug 2025 11:14:02 -0400 Subject: [PATCH 03/12] Add ability to save MRCs opened in display as PNG -Only works for the currently displayed images that are rendered in the bitmap; slices or images that are further in the stack will not be saved, and images that are zoomed in single image mode will not be displayed either. -Image selection circles and coordinate selection circles will not be present as these are not actually rendered directly onto the bitmap. It may be useful to change this in the future, so users can save selection distances and image selections as a way to point more specifically to certain images. --- src/gui/DisplayFrame.cpp | 26 + src/gui/DisplayFrame.h | 1 + src/gui/wxformbuilder/cisTEM_display.fbp | 22 +- src/programs/cisTEM_display/DisplayFrame.cpp | 643 ------------------- src/programs/cisTEM_display/display_gui.cpp | 7 + src/programs/cisTEM_display/display_gui.h | 2 + 6 files changed, 56 insertions(+), 645 deletions(-) delete mode 100644 src/programs/cisTEM_display/DisplayFrame.cpp diff --git a/src/gui/DisplayFrame.cpp b/src/gui/DisplayFrame.cpp index 93f91f70d..832949b16 100644 --- a/src/gui/DisplayFrame.cpp +++ b/src/gui/DisplayFrame.cpp @@ -61,6 +61,30 @@ void DisplayFrame::OnFileOpenClick(wxCommandEvent& event) { cisTEMDisplayPanel->OnOpen(event); } +void DisplayFrame::OnSaveDisplayedImagesClick(wxCommandEvent& event) { + // Mimics the logic ProperOverwriteCheckSaveDialog + wxFileDialog save_file_dialog(this, _("Save png image"), wxEmptyString, wxEmptyString, "PNG files (*.png)|*.png", wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition, wxDefaultSize, wxFileDialogNameStr); + + wxString wanted_extension = ".png"; + wxString default_dir = cisTEMDisplayPanel->ReturnCurrentPanel( )->filename; + wxPrintf("default_dir: %s\n", default_dir); + + // Strip away the filename to get the directory + default_dir = default_dir.BeforeLast('/'); + + save_file_dialog.SetDirectory(default_dir); + wxString extension_lowercase = wanted_extension.Lower( ); + wxString extension_uppercase = wanted_extension.Upper( ); + + wxPrintf("default_dir: %s\n", default_dir); + if ( save_file_dialog.ShowModal( ) == wxID_CANCEL ) { + save_file_dialog.Destroy( ); + return; + } + + cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_bitmap.SaveFile(save_file_dialog.GetPath( ), wxBITMAP_TYPE_PNG); +} + void DisplayFrame::OnServerOpenFile(wxCommandEvent& event) { wxString filename = event.GetString( ); if ( cisTEMDisplayPanel ) { @@ -459,6 +483,7 @@ void DisplayFrame::DisableAllToolbarButtons( ) { // Open menu only needs close tab disabled DisplayCloseTab->Enable(false); + SaveDisplayedImages->Enable(false); // Label menu LabelLocationNumber->Enable(false); @@ -482,6 +507,7 @@ void DisplayFrame::DisableAllToolbarButtons( ) { void DisplayFrame::EnableAllToolbarButtons( ) { // Open menu only needs close tab disabled DisplayCloseTab->Enable( ); + SaveDisplayedImages->Enable( ); // Label menu LabelLocationNumber->Enable( ); diff --git a/src/gui/DisplayFrame.h b/src/gui/DisplayFrame.h index 5c8cf1423..7b21804ca 100644 --- a/src/gui/DisplayFrame.h +++ b/src/gui/DisplayFrame.h @@ -21,6 +21,7 @@ class DisplayFrame : public DisplayFrameParent { // File menu void OnFileOpenClick(wxCommandEvent& event); + void OnSaveDisplayedImagesClick(wxCommandEvent& event); void OnCloseTabClick(wxCommandEvent& event); void OnExitClick(wxCommandEvent& event); diff --git a/src/gui/wxformbuilder/cisTEM_display.fbp b/src/gui/wxformbuilder/cisTEM_display.fbp index e70d170f0..83a0e3db3 100644 --- a/src/gui/wxformbuilder/cisTEM_display.fbp +++ b/src/gui/wxformbuilder/cisTEM_display.fbp @@ -151,7 +151,7 @@ wxTAB_TRAVERSAL 1 OnUpdateUI - + 1 @@ -172,7 +172,7 @@ - + File DisplayFileMenu protected @@ -208,6 +208,24 @@ m_separator7 none + + + 0 + 0 + + wxID_ANY + wxITEM_NORMAL + Save Displayed Image(s) As PNG + SaveDisplayedImages + protected + + + OnSaveDisplayedImagesClick + + + m_separator71 + none + 0 diff --git a/src/programs/cisTEM_display/DisplayFrame.cpp b/src/programs/cisTEM_display/DisplayFrame.cpp deleted file mode 100644 index 93f91f70d..000000000 --- a/src/programs/cisTEM_display/DisplayFrame.cpp +++ /dev/null @@ -1,643 +0,0 @@ -#include "../core/gui_core_headers.h" -#include "../programs/cisTEM_display/DisplayServer.h" // includes wxEVT_SERVER_OPEN_FILE - -DisplayFrame::DisplayFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) - : DisplayFrameParent(NULL, wxID_ANY, title, pos, size, style) { - - is_fullscreen = false; - remember_path = wxGetCwd( ); - - cisTEMDisplayPanel->EnableCanChangeFile( ); - cisTEMDisplayPanel->EnableCanCloseTabs( ); - cisTEMDisplayPanel->EnableCanMoveTabs( ); - cisTEMDisplayPanel->EnableCanFFT( ); - cisTEMDisplayPanel->Initialise( ); - - // Set this bool to true so that DisplayPanel knows that this frame's panel is from the cisTEM_display program - this->cisTEMDisplayPanel->is_from_display_program = true; - - int screen_x_size = wxSystemSettings::GetMetric(wxSYS_SCREEN_X); - int screen_y_size = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y); - int x_offset; - int y_offset; - - if ( screen_x_size > 1920 && screen_y_size > 1080 ) { - x_offset = (screen_x_size - 1920) / 2; - y_offset = (screen_y_size - 1080) / 2; - - if ( x_offset < 0 ) - x_offset = 0; - if ( y_offset < 0 ) - y_offset = 0; - - SetSize(x_offset, y_offset, 1920, 1080); - } - else { - Maximize(true); - } - - Bind(wxEVT_CHAR_HOOK, &DisplayFrame::OnCharHook, this); - Bind(EVT_SERVER_OPEN_FILE, &DisplayFrame::OnServerOpenFile, this); -} - -DisplayFrame::~DisplayFrame( ) { -} - -void DisplayFrame::OnCharHook(wxKeyEvent& event) { - if ( event.GetKeyCode( ) == WXK_F11 ) { - if ( is_fullscreen == true ) { - ShowFullScreen(false); - is_fullscreen = false; - } - else { - ShowFullScreen(true); - is_fullscreen = true; - } - } - event.Skip( ); -} - -void DisplayFrame::OnFileOpenClick(wxCommandEvent& event) { - cisTEMDisplayPanel->OnOpen(event); -} - -void DisplayFrame::OnServerOpenFile(wxCommandEvent& event) { - wxString filename = event.GetString( ); - if ( cisTEMDisplayPanel ) { - cisTEMDisplayPanel->OpenFile(filename, filename); - this->Raise( ); - this->SetFocus( ); - } -} - -void DisplayFrame::OnCloseTabClick(wxCommandEvent& event) { - if ( cisTEMDisplayPanel->ReturnCurrentPanel( ) != NULL ) { - cisTEMDisplayPanel->my_notebook->DeletePage(cisTEMDisplayPanel->my_notebook->GetSelection( )); - } - if ( cisTEMDisplayPanel->my_notebook->GetSelection( ) == wxNOT_FOUND ) { - DisableAllToolbarButtons( ); - } -} - -void DisplayFrame::OnExitClick(wxCommandEvent& event) { - this->Destroy( ); -} - -void DisplayFrame::OnLocationNumberClick(wxCommandEvent& event) { - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->show_label ) - cisTEMDisplayPanel->ReturnCurrentPanel( )->show_label = false; - else - cisTEMDisplayPanel->ReturnCurrentPanel( )->show_label = true; - - cisTEMDisplayPanel->ReturnCurrentPanel( )->ReDrawPanel( ); -} - -void DisplayFrame::OnImageSelectionModeClick(wxCommandEvent& event) { - // if we are already in selections mode, we don't want to do anything, so - // make a check. - if ( ! cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->number_of_coords > 0 ) { - wxMessageDialog question_dialog(this, "By switching the selection mode, you will lose your current coordinates selections if they are unsaved.\nDo you want to continue?", "Swtich Selection Modes?", wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION); - - if ( question_dialog.ShowModal( ) == wxID_YES ) { - cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->Clear( ); - cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled = true; - SelectInvertSelection->Enable(true); - } - - // User does not want to switch; do nothing - else - return; - } - else - cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled = true; - - ClearTextFileFromPanel( ); - Refresh( ); - Update( ); - } -} - -void DisplayFrame::OnCoordsSelectionModeClick(wxCommandEvent& event) { - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->number_of_selections > 0 ) { - wxMessageDialog question_dialog(this, "By switching the selection mode, you will lose your current image selections.\nDo you want to continue?", "Switch Selection Modes?", wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION); - if ( question_dialog.ShowModal( ) == wxID_YES ) { - cisTEMDisplayPanel->ClearSelection(false); - cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled = false; - - SelectInvertSelection->Enable(false); - } - // User doesn't want to lose selections; do nothing - else - return; - } - - // No selections - else - cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled = false; - - ClearTextFileFromPanel( ); - Refresh( ); - Update( ); - } -} - -void DisplayFrame::OnOpenTxtClick(wxCommandEvent& event) { - bool valid_file = true; - wxString name_of_file; - wxString caption; - wxString wildcard; - wxString default_dir; - wxString default_filename; - wxString path; - - // We want to open image selections if we're in IMAGES_PICK mode - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->number_of_selections > 0 ) { - wxMessageDialog open_without_saving_selections_dialog(this, "To open image selections, all current selections must be cleared. Do you want to continue without saving?", "Proceed without Saving Current Selections?", wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION); - if ( open_without_saving_selections_dialog.ShowModal( ) == wxID_YES ) { - cisTEMDisplayPanel->ClearSelection(true); - ClearTextFileFromPanel( ); - } - // User does not want to switch; do nothing - else - return; - } - - caption = wxT("Open selections from text file"); - wildcard = wxT("TXT files (*.txt)|*.txt"); - default_dir = remember_path; - default_filename = wxEmptyString; - wxFileDialog* open_dialog = new wxFileDialog(this, caption, default_dir, default_filename, wildcard, wxFD_OPEN); - if ( open_dialog->ShowModal( ) == wxID_OK ) { - //Start with setting up the file info - path = open_dialog->GetPath( ); - remember_path = open_dialog->GetDirectory( ); - name_of_file = open_dialog->GetFilename( ); - wxTextFile* file_to_open = new wxTextFile(path); - - // Start reading from the file - file_to_open->Open( ); - wxString current_line; - - // Continue reading until through the file - size_t line_counter = 0; - while ( valid_file && line_counter < file_to_open->GetLineCount( ) ) { - current_line = file_to_open->GetLine(line_counter); - valid_file = LoadImageSelections(current_line); - line_counter++; - } - } - } - // Otherwise, we're in coords mode - else { - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->number_of_coords > 0 ) { - wxMessageDialog question_dialog(this, "Opening a text file with coordinates selected will clear any currently selected coordinates, so if they are needed, it is recommended to save them first. Do you want to continue without saving?", "Clear Coordinates?", wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION); - if ( question_dialog.ShowModal( ) == wxID_YES ) { - cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->Clear( ); // Clear out any selections before adding new ones. - ClearTextFileFromPanel( ); - } - // User wants to save first, so do nothing - else - return; - } - - // Now we're definitely in coords mode with no coords selected; let user select file - caption = wxT("Open coordinates from text file"); - wildcard = wxT("TXT files (*.txt)|*.txt"); - default_dir = remember_path; - default_filename = wxEmptyString; - wxFileDialog* open_dialog = new wxFileDialog(this, caption, default_dir, default_filename, wildcard, wxFD_OPEN); - if ( open_dialog->ShowModal( ) == wxID_OK ) { - //Start with setting up the file info - path = open_dialog->GetPath( ); - remember_path = open_dialog->GetDirectory( ); - name_of_file = open_dialog->GetFilename( ); - wxTextFile* file_to_open = new wxTextFile(path); - - // Start reading from the file - file_to_open->Open( ); - wxString current_line; - long x, y, image_number; - - // Continue reading until through the file - size_t line_counter = 0; - while ( valid_file && line_counter < file_to_open->GetLineCount( ) ) { - current_line = file_to_open->GetLine(line_counter); - valid_file = LoadCoords(current_line, x, y, image_number); - line_counter++; - } - } - } - if ( valid_file ) { - cisTEMDisplayPanel->ReturnCurrentPanel( )->short_txt_filename = name_of_file; - cisTEMDisplayPanel->ReturnCurrentPanel( )->current_file_path = path; - cisTEMDisplayPanel->ReturnCurrentPanel( )->have_txt_filename = true; - cisTEMDisplayPanel->SetTabNameSaved( ); - } - - Refresh( ); - Update( ); -} - -void DisplayFrame::OnSaveTxtClick(wxCommandEvent& event) { - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->have_txt_filename && cisTEMDisplayPanel->ReturnCurrentPanel( )->txt_is_saved ) { - cisTEMDisplayPanel->SetTabNameSaved( ); // Just make sure it's saved and tab name is up to date - return; - } - // Have unsaved file; update the file with current selections - else if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->have_txt_filename && ! cisTEMDisplayPanel->ReturnCurrentPanel( )->txt_is_saved ) { - wxTextFile file_to_update(cisTEMDisplayPanel->ReturnCurrentPanel( )->current_file_path); // Get a wxTextFile from extant file - if ( ! file_to_update.Exists( ) ) { - wxMessageDialog nonexistent_dialog(this, "The text file you're attempting to overwrite does not exist.", "Error: File to save does not exist.", wxOK | wxOK_DEFAULT | wxICON_EXCLAMATION); - return; - } - else { - // Just open, clear, and re-fill - file_to_update.Open( ); - file_to_update.Clear( ); - - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { - for ( long i = 0; i <= cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( ); i++ ) { - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_is_selected[i] ) - file_to_update.AddLine(wxString::Format("%li", i)); - } - } - - // coords mode - else { - for ( int i = 0; i < cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->number_of_coords; i++ ) { - file_to_update.AddLine(wxString::Format("%li %li %li", cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->coords[i].x_pos, cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->coords[i].y_pos, cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->coords[i].image_number)); - } - } - file_to_update.Write( ); - file_to_update.Close( ); - } - cisTEMDisplayPanel->SetTabNameSaved( ); - } -} - -void DisplayFrame::OnSaveTxtAsClick(wxCommandEvent& event) { - wxString caption; - wxString wildcard; - wxString default_dir; - wxString default_filename; - wxString path; - wxFileName mrc_name; - wxFileName temp_filename; - int temp_int; - - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { - caption = wxT("Save image selections as text file"); - wildcard = wxT("TXT files (*.txt)|*.txt"); - default_dir = remember_path; - mrc_name = cisTEMDisplayPanel->ReturnCurrentPanel( )->filename; - default_filename = "selections_" + mrc_name.GetName( ) + ".txt"; - temp_filename = default_filename; - temp_int = 1; - - // If the default filename already exists, apppend an integer to default name - if ( temp_filename.Exists( ) ) { - while ( temp_filename.Exists( ) ) { - temp_filename = default_filename; - temp_filename = wxString::Format("%i_" + default_filename, temp_int); - temp_int++; - } - } - default_filename = temp_filename.GetFullName( ); - - wxFileDialog* save_dialog = new wxFileDialog(this, caption, default_dir, default_filename, wildcard, wxFD_SAVE); - if ( save_dialog->ShowModal( ) == wxID_OK ) { - default_filename = save_dialog->GetFilename( ); - path = save_dialog->GetPath( ); - remember_path = save_dialog->GetDirectory( ); - wxTextFile* new_selections_file = new wxTextFile(path); - for ( long i = 0; i <= cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( ); i++ ) { - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_is_selected[i] ) - new_selections_file->AddLine(wxString::Format("%li", i)); - } - new_selections_file->Write( ); - new_selections_file->Close( ); - } - } - - // coords mode - else { - caption = wxT("Save coordinates as text file"); - wildcard = wxT("TXT files (*.txt)|*.txt"); - default_dir = remember_path; - mrc_name = cisTEMDisplayPanel->ReturnCurrentPanel( )->filename; - default_filename = "coords_" + mrc_name.GetName( ) + ".txt"; - temp_filename = default_filename; - int temp_int = 1; - - // If the filename already exists, apppend an integer to default name - if ( temp_filename.Exists( ) ) { - while ( temp_filename.Exists( ) ) { - temp_filename = default_filename; - temp_filename = wxString::Format("%i_" + default_filename, temp_int); - temp_int++; - } - } - default_filename = temp_filename.GetFullName( ); - - // Now set up the file with the new name and then open the dialog for saving - wxFileDialog* save_dialog = new wxFileDialog(NULL, caption, default_dir, default_filename, wildcard, wxFD_SAVE); - if ( save_dialog->ShowModal( ) == wxID_OK ) { - default_filename = save_dialog->GetFilename( ); - path = save_dialog->GetPath( ); - remember_path = save_dialog->GetDirectory( ); - wxTextFile* new_coords_file = new wxTextFile(path); - for ( int i = 0; i < cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->number_of_coords; i++ ) { - new_coords_file->AddLine(wxString::Format("%li %li %li", cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->coords[i].x_pos, cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->coords[i].y_pos, cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->coords[i].image_number)); - } - new_coords_file->Write( ); - new_coords_file->Close( ); - } - } - // Track the currently opened file for saving in case user makes further selections - cisTEMDisplayPanel->ReturnCurrentPanel( )->short_txt_filename = default_filename; - cisTEMDisplayPanel->ReturnCurrentPanel( )->current_file_path = path; - cisTEMDisplayPanel->ReturnCurrentPanel( )->have_txt_filename = true; - cisTEMDisplayPanel->SetTabNameSaved( ); -} - -void DisplayFrame::OnInvertSelectionClick(wxCommandEvent& event) { - for ( long image_counter = 1; image_counter <= cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( ); image_counter++ ) { - cisTEMDisplayPanel->ToggleImageSelected(image_counter, false); - } - cisTEMDisplayPanel->RefreshCurrentPanel( ); - cisTEMDisplayPanel->SetTabNameUnsaved( ); -} - -void DisplayFrame::OnClearSelectionClick(wxCommandEvent& event) { - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { - for ( int image_counter = 0; image_counter < cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( ); image_counter++ ) { - cisTEMDisplayPanel->ClearSelection(false); - } - } - else if ( ! cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { - cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->Clear( ); - } - ClearTextFileFromPanel( ); - cisTEMDisplayPanel->RefreshCurrentPanel( ); -} - -void DisplayFrame::OnSize3(wxCommandEvent& event) { - cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size = 3; - Refresh( ); - Update( ); -} - -void DisplayFrame::OnSize5(wxCommandEvent& event) { - cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size = 5; - Refresh( ); - Update( ); -} - -void DisplayFrame::OnSize7(wxCommandEvent& event) { - cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size = 7; - Refresh( ); - Update( ); -} - -void DisplayFrame::OnSize10(wxCommandEvent& event) { - cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size = 10; - Refresh( ); - Update( ); -} - -void DisplayFrame::OnSingleImageModeClick(wxCommandEvent& event) { - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image ) { - cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image = false; - } - else { - cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image = true; - cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled = false; - } - - cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image_has_correct_greys = false; - cisTEMDisplayPanel->ReturnCurrentPanel( )->ReDrawPanel( ); - Refresh( ); - Update( ); -} - -void DisplayFrame::OnShowSelectionDistancesClick(wxCommandEvent& event) { - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->show_selection_distances ) - cisTEMDisplayPanel->ReturnCurrentPanel( )->show_selection_distances = false; - else - cisTEMDisplayPanel->ReturnCurrentPanel( )->show_selection_distances = true; - Refresh( ); - Update( ); -} - -void DisplayFrame::OnShowResolution(wxCommandEvent& event) { - double wanted_pixel_size; - - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->resolution_instead_of_radius ) - cisTEMDisplayPanel->ReturnCurrentPanel( )->resolution_instead_of_radius = false; - else { - wxTextEntryDialog text_dialog(this, wxT("Pixel Size (Angstroms)"), wxT("Select Pixel Size"), wxString::Format(wxT("%.2f"), cisTEMDisplayPanel->ReturnCurrentPanel( )->pixel_size), wxOK | wxCANCEL | wxCENTRE, wxDefaultPosition); - text_dialog.ShowModal( ); - - wxString current_value = text_dialog.GetValue( ); - text_dialog.Destroy( ); - if ( current_value.ToDouble(&wanted_pixel_size) == true ) { - cisTEMDisplayPanel->ReturnCurrentPanel( )->pixel_size = wanted_pixel_size; - cisTEMDisplayPanel->ReturnCurrentPanel( )->resolution_instead_of_radius = true; - } - } -} - -void DisplayFrame::OnDocumentationClick(wxCommandEvent& event) { - wxLaunchDefaultBrowser("http://www.cistem.org/documentation"); -} - -// This prevents using buttons when an image or stack is not open to act on -void DisplayFrame::DisableAllToolbarButtons( ) { - - // Open menu only needs close tab disabled - DisplayCloseTab->Enable(false); - - // Label menu - LabelLocationNumber->Enable(false); - - // Select menu - SelectImageSelectionMode->Enable(false); - SelectCoordsSelectionMode->Enable(false); - SelectOpenTxt->Enable(false); - SelectSaveTxt->Enable(false); - SelectSaveTxtAs->Enable(false); - SelectInvertSelection->Enable(false); - SelectClearSelection->Enable(false); - - // Options menu - OptionsSingleImageMode->Enable(false); - OptionsShowSelectionDistances->Enable(false); - OptionsShowResolution->Enable(false); -} - -// Call when an image is opened to activate all toolbar buttons -void DisplayFrame::EnableAllToolbarButtons( ) { - // Open menu only needs close tab disabled - DisplayCloseTab->Enable( ); - - // Label menu - LabelLocationNumber->Enable( ); - - // Select menu - SelectImageSelectionMode->Enable(true); - SelectCoordsSelectionMode->Enable(true); - SelectOpenTxt->Enable(true); - SelectSaveTxt->Enable(true); - SelectSaveTxtAs->Enable(true); - SelectInvertSelection->Enable(true); - SelectClearSelection->Enable(true); - - // Options menu - OptionsSingleImageMode->Enable(true); - OptionsShowSelectionDistances->Enable(true); - OptionsShowResolution->Enable(true); -} - -void DisplayFrame::OnUpdateUI(wxUpdateUIEvent& event) { - // First, do we have an image open? - if ( cisTEMDisplayPanel->my_notebook->GetSelection( ) != wxNOT_FOUND ) { - EnableAllToolbarButtons( ); - - // Check that there are coords selected - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->number_of_coords > 0 || cisTEMDisplayPanel->ReturnCurrentPanel( )->number_of_selections > 0 ) { - SelectSaveTxtAs->Enable(true); - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->have_txt_filename ) - SelectSaveTxt->Enable(true); - else - SelectSaveTxt->Enable(false); - } - else { - SelectSaveTxtAs->Enable(false); - SelectSaveTxt->Enable(false); - } - - // Keep picking mode radio buttons visually current - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->image_picking_mode_enabled ) { - SelectImageSelectionMode->Check(true); - SelectInvertSelection->Enable(true); - } - else { - SelectCoordsSelectionMode->Check(true); - SelectInvertSelection->Enable(false); - } - - // Make sure correct radio is checked for point size selection submenu - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size == 3 ) - CoordSize3->Check(true); - else if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size == 5 ) - CoordSize5->Check(true); - else if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size == 7 ) - CoordSize7->Check(true); - else if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size == 10 ) - CoordSize10->Check(true); - - // Make sure single image mode is checked/unchecked based on current panel - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image ) { - if ( ! OptionsSingleImageMode->IsChecked( ) ) - OptionsSingleImageMode->Check(true); - SelectImageSelectionMode->Enable(false); - } - else if ( ! cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image ) { - if ( OptionsSingleImageMode->IsChecked( ) ) - OptionsSingleImageMode->Check(false); - SelectImageSelectionMode->Enable(true); - } - - // Repeat above for res instead of radius - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->resolution_instead_of_radius ) { - if ( ! OptionsShowResolution->IsChecked( ) ) { - OptionsShowResolution->Check(true); - } - } - else if ( ! cisTEMDisplayPanel->ReturnCurrentPanel( )->resolution_instead_of_radius ) { - if ( OptionsShowResolution->IsChecked( ) ) { - OptionsShowResolution->Check(false); - } - } - - // Repeat again for selection distance option - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->show_selection_distances ) { - if ( ! OptionsShowSelectionDistances->IsChecked( ) ) { - OptionsShowSelectionDistances->Check(true); - } - } - else if ( ! cisTEMDisplayPanel->ReturnCurrentPanel( )->show_selection_distances ) { - if ( OptionsShowSelectionDistances->IsChecked( ) ) { - OptionsShowSelectionDistances->Check(false); - } - } - } - // No image -- don't want buttons active - else - DisableAllToolbarButtons( ); -} - -bool DisplayFrame::LoadCoords(wxString current_line, long& x, long& y, long& image_number) { - // Parse the string for x, y, and the image number - int index_of_whitespace = current_line.find(' '); - int prev_whitespace_position = 0; - if ( index_of_whitespace == wxNOT_FOUND ) { - wxMessageDialog wrong_file_format(this, "Cannot open Image Selection text file in Coordinate Selection mode.", "Incorrect File Format", wxOK | wxOK_DEFAULT | wxICON_EXCLAMATION); - wrong_file_format.ShowModal( ); - return false; - } - current_line.SubString(prev_whitespace_position, index_of_whitespace - 1).ToLong(&x); - prev_whitespace_position = index_of_whitespace; - index_of_whitespace = current_line.find(' ', index_of_whitespace + 1); - current_line.SubString(prev_whitespace_position + 1, index_of_whitespace - 1).ToLong(&y); - prev_whitespace_position = index_of_whitespace; - index_of_whitespace = current_line.find('\n', index_of_whitespace + 1); - current_line.SubString(prev_whitespace_position + 1, index_of_whitespace - 1).ToLong(&image_number); - - // First, check that all coordinates and image numbers are valid for the open image - if ( x < cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnImageXSize( ) && y < cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnImageYSize( ) && image_number <= cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( ) ) { - cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->ToggleCoord(image_number, x, y); - return true; - } - else { - wxMessageDialog invalid_file_dialog(this, wxString::Format("The selected coordinates exceed the dimensions of the currently opened *.mrc file. Cannot open selected coordinates.\nSelected x: %li, selected y: %li, image num: %li for image(s) with dimensions x: %i, y: %i, num images: %i).\nTry checking the selection mode and/or the text file contents.", x, y, image_number, cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnImageXSize( ), cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnImageYSize( ), cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( )), "Invalid Coordinates for Current Image(s)", wxOK | wxOK_DEFAULT | wxICON_EXCLAMATION); - if ( invalid_file_dialog.ShowModal( ) == wxID_OK ) - cisTEMDisplayPanel->ReturnCurrentPanel( )->coord_tracker->Clear( ); - return false; - } -} - -bool DisplayFrame::LoadImageSelections(wxString current_line) { - // Quick check of file format - int index_of_whitespace = current_line.find(' '); - if ( index_of_whitespace != wxNOT_FOUND ) { - wxMessageDialog wrong_file_format(this, "Cannot open Coordinate Selection text file in Image Selection mode.", "Incorrect File Format", wxOK | wxOK_DEFAULT | wxICON_EXCLAMATION); - wrong_file_format.ShowModal( ); - return false; - } - - // Get the value that's selected - long image_number; - current_line.ToLong(&image_number); - - if ( image_number <= cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( ) ) { - cisTEMDisplayPanel->ReturnCurrentPanel( )->SetImageSelected(image_number, false); - return true; - } - // If the value exceeds the possible dimensions don't try to access the index for setting selected - else { - wxMessageDialog invalid_file_dialog(this, wxString::Format("The file being opened contains selected images that exceed the number of images in the current file. Cannot open the selections.(Images in open file: %i. Image index sought: %li)", cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnNumberofImages( ), image_number), "Invalid Selection(s) for Current Image(s)", wxOK | wxOK_DEFAULT | wxICON_EXCLAMATION); - cisTEMDisplayPanel->ClearSelection(false); - return false; - } -} - -void DisplayFrame::ClearTextFileFromPanel( ) { - cisTEMDisplayPanel->ReturnCurrentPanel( )->have_txt_filename = false; - cisTEMDisplayPanel->ReturnCurrentPanel( )->short_txt_filename = wxEmptyString; - cisTEMDisplayPanel->ReturnCurrentPanel( )->current_file_path = wxEmptyString; - cisTEMDisplayPanel->SetTabNameSaved( ); -} \ No newline at end of file diff --git a/src/programs/cisTEM_display/display_gui.cpp b/src/programs/cisTEM_display/display_gui.cpp index 4659306b6..43eec2426 100644 --- a/src/programs/cisTEM_display/display_gui.cpp +++ b/src/programs/cisTEM_display/display_gui.cpp @@ -50,6 +50,12 @@ DisplayFrameParent::DisplayFrameParent( wxWindow* parent, wxWindowID id, const w DisplayFileMenu->AppendSeparator(); + SaveDisplayedImages = new wxMenuItem( DisplayFileMenu, wxID_ANY, wxString( wxT("Save Displayed Image(s) As PNG") ) , wxEmptyString, wxITEM_NORMAL ); + DisplayFileMenu->Append( SaveDisplayedImages ); + SaveDisplayedImages->Enable( false ); + + DisplayFileMenu->AppendSeparator(); + SelectOpenTxt = new wxMenuItem( DisplayFileMenu, wxID_ANY, wxString( wxT("Open Text File") ) , wxEmptyString, wxITEM_NORMAL ); DisplayFileMenu->Append( SelectOpenTxt ); SelectOpenTxt->Enable( false ); @@ -155,6 +161,7 @@ DisplayFrameParent::DisplayFrameParent( wxWindow* parent, wxWindowID id, const w this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DisplayFrameParent::OnUpdateUI ) ); DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnFileOpenClick ), this, DisplayFileOpen->GetId()); DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnCloseTabClick ), this, DisplayCloseTab->GetId()); + DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSaveDisplayedImagesClick ), this, SaveDisplayedImages->GetId()); DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnOpenTxtClick ), this, SelectOpenTxt->GetId()); DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSaveTxtClick ), this, SelectSaveTxt->GetId()); DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSaveTxtAsClick ), this, SelectSaveTxtAs->GetId()); diff --git a/src/programs/cisTEM_display/display_gui.h b/src/programs/cisTEM_display/display_gui.h index cffc20797..79f327682 100644 --- a/src/programs/cisTEM_display/display_gui.h +++ b/src/programs/cisTEM_display/display_gui.h @@ -68,6 +68,7 @@ class DisplayFrameParent : public wxFrame wxMenu* DisplayFileMenu; wxMenuItem* DisplayFileOpen; wxMenuItem* DisplayCloseTab; + wxMenuItem* SaveDisplayedImages; wxMenuItem* SelectOpenTxt; wxMenuItem* SelectSaveTxt; wxMenuItem* SelectSaveTxtAs; @@ -95,6 +96,7 @@ class DisplayFrameParent : public wxFrame virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); } virtual void OnFileOpenClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnCloseTabClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnSaveDisplayedImagesClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnOpenTxtClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnSaveTxtClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnSaveTxtAsClick( wxCommandEvent& event ) { event.Skip(); } From 2cbb15e8df64c1b628363281a68fe05ead9af8ce Mon Sep 17 00:00:00 2001 From: twagner9 Date: Wed, 13 Aug 2025 11:17:11 -0400 Subject: [PATCH 04/12] Uncomment logic for showing selection distances --- src/gui/DisplayPanel.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/gui/DisplayPanel.cpp b/src/gui/DisplayPanel.cpp index 207a85817..8cf0f5e2b 100644 --- a/src/gui/DisplayPanel.cpp +++ b/src/gui/DisplayPanel.cpp @@ -1570,14 +1570,16 @@ void DisplayNotebookPanel::UpdateImageStatusInfo(int x_pos, int y_pos) { StatusText += wxT(", Value=") + wxString::Format(wxT("%f"), raw_pixel_value); - //if (selected_distance != 0 && show_selection_distances ) StatusText += wxT(", Dist=") + wxString::Format(wxT("%f"), selected_distance); + if ( selected_distance != 0 && show_selection_distances ) + StatusText += wxT(", Dist=") + wxString::Format(wxT("%f"), selected_distance); //if (image_picking_mode_enabled == INTEGRATE_PICK && integrate_box_x_pos != -1 && integrate_box_y_pos != -1) StatusText += wxT(", Integrated Value =") + wxString::Format(wxT("%f"), integrated_value); parent_display_panel->StatusText->SetLabel(StatusText); } else { wxString StatusText = wxT(""); - //if (selected_distance != 0 && show_selection_distances ) StatusText += wxT("Dist=") + wxString::Format(wxT("%f"), selected_distance); + if ( selected_distance != 0 && show_selection_distances ) + StatusText += wxT("Dist=") + wxString::Format(wxT("%f"), selected_distance); // if (image_picking_mode_enabled == INTEGRATE_PICK && integrate_box_x_pos != -1 && integrate_box_y_pos != -1) StatusText += wxT("Integrated Value =") + wxString::Format(wxT("%f"), integrated_value); parent_display_panel->StatusText->SetLabel(StatusText); } @@ -1614,14 +1616,16 @@ void DisplayNotebookPanel::UpdateImageStatusInfo(int x_pos, int y_pos) { StatusText += wxT(", Value=") + wxString::Format(wxT("%f"), raw_pixel_value); - // if (selected_distance != 0 && show_selection_distances ) StatusText += wxT(", Dist=") + wxString::Format(wxT("%f"), selected_distance); + if ( selected_distance != 0 && show_selection_distances ) + StatusText += wxT(", Dist=") + wxString::Format(wxT("%f"), selected_distance); // if (image_picking_mode_enabled == INTEGRATE_PICK && integrate_box_x_pos != -1 && integrate_box_y_pos != -1) StatusText += wxT(", Integrated Value =") + wxString::Format(wxT("%f"), integrated_value); parent_display_panel->StatusText->SetLabel(StatusText); } else { wxString StatusText = wxT(""); - // if (selected_distance != 0 && show_selection_distances ) StatusText += wxT("Dist=") + wxString::Format(wxT("%f"), selected_distance); + if ( selected_distance != 0 && show_selection_distances ) + StatusText += wxT("Dist=") + wxString::Format(wxT("%f"), selected_distance); // if (image_picking_mode_enabled == INTEGRATE_PICK && integrate_box_x_pos != -1 && integrate_box_y_pos != -1) StatusText += wxT("Integrated Value =") + wxString::Format(wxT("%f"), integrated_value); parent_display_panel->StatusText->SetLabel(StatusText); } @@ -1629,7 +1633,8 @@ void DisplayNotebookPanel::UpdateImageStatusInfo(int x_pos, int y_pos) { else { wxString StatusText = wxT(""); - // if (selected_distance != 0 && show_selection_distances ) StatusText += wxT("Dist=") + wxString::Format(wxT("%f"), selected_distance); + if ( selected_distance != 0 && show_selection_distances ) + StatusText += wxT("Dist=") + wxString::Format(wxT("%f"), selected_distance); // if (image_picking_mode_enabled == INTEGRATE_PICK && integrate_box_x_pos != -1 && integrate_box_y_pos != -1) StatusText += wxT(" Integrated Value =") + wxString::Format(wxT("%f"), integrated_value); parent_display_panel->StatusText->SetLabel(StatusText); } From d55dad0185e35abc4709c309b8e333550d752f1d Mon Sep 17 00:00:00 2001 From: twagner9 Date: Wed, 13 Aug 2025 14:06:55 -0400 Subject: [PATCH 05/12] When saving as PNG, stop at end of relevant bitmap Original bitmap saving to PNG would save the full client panel size, not just the part of the bitmap that contains the relevant info. This updates the logic so that only the relevant porition of the image is saved. --- src/gui/DisplayFrame.cpp | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/gui/DisplayFrame.cpp b/src/gui/DisplayFrame.cpp index 832949b16..0e1cc4584 100644 --- a/src/gui/DisplayFrame.cpp +++ b/src/gui/DisplayFrame.cpp @@ -62,12 +62,11 @@ void DisplayFrame::OnFileOpenClick(wxCommandEvent& event) { } void DisplayFrame::OnSaveDisplayedImagesClick(wxCommandEvent& event) { - // Mimics the logic ProperOverwriteCheckSaveDialog + // Mimics the logic ProperOverwriteCheckSaveDialog in my_controls.cpp wxFileDialog save_file_dialog(this, _("Save png image"), wxEmptyString, wxEmptyString, "PNG files (*.png)|*.png", wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition, wxDefaultSize, wxFileDialogNameStr); wxString wanted_extension = ".png"; wxString default_dir = cisTEMDisplayPanel->ReturnCurrentPanel( )->filename; - wxPrintf("default_dir: %s\n", default_dir); // Strip away the filename to get the directory default_dir = default_dir.BeforeLast('/'); @@ -76,13 +75,38 @@ void DisplayFrame::OnSaveDisplayedImagesClick(wxCommandEvent& event) { wxString extension_lowercase = wanted_extension.Lower( ); wxString extension_uppercase = wanted_extension.Upper( ); - wxPrintf("default_dir: %s\n", default_dir); if ( save_file_dialog.ShowModal( ) == wxID_CANCEL ) { save_file_dialog.Destroy( ); return; } - cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_bitmap.SaveFile(save_file_dialog.GetPath( ), wxBITMAP_TYPE_PNG); + // Crop out the blank space around the image: get the true width of the relevant area on the bitmap. + wxBitmap sub_bitmap; + int sub_bmp_width; + int sub_bmp_height; + int single_image_x = cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image_x; + int single_image_y = cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image_y; + float scale_factor = cisTEMDisplayPanel->ReturnCurrentPanel( )->actual_scale_factor; + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image ) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->GetClientSize(&sub_bmp_width, &sub_bmp_height); + if ( single_image_x * scale_factor + sub_bmp_width > cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetWidth( ) ) { + sub_bmp_width = cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetWidth( ) - single_image_x * scale_factor; + } + if ( single_image_y * scale_factor + sub_bmp_height > cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetHeight( ) ) { + sub_bmp_height = cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetHeight( ) - single_image_y * scale_factor; + } + wxRect sub_bmp_dims(single_image_x * scale_factor, single_image_y * scale_factor, sub_bmp_width, sub_bmp_height); + wxImage tmp_sub_img(cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetSubImage(sub_bmp_dims)); + sub_bitmap = wxBitmap(tmp_sub_img); + } + else { + sub_bmp_width = cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnImageXSize( ) * cisTEMDisplayPanel->ReturnCurrentPanel( )->actual_scale_factor * cisTEMDisplayPanel->ReturnCurrentPanel( )->images_in_x; + sub_bmp_height = cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnImageYSize( ) * cisTEMDisplayPanel->ReturnCurrentPanel( )->actual_scale_factor * cisTEMDisplayPanel->ReturnCurrentPanel( )->images_in_y; + wxRect sub_bmp_dims(single_image_x * scale_factor, single_image_y * scale_factor, sub_bmp_width, sub_bmp_height); + sub_bitmap = cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_bitmap.GetSubBitmap(sub_bmp_dims); + } + + sub_bitmap.SaveFile(save_file_dialog.GetPath( ), wxBITMAP_TYPE_PNG); } void DisplayFrame::OnServerOpenFile(wxCommandEvent& event) { From 066606bd116c7bcd9a3138a3b442adf3da325ffe Mon Sep 17 00:00:00 2001 From: twagner9 Date: Thu, 14 Aug 2025 09:50:52 -0400 Subject: [PATCH 06/12] Add controls manual to help menu in display The cisTEM display program has some keyboard and mouse controls that are not immediately clear upon opening the display. This adds an option to the help menu that will open up the manual and explain some of these controls. In the future, this may also be a good place to add additional information on how a user might go about utilizing the display. --- src/gui/DisplayFrame.cpp | 75 +++++++++++++++++++++ src/gui/DisplayFrame.h | 3 +- src/gui/wxformbuilder/cisTEM_display.fbp | 32 ++++++--- src/programs/cisTEM_display/display_gui.cpp | 4 ++ src/programs/cisTEM_display/display_gui.h | 2 + 5 files changed, 106 insertions(+), 10 deletions(-) diff --git a/src/gui/DisplayFrame.cpp b/src/gui/DisplayFrame.cpp index 0e1cc4584..7880cbbc1 100644 --- a/src/gui/DisplayFrame.cpp +++ b/src/gui/DisplayFrame.cpp @@ -502,6 +502,81 @@ void DisplayFrame::OnDocumentationClick(wxCommandEvent& event) { wxLaunchDefaultBrowser("http://www.cistem.org/documentation"); } +void DisplayFrame::OnDisplayControlsClick(wxCommandEvent& event) { + // 1. Create a simple scroll window dialog + wxDialog* manual_dialog = new wxDialog(this, wxID_ANY, "cisTEM Display Manual", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER, "cisTEM Display Manual"); + + // 2. Populate the dialog with text that explains the display controls + wxScrolledWindow* scrolled_window = new wxScrolledWindow(manual_dialog, wxID_ANY); + wxBoxSizer* content_sizer = new wxBoxSizer(wxVERTICAL); + + wxRichTextCtrl* text_ctrl = new wxRichTextCtrl(scrolled_window, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY); + + text_ctrl->BeginFontSize(16); + text_ctrl->BeginAlignment(wxTEXT_ALIGNMENT_LEFT); + text_ctrl->BeginBold( ); + text_ctrl->WriteText("cisTEM Display Manual\n\n"); + text_ctrl->EndBold( ); + text_ctrl->EndAlignment( ); + text_ctrl->EndFontSize( ); + + text_ctrl->BeginFontSize(12); + text_ctrl->BeginBold( ); + text_ctrl->WriteText("\nKeyboard Shortcuts\n\n"); + text_ctrl->EndBold( ); + text_ctrl->EndFontSize( ); + + text_ctrl->BeginBold( ); + text_ctrl->WriteText("\n1. Left Arrow Key"); + text_ctrl->EndBold( ); + text_ctrl->WriteText(": Scroll to the previous open image tab.\n"); + text_ctrl->BeginBold( ); + text_ctrl->WriteText("2. Right Arrow Key"); + text_ctrl->EndBold( ); + text_ctrl->WriteText(": Scroll to the next open image tab.\n"); + text_ctrl->BeginBold( ); + text_ctrl->WriteText("3. Up Arrow Key"); + text_ctrl->EndBold( ); + text_ctrl->WriteText(": Scroll to the next section of images/slices that will fit within the current display window.\n"); + text_ctrl->BeginBold( ); + text_ctrl->WriteText("4. Down Arrow Key"); + text_ctrl->EndBold( ); + text_ctrl->WriteText(": Scroll to the previous section of images/slices that will fit within the current display window.\n"); + + text_ctrl->BeginBold( ); + text_ctrl->BeginFontSize(12); + text_ctrl->WriteText("\nMouse Controls\n\n"); + text_ctrl->EndFontSize( ); + text_ctrl->WriteText("\n1. Left Mouse Button"); + text_ctrl->EndBold( ); + text_ctrl->WriteText(": Select or deselect images or coordinates, depending on the current picking mode (found within the Select menu).\n"); + text_ctrl->BeginBold( ); + text_ctrl->WriteText("2. Right Mouse Button"); + text_ctrl->EndBold( ); + text_ctrl->WriteText(": Create a zoomed/upscaled subwindow that will display a more detailed view of the image contents below the mouse position. This can be dragged to view different areas of the image.\n"); + text_ctrl->BeginBold( ); + text_ctrl->WriteText("3. Middle Mouse Button"); + text_ctrl->EndBold( ); + text_ctrl->WriteText(": When in Single Image Mode (selected from the Options menu), dragging the mouse will shift the displayed window in the direction of the drag."); + + wxStdDialogButtonSizer* button_sizer = new wxStdDialogButtonSizer( ); + wxButton* ok_button = new wxButton(manual_dialog, wxID_OK); + button_sizer->AddButton(ok_button); + button_sizer->Realize( ); + + content_sizer->Add(text_ctrl, 1, wxEXPAND | wxALL, 10); + scrolled_window->SetSizer(content_sizer); + scrolled_window->SetScrollRate(5, 5); + wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); + main_sizer->Add(scrolled_window, 1, wxEXPAND); + main_sizer->Add(button_sizer, 0, wxALIGN_RIGHT | wxALL, 5); + manual_dialog->SetSizerAndFit(main_sizer); + manual_dialog->SetMinSize(wxSize(900, 500)); + + manual_dialog->Layout( ); + manual_dialog->Show( ); +} + // This prevents using buttons when an image or stack is not open to act on void DisplayFrame::DisableAllToolbarButtons( ) { diff --git a/src/gui/DisplayFrame.h b/src/gui/DisplayFrame.h index 7b21804ca..d2a948475 100644 --- a/src/gui/DisplayFrame.h +++ b/src/gui/DisplayFrame.h @@ -21,7 +21,7 @@ class DisplayFrame : public DisplayFrameParent { // File menu void OnFileOpenClick(wxCommandEvent& event); - void OnSaveDisplayedImagesClick(wxCommandEvent& event); + void OnSaveDisplayedImagesClick(wxCommandEvent& event); void OnCloseTabClick(wxCommandEvent& event); void OnExitClick(wxCommandEvent& event); @@ -48,6 +48,7 @@ class DisplayFrame : public DisplayFrameParent { // Help menu void OnDocumentationClick(wxCommandEvent& event); + void OnDisplayControlsClick(wxCommandEvent& event); private: bool is_fullscreen; diff --git a/src/gui/wxformbuilder/cisTEM_display.fbp b/src/gui/wxformbuilder/cisTEM_display.fbp index 83a0e3db3..7bc48d0af 100644 --- a/src/gui/wxformbuilder/cisTEM_display.fbp +++ b/src/gui/wxformbuilder/cisTEM_display.fbp @@ -29,7 +29,7 @@ 0 1 0 - + 0 wxAUI_MGR_DEFAULT @@ -53,7 +53,7 @@ wxTAB_TRAVERSAL OnMiddleUp - + MainSizer wxVERTICAL @@ -122,7 +122,7 @@ - + 0 wxAUI_MGR_DEFAULT @@ -151,7 +151,7 @@ wxTAB_TRAVERSAL 1 OnUpdateUI - + 1 @@ -172,7 +172,7 @@ - + File DisplayFileMenu protected @@ -208,7 +208,7 @@ m_separator7 none - + 0 0 @@ -222,7 +222,7 @@ OnSaveDisplayedImagesClick - + m_separator71 none @@ -488,6 +488,20 @@ Help DisplayHelpMenu protected + + + 0 + 1 + User Manual for cisTEM Display + wxID_ANY + wxITEM_NORMAL + Display Controls + HelpDisplayControls + protected + + + OnDisplayControlsClick + 0 @@ -568,7 +582,7 @@ - + 0 wxAUI_MGR_DEFAULT @@ -600,7 +614,7 @@ OnMotion OnPaint OnRightDown - + MainSizer wxVERTICAL diff --git a/src/programs/cisTEM_display/display_gui.cpp b/src/programs/cisTEM_display/display_gui.cpp index 43eec2426..dee858aae 100644 --- a/src/programs/cisTEM_display/display_gui.cpp +++ b/src/programs/cisTEM_display/display_gui.cpp @@ -139,6 +139,9 @@ DisplayFrameParent::DisplayFrameParent( wxWindow* parent, wxWindowID id, const w m_menubar2->Append( DisplayOptionsMenu, wxT("Options") ); DisplayHelpMenu = new wxMenu(); + HelpDisplayControls = new wxMenuItem( DisplayHelpMenu, wxID_ANY, wxString( wxT("Display Controls") ) , wxT("User Manual for cisTEM Display"), wxITEM_NORMAL ); + DisplayHelpMenu->Append( HelpDisplayControls ); + HelpAbout = new wxMenuItem( DisplayHelpMenu, wxID_ANY, wxString( wxT("Documentation") ) , wxEmptyString, wxITEM_NORMAL ); DisplayHelpMenu->Append( HelpAbout ); @@ -178,6 +181,7 @@ DisplayFrameParent::DisplayFrameParent( wxWindow* parent, wxWindowID id, const w DisplayOptionsMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSingleImageModeClick ), this, OptionsSingleImageMode->GetId()); DisplayOptionsMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnShowSelectionDistancesClick ), this, OptionsShowSelectionDistances->GetId()); DisplayOptionsMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnShowResolution ), this, OptionsShowResolution->GetId()); + DisplayHelpMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnDisplayControlsClick ), this, HelpDisplayControls->GetId()); DisplayHelpMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnDocumentationClick ), this, HelpAbout->GetId()); } diff --git a/src/programs/cisTEM_display/display_gui.h b/src/programs/cisTEM_display/display_gui.h index 79f327682..6fa60e95b 100644 --- a/src/programs/cisTEM_display/display_gui.h +++ b/src/programs/cisTEM_display/display_gui.h @@ -90,6 +90,7 @@ class DisplayFrameParent : public wxFrame wxMenuItem* OptionsShowSelectionDistances; wxMenuItem* OptionsShowResolution; wxMenu* DisplayHelpMenu; + wxMenuItem* HelpDisplayControls; wxMenuItem* HelpAbout; // Virtual event handlers, override them in your derived class @@ -113,6 +114,7 @@ class DisplayFrameParent : public wxFrame virtual void OnSingleImageModeClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnShowSelectionDistancesClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnShowResolution( wxCommandEvent& event ) { event.Skip(); } + virtual void OnDisplayControlsClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnDocumentationClick( wxCommandEvent& event ) { event.Skip(); } From 99d9c93f79adc6f0a91d2dfa8a043758aebf63d7 Mon Sep 17 00:00:00 2001 From: twagner9 Date: Fri, 29 Aug 2025 14:15:12 -0400 Subject: [PATCH 07/12] feat: add ability to save PNG of MRCs with legend -DisplayFrame has a new option in the File menu that allows users to save their displayed image(s) as a PNG with a legend that displays a grayscale gradient displaying intervals of pixel values. -DisplayPanel now properly stores the number of images in the current view; before it would default to the maximum number of images that could fit on the panel instead of the number actually displayed. --- src/gui/DisplayFrame.cpp | 199 +++++++++++++++++--- src/gui/DisplayFrame.h | 2 + src/gui/DisplayPanel.cpp | 13 +- src/gui/wxformbuilder/cisTEM_display.fbp | 20 +- src/programs/cisTEM_display/display_gui.cpp | 5 + src/programs/cisTEM_display/display_gui.h | 2 + 6 files changed, 215 insertions(+), 26 deletions(-) diff --git a/src/gui/DisplayFrame.cpp b/src/gui/DisplayFrame.cpp index 7880cbbc1..fa29057af 100644 --- a/src/gui/DisplayFrame.cpp +++ b/src/gui/DisplayFrame.cpp @@ -1,5 +1,6 @@ #include "../core/gui_core_headers.h" #include "../programs/cisTEM_display/DisplayServer.h" // includes wxEVT_SERVER_OPEN_FILE +#include DisplayFrame::DisplayFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : DisplayFrameParent(NULL, wxID_ANY, title, pos, size, style) { @@ -81,32 +82,133 @@ void DisplayFrame::OnSaveDisplayedImagesClick(wxCommandEvent& event) { } // Crop out the blank space around the image: get the true width of the relevant area on the bitmap. - wxBitmap sub_bitmap; - int sub_bmp_width; - int sub_bmp_height; - int single_image_x = cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image_x; - int single_image_y = cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image_y; - float scale_factor = cisTEMDisplayPanel->ReturnCurrentPanel( )->actual_scale_factor; - if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image ) { - cisTEMDisplayPanel->ReturnCurrentPanel( )->GetClientSize(&sub_bmp_width, &sub_bmp_height); - if ( single_image_x * scale_factor + sub_bmp_width > cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetWidth( ) ) { - sub_bmp_width = cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetWidth( ) - single_image_x * scale_factor; + wxBitmap sub_bitmap = CropImageForSaving( ); + + sub_bitmap.SaveFile(save_file_dialog.GetPath( ), wxBITMAP_TYPE_PNG); +} + +void DisplayFrame::OnSaveDisplayedImagesWithLegendClick(wxCommandEvent& event) { + // Mimics the logic ProperOverwriteCheckSaveDialog in my_controls.cpp + wxFileDialog save_file_dialog(this, _("Save png image with legend"), wxEmptyString, wxEmptyString, "PNG files (*.png)|*.png", wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition, wxDefaultSize, wxFileDialogNameStr); + + wxString wanted_extension = ".png"; + wxString default_dir = cisTEMDisplayPanel->ReturnCurrentPanel( )->filename; + + // Strip away the filename to get the directory + default_dir = default_dir.BeforeLast('/'); + + save_file_dialog.SetDirectory(default_dir); + wxString extension_lowercase = wanted_extension.Lower( ); + wxString extension_uppercase = wanted_extension.Upper( ); + + if ( save_file_dialog.ShowModal( ) == wxID_CANCEL ) { + save_file_dialog.Destroy( ); + return; + } + + // Crop out the blank space around the image: get the true width of the relevant area on the bitmap. + wxBitmap sub_bitmap = CropImageForSaving( ); + int sub_bmp_width = sub_bitmap.GetWidth( ); + int sub_bmp_height = sub_bitmap.GetHeight( ); + + // Create legend, width of 80 pixels + int legend_width = 80; + + int legend_height = sub_bmp_height; + wxImage legend_img(legend_width, legend_height); + + // Draw color bar gradient; this method calculates a value for each row + // of the legend and fills it in with a grayscale color by using the + // proportional distance from the top (max) to the bottom (min). + for ( int y = 0; y < legend_height; ++y ) { + double t = 1.0 - double(y) / legend_height; + + // Simple grayscale: interpolate between min and max + unsigned char val = static_cast(255 * t); + for ( int x = 0; x < legend_width; ++x ) { + legend_img.SetRGB(x, y, val, val, val); } - if ( single_image_y * scale_factor + sub_bmp_height > cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetHeight( ) ) { - sub_bmp_height = cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetHeight( ) - single_image_y * scale_factor; + } + + // Draw min/max text + // Note: wxImage does not support drawing directly, so we convert to wxBitmap for this step + // and then convert back to wxImage + wxBitmap legend_bmp(legend_img); + wxMemoryDC dc(legend_bmp); + + // Add a spacer between the image and the legend + int spacer_width = 15; + wxImage spacer_img(spacer_width, sub_bmp_height); + for ( int y = 0; y < sub_bmp_height; ++y ) { + for ( int x = 0; x < spacer_width; ++x ) { + spacer_img.SetRGB(x, y, 255, 255, 255); } - wxRect sub_bmp_dims(single_image_x * scale_factor, single_image_y * scale_factor, sub_bmp_width, sub_bmp_height); - wxImage tmp_sub_img(cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetSubImage(sub_bmp_dims)); - sub_bitmap = wxBitmap(tmp_sub_img); } - else { - sub_bmp_width = cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnImageXSize( ) * cisTEMDisplayPanel->ReturnCurrentPanel( )->actual_scale_factor * cisTEMDisplayPanel->ReturnCurrentPanel( )->images_in_x; - sub_bmp_height = cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnImageYSize( ) * cisTEMDisplayPanel->ReturnCurrentPanel( )->actual_scale_factor * cisTEMDisplayPanel->ReturnCurrentPanel( )->images_in_y; - wxRect sub_bmp_dims(single_image_x * scale_factor, single_image_y * scale_factor, sub_bmp_width, sub_bmp_height); - sub_bitmap = cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_bitmap.GetSubBitmap(sub_bmp_dims); + + int combined_width = sub_bmp_width + legend_width + spacer_width; + int white_space = 200; + wxImage background_img(combined_width + white_space, sub_bmp_height + white_space); + for ( int i = 0; i < background_img.GetWidth( ); ++i ) { + for ( int j = 0; j < background_img.GetHeight( ); ++j ) { + background_img.SetRGB(i, j, 255, 255, 255); + } } - sub_bitmap.SaveFile(save_file_dialog.GetPath( ), wxBITMAP_TYPE_PNG); + // Minimum tick spacing should be about 1/5 of the legend height to balance readability and clutter; + // if there is not much space, only use 2 gradations (min and max) + int min_tick_spacing = sub_bmp_height / 5; + int num_gradations = std::max(2, legend_height / min_tick_spacing); + + float min_pixel, max_pixel; + cisTEMDisplayPanel->ReturnCurrentPanel( )->image_memory_buffer->GetMinMax(min_pixel, max_pixel); + float pixel_range = max_pixel - min_pixel; + + // Convert to bitmap to be able to draw + wxBitmap background_bmp(background_img); + dc.SelectObject(background_bmp); + dc.SetPen(wxPen(*wxBLACK, 2)); + + for ( int i = 0; i < num_gradations; ++i ) { + // Spread gradations only across the legend area + int legend_top_y = white_space / 2; + int legend_bottom_y = legend_top_y + legend_height - 1; + int y = legend_top_y + int(i * (legend_height - 1) / (num_gradations - 1)); + + // Calculate the value corresponding to this gradation by interpolating between min and max + double value = max_pixel - (pixel_range * i) / (num_gradations - 1); + + int legend_right_x = sub_bmp_width + spacer_width + white_space / 2 + legend_width; + int gradation_start_x = legend_right_x; + int gradation_end_x = gradation_start_x + 10; + + dc.DrawLine(gradation_start_x, y, gradation_end_x, y); + + // Subtract 12 from y to better align text with gradation line, add 5 to starting point + // to space out from the gradation line + dc.DrawText(wxString::Format("%.2f", value), gradation_end_x + 5, y - 12); + } + + dc.SelectObject(wxNullBitmap); + + // Combine all the images + wxImage combined_img(background_img.GetWidth( ), background_img.GetHeight( ), true); + combined_img.Paste(background_bmp.ConvertToImage( ), 0, 0); + combined_img.Paste(sub_bitmap.ConvertToImage( ), white_space / 2, white_space / 2); + combined_img.Paste(spacer_img, sub_bmp_width + white_space / 2, white_space / 2); + combined_img.Paste(legend_bmp.ConvertToImage( ), sub_bmp_width + spacer_width + white_space / 2, white_space / 2); + + // Finally, draw a rectangle around the legend area to separate it from the background + // This is done last to ensure the rectangle is on top of everything else and transparent + // so there's nothing blocking the view of the legend, but the rectangle border is still + // visible. + wxBitmap combined_bmp(combined_img); + dc.SelectObject(combined_bmp); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRectangle(sub_bmp_width + spacer_width + white_space / 2, white_space / 2, legend_width, legend_height); + combined_img = combined_bmp.ConvertToImage( ); + dc.SelectObject(wxNullBitmap); + + combined_img.SaveFile(save_file_dialog.GetPath( ), wxBITMAP_TYPE_PNG); } void DisplayFrame::OnServerOpenFile(wxCommandEvent& event) { @@ -583,6 +685,7 @@ void DisplayFrame::DisableAllToolbarButtons( ) { // Open menu only needs close tab disabled DisplayCloseTab->Enable(false); SaveDisplayedImages->Enable(false); + SaveDisplayedImagesWithLegend->Enable(false); // Label menu LabelLocationNumber->Enable(false); @@ -607,6 +710,7 @@ void DisplayFrame::EnableAllToolbarButtons( ) { // Open menu only needs close tab disabled DisplayCloseTab->Enable( ); SaveDisplayedImages->Enable( ); + SaveDisplayedImagesWithLegend->Enable( ); // Label menu LabelLocationNumber->Enable( ); @@ -765,4 +869,57 @@ void DisplayFrame::ClearTextFileFromPanel( ) { cisTEMDisplayPanel->ReturnCurrentPanel( )->short_txt_filename = wxEmptyString; cisTEMDisplayPanel->ReturnCurrentPanel( )->current_file_path = wxEmptyString; cisTEMDisplayPanel->SetTabNameSaved( ); +} + +/** + * @brief Crops the current image at the borders to remove excess blank space aroudn the image(s) being displayed. + * + * @return wxBitmap The cropped bitmap ready for saving. + */ +wxBitmap DisplayFrame::CropImageForSaving( ) { + + // TODO: must also account for the case of a single image being displayed but not being in single image mode; + // failure to do so causes the saved image to have excessively large legend (speicfically in terms of legend height) + // because the image is small but the legend is sized for the full panel. + wxBitmap sub_bitmap; + int sub_bmp_width; + int sub_bmp_height; + int single_image_x = cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image_x; + int single_image_y = cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image_y; + float scale_factor = cisTEMDisplayPanel->ReturnCurrentPanel( )->actual_scale_factor; + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image ) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->GetClientSize(&sub_bmp_width, &sub_bmp_height); + if ( single_image_x * scale_factor + sub_bmp_width > cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetWidth( ) ) { + sub_bmp_width = cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetWidth( ) - single_image_x * scale_factor; + } + if ( single_image_y * scale_factor + sub_bmp_height > cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetHeight( ) ) { + sub_bmp_height = cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetHeight( ) - single_image_y * scale_factor; + } + wxRect sub_bmp_dims(single_image_x * scale_factor, single_image_y * scale_factor, sub_bmp_width, sub_bmp_height); + wxImage tmp_sub_img(cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_image->GetSubImage(sub_bmp_dims)); + sub_bitmap = wxBitmap(tmp_sub_img); + } + else { + int num_rows_with_imgs = cisTEMDisplayPanel->ReturnCurrentPanel( )->images_in_current_view / cisTEMDisplayPanel->ReturnCurrentPanel( )->images_in_x; + + // if columns_in_x is 0, then we have less than one full row of images, the number of rows shown is 1 + // if columns_in_x is > 0, then we have at least one full row of images, and the number of rows shown is either 1 or more; + // we can check if it's more than one by using modulus; if it's 0, then all rows are filled, otherwise we have a partial row + // and must increment by 1. + if ( num_rows_with_imgs > 0 ) { + // We have a partial row, so increment filled_rows by 1 + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->images_in_current_view % cisTEMDisplayPanel->ReturnCurrentPanel( )->images_in_x != 0 ) { + num_rows_with_imgs++; + } + } + else { + num_rows_with_imgs = 1; + } + + sub_bmp_width = cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnImageXSize( ) * cisTEMDisplayPanel->ReturnCurrentPanel( )->actual_scale_factor * cisTEMDisplayPanel->ReturnCurrentPanel( )->images_in_x; + sub_bmp_height = cisTEMDisplayPanel->ReturnCurrentPanel( )->ReturnImageYSize( ) * cisTEMDisplayPanel->ReturnCurrentPanel( )->actual_scale_factor * num_rows_with_imgs; + wxRect sub_bmp_dims(single_image_x * scale_factor, single_image_y * scale_factor, sub_bmp_width, sub_bmp_height); + sub_bitmap = cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_bitmap.GetSubBitmap(sub_bmp_dims); + } + return sub_bitmap; } \ No newline at end of file diff --git a/src/gui/DisplayFrame.h b/src/gui/DisplayFrame.h index d2a948475..c2e7ddbde 100644 --- a/src/gui/DisplayFrame.h +++ b/src/gui/DisplayFrame.h @@ -22,6 +22,7 @@ class DisplayFrame : public DisplayFrameParent { // File menu void OnFileOpenClick(wxCommandEvent& event); void OnSaveDisplayedImagesClick(wxCommandEvent& event); + void OnSaveDisplayedImagesWithLegendClick(wxCommandEvent& event); void OnCloseTabClick(wxCommandEvent& event); void OnExitClick(wxCommandEvent& event); @@ -56,6 +57,7 @@ class DisplayFrame : public DisplayFrameParent { bool LoadCoords(wxString current_line, long& x, long& y, long& image_number); bool LoadImageSelections(wxString current_line); void ClearTextFileFromPanel( ); + wxBitmap CropImageForSaving( ); }; #endif \ No newline at end of file diff --git a/src/gui/DisplayPanel.cpp b/src/gui/DisplayPanel.cpp index 8cf0f5e2b..9e2d1324e 100644 --- a/src/gui/DisplayPanel.cpp +++ b/src/gui/DisplayPanel.cpp @@ -2338,8 +2338,17 @@ void DisplayNotebookPanel::ReDrawPanel(void) { images_in_x = 1; images_in_y = 1; } - else - images_in_current_view = images_in_x * images_in_y; + else { + // Checks if the number of images that will be displayed on the panel will fill the available + // space; if not, then we adjust the images_in_current_view to be accurate. + const int imgs_remaining = ReturnNumberofImages( ) + 1 - current_location; + if ( imgs_remaining < images_in_x * images_in_y ) { + images_in_current_view = imgs_remaining; + } + else { + images_in_current_view = images_in_x * images_in_y; + } + } if ( current_location != location_on_last_draw || images_in_x != images_in_x_on_last_draw || images_in_y != images_in_y_on_last_draw ) { //dc.Clear(); diff --git a/src/gui/wxformbuilder/cisTEM_display.fbp b/src/gui/wxformbuilder/cisTEM_display.fbp index 7bc48d0af..d9d1cc2fc 100644 --- a/src/gui/wxformbuilder/cisTEM_display.fbp +++ b/src/gui/wxformbuilder/cisTEM_display.fbp @@ -122,7 +122,7 @@ - + 0 wxAUI_MGR_DEFAULT @@ -151,7 +151,7 @@ wxTAB_TRAVERSAL 1 OnUpdateUI - + 1 @@ -172,7 +172,7 @@ - + File DisplayFileMenu protected @@ -222,6 +222,20 @@ OnSaveDisplayedImagesClick + + + 0 + 0 + + wxID_ANY + wxITEM_NORMAL + Save Displayed Image(s) As PNG with Legend + SaveDisplayedImagesWithLegend + protected + + + OnSaveDisplayedImagesWithLegendClick + m_separator71 none diff --git a/src/programs/cisTEM_display/display_gui.cpp b/src/programs/cisTEM_display/display_gui.cpp index dee858aae..94233c9d1 100644 --- a/src/programs/cisTEM_display/display_gui.cpp +++ b/src/programs/cisTEM_display/display_gui.cpp @@ -54,6 +54,10 @@ DisplayFrameParent::DisplayFrameParent( wxWindow* parent, wxWindowID id, const w DisplayFileMenu->Append( SaveDisplayedImages ); SaveDisplayedImages->Enable( false ); + SaveDisplayedImagesWithLegend = new wxMenuItem( DisplayFileMenu, wxID_ANY, wxString( wxT("Save Displayed Image(s) As PNG with Legend") ) , wxEmptyString, wxITEM_NORMAL ); + DisplayFileMenu->Append( SaveDisplayedImagesWithLegend ); + SaveDisplayedImagesWithLegend->Enable( false ); + DisplayFileMenu->AppendSeparator(); SelectOpenTxt = new wxMenuItem( DisplayFileMenu, wxID_ANY, wxString( wxT("Open Text File") ) , wxEmptyString, wxITEM_NORMAL ); @@ -165,6 +169,7 @@ DisplayFrameParent::DisplayFrameParent( wxWindow* parent, wxWindowID id, const w DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnFileOpenClick ), this, DisplayFileOpen->GetId()); DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnCloseTabClick ), this, DisplayCloseTab->GetId()); DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSaveDisplayedImagesClick ), this, SaveDisplayedImages->GetId()); + DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSaveDisplayedImagesWithLegendClick ), this, SaveDisplayedImagesWithLegend->GetId()); DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnOpenTxtClick ), this, SelectOpenTxt->GetId()); DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSaveTxtClick ), this, SelectSaveTxt->GetId()); DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSaveTxtAsClick ), this, SelectSaveTxtAs->GetId()); diff --git a/src/programs/cisTEM_display/display_gui.h b/src/programs/cisTEM_display/display_gui.h index 6fa60e95b..a24dee893 100644 --- a/src/programs/cisTEM_display/display_gui.h +++ b/src/programs/cisTEM_display/display_gui.h @@ -69,6 +69,7 @@ class DisplayFrameParent : public wxFrame wxMenuItem* DisplayFileOpen; wxMenuItem* DisplayCloseTab; wxMenuItem* SaveDisplayedImages; + wxMenuItem* SaveDisplayedImagesWithLegend; wxMenuItem* SelectOpenTxt; wxMenuItem* SelectSaveTxt; wxMenuItem* SelectSaveTxtAs; @@ -98,6 +99,7 @@ class DisplayFrameParent : public wxFrame virtual void OnFileOpenClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnCloseTabClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnSaveDisplayedImagesClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnSaveDisplayedImagesWithLegendClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnOpenTxtClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnSaveTxtClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnSaveTxtAsClick( wxCommandEvent& event ) { event.Skip(); } From 8797fb3d2351102587c4b665441ba6d513fc96d0 Mon Sep 17 00:00:00 2001 From: twagner9 Date: Thu, 16 Oct 2025 14:27:05 -0400 Subject: [PATCH 08/12] Add CLI flag cisTEM_display.cpp: -Now uses wxCmdLineParser to check for a switch, -n, which will allow users to open a new instance of cisTEM_display WITH arguments, instead of forcing users to open in the current display server. Requested by @timothygrant80. clang-format for MyRefinementResultsPanel.h --- src/gui/MyRefinementResultsPanel.h | 2 +- .../cisTEM_display/cisTEM_display.cpp | 52 +++++++++++++------ 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/gui/MyRefinementResultsPanel.h b/src/gui/MyRefinementResultsPanel.h index c24b59afe..34995ab26 100644 --- a/src/gui/MyRefinementResultsPanel.h +++ b/src/gui/MyRefinementResultsPanel.h @@ -26,7 +26,7 @@ class MyRefinementResultsPanel : public RefinementResultsPanel { void OnClassComboBoxChange(wxCommandEvent& event); void AngularPlotPopupClick(wxCommandEvent& event); void PopupParametersClick(wxCommandEvent& event); - void SaveBinnedPlotClick(wxCommandEvent& event); + void SaveBinnedPlotClick(wxCommandEvent& event); void UpdateCachedRefinement( ); void UpdateBufferedFullRefinement( ); diff --git a/src/programs/cisTEM_display/cisTEM_display.cpp b/src/programs/cisTEM_display/cisTEM_display.cpp index d58739d90..dfc48679d 100644 --- a/src/programs/cisTEM_display/cisTEM_display.cpp +++ b/src/programs/cisTEM_display/cisTEM_display.cpp @@ -20,21 +20,35 @@ class DisplayApp : public wxApp { private: wxSingleInstanceChecker* m_checker; + bool new_instance; + wxArrayString files_to_open; + // MyServer* m_server; }; +static const wxCmdLineEntryDesc display_cmd_line_desc[] = { + {wxCMD_LINE_SWITCH, "h", "help", "displays help on the command line parameters", wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP}, + {wxCMD_LINE_SWITCH, "n", "new-instance", "force starting a new instance, even if another is already running", wxCMD_LINE_VAL_NONE, 0}, + {wxCMD_LINE_PARAM, nullptr, nullptr, "file(s) to open", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE}, + {wxCMD_LINE_NONE}}; + IMPLEMENT_APP(DisplayApp) -DisplayFrame* display_frame; +DisplayFrame* + display_frame; DisplayApp::~DisplayApp( ) { DisplayServer::GetInstance( ).Stop( ); } bool DisplayApp::OnInit( ) { + if ( ! wxApp::OnInit( ) ) + return false; + + // new_instance = m_parser->Found(wxT("n")); const wxString name = wxString::Format("cisTEM_Display-%s", wxGetUserId( )); m_checker = new wxSingleInstanceChecker(name); - if ( m_checker->IsAnotherRunning( ) ) { + if ( m_checker->IsAnotherRunning( ) && ! new_instance ) { if ( argc > 1 ) { int sock = socket(AF_UNIX, SOCK_STREAM, 0); if ( sock != -1 ) { @@ -43,11 +57,8 @@ bool DisplayApp::OnInit( ) { addr.sun_family = AF_UNIX; strcpy(addr.sun_path, SOCKET_PATH.c_str( )); if ( connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0 ) { - for ( int i = 1; i < argc; i++ ) { - wxFileName filename(argv[i]); - filename.Normalize(wxPATH_NORM_LONG | wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_ABSOLUTE); - wxString cmd_full_filename = filename.GetFullPath( ); - wxScopedCharBuffer buffer = cmd_full_filename.ToUTF8( ); + for ( size_t i = 0; i < files_to_open.GetCount( ); i++ ) { + wxScopedCharBuffer buffer = files_to_open[i].ToUTF8( ); write(sock, buffer.data( ), buffer.length( )); write(sock, "\n", 1); } @@ -60,6 +71,10 @@ bool DisplayApp::OnInit( ) { return false; } } + else if ( m_checker->IsAnotherRunning( ) && new_instance ) { + // Now make sure we proceed with opening a new application instance + wxPrintf("Proceding with opening a new instance...\n"); + } else { SetupSignalHandlers( ); DisplayServer::GetInstance( ).Start( ); @@ -71,15 +86,8 @@ bool DisplayApp::OnInit( ) { wxString cmd_full_filename; wxString cmd_filename; - // Check if filenames are present; if so, open them - if ( argc > 1 ) { - for ( int i = 1; i < argc; i++ ) { - cmd_filename = argv[i]; - wxFileName filename(cmd_filename); - filename.Normalize(wxPATH_NORM_LONG | wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_ABSOLUTE); - cmd_full_filename = filename.GetFullPath( ); - display_frame->cisTEMDisplayPanel->OpenFile(cmd_full_filename, cmd_full_filename); - } + for ( int i = 0; i < files_to_open.GetCount( ); i++ ) { + display_frame->cisTEMDisplayPanel->OpenFile(files_to_open[i], files_to_open[i]); } display_frame->Layout( ); @@ -88,10 +96,20 @@ bool DisplayApp::OnInit( ) { } void DisplayApp::OnInitCmdLine(wxCmdLineParser& parser) { + parser.SetDesc(display_cmd_line_desc); + parser.SetSwitchChars(wxT("-")); } bool DisplayApp::OnCmdLineParsed(wxCmdLineParser& parser) { - + new_instance = parser.Found(wxT("n")); + + for ( size_t arg_counter = 0; arg_counter < parser.GetParamCount( ); arg_counter++ ) { + wxString cmd_filename = parser.GetParam(arg_counter); + wxFileName filename(cmd_filename); + filename.Normalize(wxPATH_NORM_LONG | wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_ABSOLUTE); + wxString cmd_full_filename = filename.GetFullPath( ); + files_to_open.Add(cmd_full_filename); + } return true; } From 4a2203cdac7f3eae01f927a9d5c46cb4589fe496 Mon Sep 17 00:00:00 2001 From: twagner9 Date: Tue, 28 Oct 2025 09:59:25 -0400 Subject: [PATCH 09/12] bugfix: keep name after image selections -DisplayPanel.cpp: Previously, the short_image_filename member of the DisplayNotebookPanel class was not being updated to store the wanted tab title, and would leave only an '*' character. This causes the assignment to happen during the OpenFile function instead of outside of it, so that the tab title will always be properly displayed. Also unifies the display when opening from CLI or the file opening dialog so that only the file name is displayed rather than the absolute path. The absolute path can still be displayed by hovering to get a tooltip. -cisTEM_display.cpp: gets the wanted tab title so that it can be passed to DisplayPanel::OpenFile and properly store the file name. --- src/gui/DisplayPanel.cpp | 3 ++- src/programs/cisTEM_display/cisTEM_display.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/DisplayPanel.cpp b/src/gui/DisplayPanel.cpp index 9e2d1324e..6cd26046e 100644 --- a/src/gui/DisplayPanel.cpp +++ b/src/gui/DisplayPanel.cpp @@ -407,7 +407,6 @@ void DisplayPanel::OnOpen(wxCommandEvent& WXUNUSED(event)) { extension is included in this list, which is not robust against the various extensions that could exist*/ OpenFile(path, this_filename); - ReturnCurrentPanel( )->short_image_filename = this_filename; } else wxMessageBox(wxT("This file is not a compatible type; must be mrc file format."), wxT("Error"), wxOK | wxICON_INFORMATION); @@ -855,6 +854,8 @@ void DisplayPanel::OpenFile(wxString wanted_filename, wxString wanted_tab_title, return; } + my_panel->short_image_filename = wanted_tab_title; + // which images are we including.. if ( wanted_included_image_numbers == NULL ) { diff --git a/src/programs/cisTEM_display/cisTEM_display.cpp b/src/programs/cisTEM_display/cisTEM_display.cpp index dfc48679d..b471b12cd 100644 --- a/src/programs/cisTEM_display/cisTEM_display.cpp +++ b/src/programs/cisTEM_display/cisTEM_display.cpp @@ -87,7 +87,8 @@ bool DisplayApp::OnInit( ) { wxString cmd_filename; for ( int i = 0; i < files_to_open.GetCount( ); i++ ) { - display_frame->cisTEMDisplayPanel->OpenFile(files_to_open[i], files_to_open[i]); + wxString tab_title = wxFileName(files_to_open[i]).GetFullName( ); + display_frame->cisTEMDisplayPanel->OpenFile(files_to_open[i], tab_title); } display_frame->Layout( ); From 0825ec6de259902c17af1dea9c16ca3aff119541 Mon Sep 17 00:00:00 2001 From: twagner9 Date: Mon, 27 Apr 2026 15:32:17 -0400 Subject: [PATCH 10/12] Applied clang format to all unformatted files --- src/programs/cisTEM_display/DisplayServer.cpp | 1 - src/programs/cisTEM_display/display_gui.cpp | 441 +++++++++--------- src/programs/cisTEM_display/display_gui.h | 264 ++++++----- .../measure_template_bias.cpp | 141 +++--- .../sum_all_eer_files/sum_all_eer_files.cpp | 32 +- 5 files changed, 439 insertions(+), 440 deletions(-) diff --git a/src/programs/cisTEM_display/DisplayServer.cpp b/src/programs/cisTEM_display/DisplayServer.cpp index 1d1a62f34..134c191ec 100644 --- a/src/programs/cisTEM_display/DisplayServer.cpp +++ b/src/programs/cisTEM_display/DisplayServer.cpp @@ -68,7 +68,6 @@ void DisplayServer::ServerLoop( ) { std::string filename = buffer.substr(start, pos - start); start = pos + 1; - if ( ! filename.empty( ) ) { wxString message = wxString::FromUTF8(filename.c_str( )).Trim( ); wxCommandEvent evt(EVT_SERVER_OPEN_FILE, 1000); diff --git a/src/programs/cisTEM_display/display_gui.cpp b/src/programs/cisTEM_display/display_gui.cpp index 94233c9d1..ab24ad8e1 100644 --- a/src/programs/cisTEM_display/display_gui.cpp +++ b/src/programs/cisTEM_display/display_gui.cpp @@ -11,322 +11,299 @@ /////////////////////////////////////////////////////////////////////////// -DisplayPanelParent::DisplayPanelParent( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name ) -{ - MainSizer = new wxBoxSizer( wxVERTICAL ); +DisplayPanelParent::DisplayPanelParent(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxPanel(parent, id, pos, size, style, name) { + MainSizer = new wxBoxSizer(wxVERTICAL); - Toolbar = new wxToolBar( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_FLAT|wxTB_HORIZONTAL ); - Toolbar->Realize(); + Toolbar = new wxToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_FLAT | wxTB_HORIZONTAL); + Toolbar->Realize( ); - MainSizer->Add( Toolbar, 0, wxEXPAND, 5 ); + MainSizer->Add(Toolbar, 0, wxEXPAND, 5); + this->SetSizer(MainSizer); + this->Layout( ); - this->SetSizer( MainSizer ); - this->Layout(); - - // Connect Events - this->Connect( wxEVT_MIDDLE_UP, wxMouseEventHandler( DisplayPanelParent::OnMiddleUp ) ); + // Connect Events + this->Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler(DisplayPanelParent::OnMiddleUp)); } -DisplayPanelParent::~DisplayPanelParent() -{ - // Disconnect Events - this->Disconnect( wxEVT_MIDDLE_UP, wxMouseEventHandler( DisplayPanelParent::OnMiddleUp ) ); - +DisplayPanelParent::~DisplayPanelParent( ) { + // Disconnect Events + this->Disconnect(wxEVT_MIDDLE_UP, wxMouseEventHandler(DisplayPanelParent::OnMiddleUp)); } -DisplayFrameParent::DisplayFrameParent( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - m_menubar2 = new wxMenuBar( 0 ); - DisplayFileMenu = new wxMenu(); - DisplayFileOpen = new wxMenuItem( DisplayFileMenu, wxID_ANY, wxString( wxT("Open Image") ) , wxEmptyString, wxITEM_NORMAL ); - DisplayFileMenu->Append( DisplayFileOpen ); +DisplayFrameParent::DisplayFrameParent(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxFrame(parent, id, title, pos, size, style) { + this->SetSizeHints(wxDefaultSize, wxDefaultSize); - DisplayCloseTab = new wxMenuItem( DisplayFileMenu, wxID_ANY, wxString( wxT("Close tab") ) , wxEmptyString, wxITEM_NORMAL ); - DisplayFileMenu->Append( DisplayCloseTab ); - DisplayCloseTab->Enable( false ); + m_menubar2 = new wxMenuBar(0); + DisplayFileMenu = new wxMenu( ); + DisplayFileOpen = new wxMenuItem(DisplayFileMenu, wxID_ANY, wxString(wxT("Open Image")), wxEmptyString, wxITEM_NORMAL); + DisplayFileMenu->Append(DisplayFileOpen); - DisplayFileMenu->AppendSeparator(); + DisplayCloseTab = new wxMenuItem(DisplayFileMenu, wxID_ANY, wxString(wxT("Close tab")), wxEmptyString, wxITEM_NORMAL); + DisplayFileMenu->Append(DisplayCloseTab); + DisplayCloseTab->Enable(false); - SaveDisplayedImages = new wxMenuItem( DisplayFileMenu, wxID_ANY, wxString( wxT("Save Displayed Image(s) As PNG") ) , wxEmptyString, wxITEM_NORMAL ); - DisplayFileMenu->Append( SaveDisplayedImages ); - SaveDisplayedImages->Enable( false ); + DisplayFileMenu->AppendSeparator( ); - SaveDisplayedImagesWithLegend = new wxMenuItem( DisplayFileMenu, wxID_ANY, wxString( wxT("Save Displayed Image(s) As PNG with Legend") ) , wxEmptyString, wxITEM_NORMAL ); - DisplayFileMenu->Append( SaveDisplayedImagesWithLegend ); - SaveDisplayedImagesWithLegend->Enable( false ); + SaveDisplayedImages = new wxMenuItem(DisplayFileMenu, wxID_ANY, wxString(wxT("Save Displayed Image(s) As PNG")), wxEmptyString, wxITEM_NORMAL); + DisplayFileMenu->Append(SaveDisplayedImages); + SaveDisplayedImages->Enable(false); - DisplayFileMenu->AppendSeparator(); + SaveDisplayedImagesWithLegend = new wxMenuItem(DisplayFileMenu, wxID_ANY, wxString(wxT("Save Displayed Image(s) As PNG with Legend")), wxEmptyString, wxITEM_NORMAL); + DisplayFileMenu->Append(SaveDisplayedImagesWithLegend); + SaveDisplayedImagesWithLegend->Enable(false); - SelectOpenTxt = new wxMenuItem( DisplayFileMenu, wxID_ANY, wxString( wxT("Open Text File") ) , wxEmptyString, wxITEM_NORMAL ); - DisplayFileMenu->Append( SelectOpenTxt ); - SelectOpenTxt->Enable( false ); + DisplayFileMenu->AppendSeparator( ); - SelectSaveTxt = new wxMenuItem( DisplayFileMenu, wxID_ANY, wxString( wxT("Save Text File") ) , wxEmptyString, wxITEM_NORMAL ); - DisplayFileMenu->Append( SelectSaveTxt ); - SelectSaveTxt->Enable( false ); + SelectOpenTxt = new wxMenuItem(DisplayFileMenu, wxID_ANY, wxString(wxT("Open Text File")), wxEmptyString, wxITEM_NORMAL); + DisplayFileMenu->Append(SelectOpenTxt); + SelectOpenTxt->Enable(false); - SelectSaveTxtAs = new wxMenuItem( DisplayFileMenu, wxID_ANY, wxString( wxT("Save Text File As") ) , wxEmptyString, wxITEM_NORMAL ); - DisplayFileMenu->Append( SelectSaveTxtAs ); - SelectSaveTxtAs->Enable( false ); + SelectSaveTxt = new wxMenuItem(DisplayFileMenu, wxID_ANY, wxString(wxT("Save Text File")), wxEmptyString, wxITEM_NORMAL); + DisplayFileMenu->Append(SelectSaveTxt); + SelectSaveTxt->Enable(false); - DisplayFileMenu->AppendSeparator(); + SelectSaveTxtAs = new wxMenuItem(DisplayFileMenu, wxID_ANY, wxString(wxT("Save Text File As")), wxEmptyString, wxITEM_NORMAL); + DisplayFileMenu->Append(SelectSaveTxtAs); + SelectSaveTxtAs->Enable(false); - DisplayExit = new wxMenuItem( DisplayFileMenu, wxID_ANY, wxString( wxT("Exit") ) , wxEmptyString, wxITEM_NORMAL ); - DisplayFileMenu->Append( DisplayExit ); + DisplayFileMenu->AppendSeparator( ); - m_menubar2->Append( DisplayFileMenu, wxT("File") ); + DisplayExit = new wxMenuItem(DisplayFileMenu, wxID_ANY, wxString(wxT("Exit")), wxEmptyString, wxITEM_NORMAL); + DisplayFileMenu->Append(DisplayExit); - DisplayLabelMenu = new wxMenu(); - LabelLocationNumber = new wxMenuItem( DisplayLabelMenu, wxID_ANY, wxString( wxT("Location Number") ) , wxEmptyString, wxITEM_CHECK ); - DisplayLabelMenu->Append( LabelLocationNumber ); - LabelLocationNumber->Enable( false ); - LabelLocationNumber->Check( true ); + m_menubar2->Append(DisplayFileMenu, wxT("File")); - m_menubar2->Append( DisplayLabelMenu, wxT("Label") ); + DisplayLabelMenu = new wxMenu( ); + LabelLocationNumber = new wxMenuItem(DisplayLabelMenu, wxID_ANY, wxString(wxT("Location Number")), wxEmptyString, wxITEM_CHECK); + DisplayLabelMenu->Append(LabelLocationNumber); + LabelLocationNumber->Enable(false); + LabelLocationNumber->Check(true); - DisplaySelectMenu = new wxMenu(); - SelectImageSelectionMode = new wxMenuItem( DisplaySelectMenu, wxID_ANY, wxString( wxT("Image Selection Mode") ) , wxEmptyString, wxITEM_RADIO ); - DisplaySelectMenu->Append( SelectImageSelectionMode ); - SelectImageSelectionMode->Enable( false ); - SelectImageSelectionMode->Check( true ); + m_menubar2->Append(DisplayLabelMenu, wxT("Label")); - SelectCoordsSelectionMode = new wxMenuItem( DisplaySelectMenu, wxID_ANY, wxString( wxT("Coords Selection Mode") ) , wxEmptyString, wxITEM_RADIO ); - DisplaySelectMenu->Append( SelectCoordsSelectionMode ); - SelectCoordsSelectionMode->Enable( false ); + DisplaySelectMenu = new wxMenu( ); + SelectImageSelectionMode = new wxMenuItem(DisplaySelectMenu, wxID_ANY, wxString(wxT("Image Selection Mode")), wxEmptyString, wxITEM_RADIO); + DisplaySelectMenu->Append(SelectImageSelectionMode); + SelectImageSelectionMode->Enable(false); + SelectImageSelectionMode->Check(true); - DisplaySelectMenu->AppendSeparator(); + SelectCoordsSelectionMode = new wxMenuItem(DisplaySelectMenu, wxID_ANY, wxString(wxT("Coords Selection Mode")), wxEmptyString, wxITEM_RADIO); + DisplaySelectMenu->Append(SelectCoordsSelectionMode); + SelectCoordsSelectionMode->Enable(false); - SelectInvertSelection = new wxMenuItem( DisplaySelectMenu, wxID_ANY, wxString( wxT("Invert Selection") ) , wxEmptyString, wxITEM_NORMAL ); - DisplaySelectMenu->Append( SelectInvertSelection ); - SelectInvertSelection->Enable( false ); + DisplaySelectMenu->AppendSeparator( ); - SelectClearSelection = new wxMenuItem( DisplaySelectMenu, wxID_ANY, wxString( wxT("Clear Selection") ) , wxEmptyString, wxITEM_NORMAL ); - DisplaySelectMenu->Append( SelectClearSelection ); - SelectClearSelection->Enable( false ); + SelectInvertSelection = new wxMenuItem(DisplaySelectMenu, wxID_ANY, wxString(wxT("Invert Selection")), wxEmptyString, wxITEM_NORMAL); + DisplaySelectMenu->Append(SelectInvertSelection); + SelectInvertSelection->Enable(false); - m_menubar2->Append( DisplaySelectMenu, wxT("Select") ); + SelectClearSelection = new wxMenuItem(DisplaySelectMenu, wxID_ANY, wxString(wxT("Clear Selection")), wxEmptyString, wxITEM_NORMAL); + DisplaySelectMenu->Append(SelectClearSelection); + SelectClearSelection->Enable(false); - DisplayOptionsMenu = new wxMenu(); - OptionsSetPointSize = new wxMenu(); - wxMenuItem* OptionsSetPointSizeItem = new wxMenuItem( DisplayOptionsMenu, wxID_ANY, wxT("Set Point Size"), wxEmptyString, wxITEM_NORMAL, OptionsSetPointSize ); - CoordSize3 = new wxMenuItem( OptionsSetPointSize, wxID_ANY, wxString( wxT("3") ) , wxEmptyString, wxITEM_RADIO ); - OptionsSetPointSize->Append( CoordSize3 ); + m_menubar2->Append(DisplaySelectMenu, wxT("Select")); - CoordSize5 = new wxMenuItem( OptionsSetPointSize, wxID_ANY, wxString( wxT("5") ) , wxEmptyString, wxITEM_RADIO ); - OptionsSetPointSize->Append( CoordSize5 ); + DisplayOptionsMenu = new wxMenu( ); + OptionsSetPointSize = new wxMenu( ); + wxMenuItem* OptionsSetPointSizeItem = new wxMenuItem(DisplayOptionsMenu, wxID_ANY, wxT("Set Point Size"), wxEmptyString, wxITEM_NORMAL, OptionsSetPointSize); + CoordSize3 = new wxMenuItem(OptionsSetPointSize, wxID_ANY, wxString(wxT("3")), wxEmptyString, wxITEM_RADIO); + OptionsSetPointSize->Append(CoordSize3); - CoordSize7 = new wxMenuItem( OptionsSetPointSize, wxID_ANY, wxString( wxT("7") ) , wxEmptyString, wxITEM_RADIO ); - OptionsSetPointSize->Append( CoordSize7 ); + CoordSize5 = new wxMenuItem(OptionsSetPointSize, wxID_ANY, wxString(wxT("5")), wxEmptyString, wxITEM_RADIO); + OptionsSetPointSize->Append(CoordSize5); - CoordSize10 = new wxMenuItem( OptionsSetPointSize, wxID_ANY, wxString( wxT("10") ) , wxEmptyString, wxITEM_RADIO ); - OptionsSetPointSize->Append( CoordSize10 ); + CoordSize7 = new wxMenuItem(OptionsSetPointSize, wxID_ANY, wxString(wxT("7")), wxEmptyString, wxITEM_RADIO); + OptionsSetPointSize->Append(CoordSize7); - DisplayOptionsMenu->Append( OptionsSetPointSizeItem ); + CoordSize10 = new wxMenuItem(OptionsSetPointSize, wxID_ANY, wxString(wxT("10")), wxEmptyString, wxITEM_RADIO); + OptionsSetPointSize->Append(CoordSize10); - OptionsSingleImageMode = new wxMenuItem( DisplayOptionsMenu, wxID_ANY, wxString( wxT("Single Image Mode") ) , wxEmptyString, wxITEM_CHECK ); - DisplayOptionsMenu->Append( OptionsSingleImageMode ); - OptionsSingleImageMode->Enable( false ); + DisplayOptionsMenu->Append(OptionsSetPointSizeItem); - OptionsShowSelectionDistances = new wxMenuItem( DisplayOptionsMenu, wxID_ANY, wxString( wxT("Show Selection Distances") ) , wxEmptyString, wxITEM_CHECK ); - DisplayOptionsMenu->Append( OptionsShowSelectionDistances ); - OptionsShowSelectionDistances->Enable( false ); + OptionsSingleImageMode = new wxMenuItem(DisplayOptionsMenu, wxID_ANY, wxString(wxT("Single Image Mode")), wxEmptyString, wxITEM_CHECK); + DisplayOptionsMenu->Append(OptionsSingleImageMode); + OptionsSingleImageMode->Enable(false); - DisplayOptionsMenu->AppendSeparator(); + OptionsShowSelectionDistances = new wxMenuItem(DisplayOptionsMenu, wxID_ANY, wxString(wxT("Show Selection Distances")), wxEmptyString, wxITEM_CHECK); + DisplayOptionsMenu->Append(OptionsShowSelectionDistances); + OptionsShowSelectionDistances->Enable(false); - OptionsShowResolution = new wxMenuItem( DisplayOptionsMenu, wxID_ANY, wxString( wxT("Show Resolution Instead of Radius") ) , wxEmptyString, wxITEM_CHECK ); - DisplayOptionsMenu->Append( OptionsShowResolution ); - OptionsShowResolution->Enable( false ); + DisplayOptionsMenu->AppendSeparator( ); - m_menubar2->Append( DisplayOptionsMenu, wxT("Options") ); + OptionsShowResolution = new wxMenuItem(DisplayOptionsMenu, wxID_ANY, wxString(wxT("Show Resolution Instead of Radius")), wxEmptyString, wxITEM_CHECK); + DisplayOptionsMenu->Append(OptionsShowResolution); + OptionsShowResolution->Enable(false); - DisplayHelpMenu = new wxMenu(); - HelpDisplayControls = new wxMenuItem( DisplayHelpMenu, wxID_ANY, wxString( wxT("Display Controls") ) , wxT("User Manual for cisTEM Display"), wxITEM_NORMAL ); - DisplayHelpMenu->Append( HelpDisplayControls ); + m_menubar2->Append(DisplayOptionsMenu, wxT("Options")); - HelpAbout = new wxMenuItem( DisplayHelpMenu, wxID_ANY, wxString( wxT("Documentation") ) , wxEmptyString, wxITEM_NORMAL ); - DisplayHelpMenu->Append( HelpAbout ); + DisplayHelpMenu = new wxMenu( ); + HelpDisplayControls = new wxMenuItem(DisplayHelpMenu, wxID_ANY, wxString(wxT("Display Controls")), wxT("User Manual for cisTEM Display"), wxITEM_NORMAL); + DisplayHelpMenu->Append(HelpDisplayControls); - m_menubar2->Append( DisplayHelpMenu, wxT("Help") ); + HelpAbout = new wxMenuItem(DisplayHelpMenu, wxID_ANY, wxString(wxT("Documentation")), wxEmptyString, wxITEM_NORMAL); + DisplayHelpMenu->Append(HelpAbout); - this->SetMenuBar( m_menubar2 ); + m_menubar2->Append(DisplayHelpMenu, wxT("Help")); - bSizer631 = new wxBoxSizer( wxVERTICAL ); + this->SetMenuBar(m_menubar2); - cisTEMDisplayPanel = new DisplayPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - bSizer631->Add( cisTEMDisplayPanel, 1, wxEXPAND | wxALL, 5 ); + bSizer631 = new wxBoxSizer(wxVERTICAL); + cisTEMDisplayPanel = new DisplayPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); + bSizer631->Add(cisTEMDisplayPanel, 1, wxEXPAND | wxALL, 5); - this->SetSizer( bSizer631 ); - this->Layout(); + this->SetSizer(bSizer631); + this->Layout( ); - this->Centre( wxBOTH ); + this->Centre(wxBOTH); - // Connect Events - this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DisplayFrameParent::OnUpdateUI ) ); - DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnFileOpenClick ), this, DisplayFileOpen->GetId()); - DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnCloseTabClick ), this, DisplayCloseTab->GetId()); - DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSaveDisplayedImagesClick ), this, SaveDisplayedImages->GetId()); - DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSaveDisplayedImagesWithLegendClick ), this, SaveDisplayedImagesWithLegend->GetId()); - DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnOpenTxtClick ), this, SelectOpenTxt->GetId()); - DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSaveTxtClick ), this, SelectSaveTxt->GetId()); - DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSaveTxtAsClick ), this, SelectSaveTxtAs->GetId()); - DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnExitClick ), this, DisplayExit->GetId()); - DisplayLabelMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnLocationNumberClick ), this, LabelLocationNumber->GetId()); - DisplaySelectMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnImageSelectionModeClick ), this, SelectImageSelectionMode->GetId()); - DisplaySelectMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnCoordsSelectionModeClick ), this, SelectCoordsSelectionMode->GetId()); - DisplaySelectMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnInvertSelectionClick ), this, SelectInvertSelection->GetId()); - DisplaySelectMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnClearSelectionClick ), this, SelectClearSelection->GetId()); - OptionsSetPointSize->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSize3 ), this, CoordSize3->GetId()); - OptionsSetPointSize->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSize5 ), this, CoordSize5->GetId()); - OptionsSetPointSize->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSize7 ), this, CoordSize7->GetId()); - OptionsSetPointSize->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSize10 ), this, CoordSize10->GetId()); - DisplayOptionsMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnSingleImageModeClick ), this, OptionsSingleImageMode->GetId()); - DisplayOptionsMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnShowSelectionDistancesClick ), this, OptionsShowSelectionDistances->GetId()); - DisplayOptionsMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnShowResolution ), this, OptionsShowResolution->GetId()); - DisplayHelpMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnDisplayControlsClick ), this, HelpDisplayControls->GetId()); - DisplayHelpMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( DisplayFrameParent::OnDocumentationClick ), this, HelpAbout->GetId()); + // Connect Events + this->Connect(wxEVT_UPDATE_UI, wxUpdateUIEventHandler(DisplayFrameParent::OnUpdateUI)); + DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnFileOpenClick), this, DisplayFileOpen->GetId( )); + DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnCloseTabClick), this, DisplayCloseTab->GetId( )); + DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnSaveDisplayedImagesClick), this, SaveDisplayedImages->GetId( )); + DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnSaveDisplayedImagesWithLegendClick), this, SaveDisplayedImagesWithLegend->GetId( )); + DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnOpenTxtClick), this, SelectOpenTxt->GetId( )); + DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnSaveTxtClick), this, SelectSaveTxt->GetId( )); + DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnSaveTxtAsClick), this, SelectSaveTxtAs->GetId( )); + DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnExitClick), this, DisplayExit->GetId( )); + DisplayLabelMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnLocationNumberClick), this, LabelLocationNumber->GetId( )); + DisplaySelectMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnImageSelectionModeClick), this, SelectImageSelectionMode->GetId( )); + DisplaySelectMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnCoordsSelectionModeClick), this, SelectCoordsSelectionMode->GetId( )); + DisplaySelectMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnInvertSelectionClick), this, SelectInvertSelection->GetId( )); + DisplaySelectMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnClearSelectionClick), this, SelectClearSelection->GetId( )); + OptionsSetPointSize->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnSize3), this, CoordSize3->GetId( )); + OptionsSetPointSize->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnSize5), this, CoordSize5->GetId( )); + OptionsSetPointSize->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnSize7), this, CoordSize7->GetId( )); + OptionsSetPointSize->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnSize10), this, CoordSize10->GetId( )); + DisplayOptionsMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnSingleImageModeClick), this, OptionsSingleImageMode->GetId( )); + DisplayOptionsMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnShowSelectionDistancesClick), this, OptionsShowSelectionDistances->GetId( )); + DisplayOptionsMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnShowResolution), this, OptionsShowResolution->GetId( )); + DisplayHelpMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnDisplayControlsClick), this, HelpDisplayControls->GetId( )); + DisplayHelpMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnDocumentationClick), this, HelpAbout->GetId( )); } -DisplayFrameParent::~DisplayFrameParent() -{ - // Disconnect Events - this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DisplayFrameParent::OnUpdateUI ) ); - +DisplayFrameParent::~DisplayFrameParent( ) { + // Disconnect Events + this->Disconnect(wxEVT_UPDATE_UI, wxUpdateUIEventHandler(DisplayFrameParent::OnUpdateUI)); } -DisplayManualDialogParent::DisplayManualDialogParent( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - MainSizer = new wxBoxSizer( wxVERTICAL ); - - - MainSizer->Add( 400, 200, 0, wxFIXED_MINSIZE, 5 ); - - m_staticline58 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - MainSizer->Add( m_staticline58, 0, wxEXPAND | wxALL, 5 ); - - wxBoxSizer* bSizer262; - bSizer262 = new wxBoxSizer( wxHORIZONTAL ); +DisplayManualDialogParent::DisplayManualDialogParent(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxDialog(parent, id, title, pos, size, style) { + this->SetSizeHints(wxDefaultSize, wxDefaultSize); + MainSizer = new wxBoxSizer(wxVERTICAL); - bSizer262->Add( 0, 0, 1, wxEXPAND, 5 ); + MainSizer->Add(400, 200, 0, wxFIXED_MINSIZE, 5); - m_staticText315 = new wxStaticText( this, wxID_ANY, wxT("Min : "), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText315->Wrap( -1 ); - bSizer262->Add( m_staticText315, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + m_staticline58 = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL); + MainSizer->Add(m_staticline58, 0, wxEXPAND | wxALL, 5); - minimum_text_ctrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER|wxTE_CENTER ); - bSizer262->Add( minimum_text_ctrl, 0, wxALL, 5 ); + wxBoxSizer* bSizer262; + bSizer262 = new wxBoxSizer(wxHORIZONTAL); - m_staticText316 = new wxStaticText( this, wxID_ANY, wxT("/"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText316->Wrap( -1 ); - bSizer262->Add( m_staticText316, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizer262->Add(0, 0, 1, wxEXPAND, 5); - maximum_text_ctrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER|wxTE_CENTER ); - bSizer262->Add( maximum_text_ctrl, 0, wxALL, 5 ); + m_staticText315 = new wxStaticText(this, wxID_ANY, wxT("Min : "), wxDefaultPosition, wxDefaultSize, 0); + m_staticText315->Wrap(-1); + bSizer262->Add(m_staticText315, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); - m_staticText317 = new wxStaticText( this, wxID_ANY, wxT(": Max"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText317->Wrap( -1 ); - bSizer262->Add( m_staticText317, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + minimum_text_ctrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER | wxTE_CENTER); + bSizer262->Add(minimum_text_ctrl, 0, wxALL, 5); + m_staticText316 = new wxStaticText(this, wxID_ANY, wxT("/"), wxDefaultPosition, wxDefaultSize, 0); + m_staticText316->Wrap(-1); + bSizer262->Add(m_staticText316, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); - bSizer262->Add( 0, 0, 1, wxEXPAND, 5 ); + maximum_text_ctrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER | wxTE_CENTER); + bSizer262->Add(maximum_text_ctrl, 0, wxALL, 5); + m_staticText317 = new wxStaticText(this, wxID_ANY, wxT(": Max"), wxDefaultPosition, wxDefaultSize, 0); + m_staticText317->Wrap(-1); + bSizer262->Add(m_staticText317, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); - MainSizer->Add( bSizer262, 0, wxEXPAND, 5 ); + bSizer262->Add(0, 0, 1, wxEXPAND, 5); - wxBoxSizer* bSizer265; - bSizer265 = new wxBoxSizer( wxHORIZONTAL ); + MainSizer->Add(bSizer262, 0, wxEXPAND, 5); + wxBoxSizer* bSizer265; + bSizer265 = new wxBoxSizer(wxHORIZONTAL); - bSizer265->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer265->Add(0, 0, 1, wxEXPAND, 5); - Toolbar = new wxToolBar( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL ); - Toolbar->Realize(); + Toolbar = new wxToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL); + Toolbar->Realize( ); - bSizer265->Add( Toolbar, 0, 0, 5 ); + bSizer265->Add(Toolbar, 0, 0, 5); + bSizer265->Add(0, 0, 1, wxEXPAND, 5); - bSizer265->Add( 0, 0, 1, wxEXPAND, 5 ); + MainSizer->Add(bSizer265, 0, wxEXPAND, 5); + m_staticline61 = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL); + MainSizer->Add(m_staticline61, 0, wxEXPAND | wxALL, 5); - MainSizer->Add( bSizer265, 0, wxEXPAND, 5 ); + wxGridSizer* gSizer13; + gSizer13 = new wxGridSizer(0, 2, 0, 0); - m_staticline61 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - MainSizer->Add( m_staticline61, 0, wxEXPAND | wxALL, 5 ); + histogram_checkbox = new wxCheckBox(this, wxID_ANY, wxT("Use Entire File For Histogram"), wxDefaultPosition, wxDefaultSize, 0); + gSizer13->Add(histogram_checkbox, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5); - wxGridSizer* gSizer13; - gSizer13 = new wxGridSizer( 0, 2, 0, 0 ); + live_checkbox = new wxCheckBox(this, wxID_ANY, wxT("Live Update of Display"), wxDefaultPosition, wxDefaultSize, 0); + live_checkbox->SetValue(true); + gSizer13->Add(live_checkbox, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5); - histogram_checkbox = new wxCheckBox( this, wxID_ANY, wxT("Use Entire File For Histogram"), wxDefaultPosition, wxDefaultSize, 0 ); - gSizer13->Add( histogram_checkbox, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + MainSizer->Add(gSizer13, 0, wxEXPAND, 5); - live_checkbox = new wxCheckBox( this, wxID_ANY, wxT("Live Update of Display"), wxDefaultPosition, wxDefaultSize, 0 ); - live_checkbox->SetValue(true); - gSizer13->Add( live_checkbox, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + m_staticline63 = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL); + MainSizer->Add(m_staticline63, 0, wxEXPAND | wxALL, 5); + wxBoxSizer* bSizer264; + bSizer264 = new wxBoxSizer(wxHORIZONTAL); - MainSizer->Add( gSizer13, 0, wxEXPAND, 5 ); + bSizer264->Add(0, 0, 1, wxEXPAND, 5); - m_staticline63 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - MainSizer->Add( m_staticline63, 0, wxEXPAND | wxALL, 5 ); + m_button94 = new wxButton(this, wxID_ANY, wxT("OK"), wxDefaultPosition, wxDefaultSize, 0); + bSizer264->Add(m_button94, 0, wxALL, 5); - wxBoxSizer* bSizer264; - bSizer264 = new wxBoxSizer( wxHORIZONTAL ); + m_button95 = new wxButton(this, wxID_ANY, wxT("Cancel"), wxDefaultPosition, wxDefaultSize, 0); + bSizer264->Add(m_button95, 0, wxALL, 5); + bSizer264->Add(0, 0, 1, wxEXPAND, 5); - bSizer264->Add( 0, 0, 1, wxEXPAND, 5 ); + MainSizer->Add(bSizer264, 0, wxEXPAND, 5); - m_button94 = new wxButton( this, wxID_ANY, wxT("OK"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer264->Add( m_button94, 0, wxALL, 5 ); + this->SetSizer(MainSizer); + this->Layout( ); + MainSizer->Fit(this); - m_button95 = new wxButton( this, wxID_ANY, wxT("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer264->Add( m_button95, 0, wxALL, 5 ); + this->Centre(wxBOTH); - - bSizer264->Add( 0, 0, 1, wxEXPAND, 5 ); - - - MainSizer->Add( bSizer264, 0, wxEXPAND, 5 ); - - - this->SetSizer( MainSizer ); - this->Layout(); - MainSizer->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DisplayManualDialogParent::OnClose ) ); - this->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DisplayManualDialogParent::OnLeftDown ) ); - this->Connect( wxEVT_MOTION, wxMouseEventHandler( DisplayManualDialogParent::OnMotion ) ); - this->Connect( wxEVT_PAINT, wxPaintEventHandler( DisplayManualDialogParent::OnPaint ) ); - this->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( DisplayManualDialogParent::OnRightDown ) ); - minimum_text_ctrl->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DisplayManualDialogParent::OnLowChange ), NULL, this ); - maximum_text_ctrl->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DisplayManualDialogParent::OnHighChange ), NULL, this ); - histogram_checkbox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DisplayManualDialogParent::OnHistogramCheck ), NULL, this ); - live_checkbox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DisplayManualDialogParent::OnRealtimeCheck ), NULL, this ); - m_button94->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DisplayManualDialogParent::OnButtonOK ), NULL, this ); - m_button95->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DisplayManualDialogParent::OnButtonCancel ), NULL, this ); + // Connect Events + this->Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(DisplayManualDialogParent::OnClose)); + this->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(DisplayManualDialogParent::OnLeftDown)); + this->Connect(wxEVT_MOTION, wxMouseEventHandler(DisplayManualDialogParent::OnMotion)); + this->Connect(wxEVT_PAINT, wxPaintEventHandler(DisplayManualDialogParent::OnPaint)); + this->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(DisplayManualDialogParent::OnRightDown)); + minimum_text_ctrl->Connect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(DisplayManualDialogParent::OnLowChange), NULL, this); + maximum_text_ctrl->Connect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(DisplayManualDialogParent::OnHighChange), NULL, this); + histogram_checkbox->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(DisplayManualDialogParent::OnHistogramCheck), NULL, this); + live_checkbox->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(DisplayManualDialogParent::OnRealtimeCheck), NULL, this); + m_button94->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DisplayManualDialogParent::OnButtonOK), NULL, this); + m_button95->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DisplayManualDialogParent::OnButtonCancel), NULL, this); } -DisplayManualDialogParent::~DisplayManualDialogParent() -{ - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DisplayManualDialogParent::OnClose ) ); - this->Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DisplayManualDialogParent::OnLeftDown ) ); - this->Disconnect( wxEVT_MOTION, wxMouseEventHandler( DisplayManualDialogParent::OnMotion ) ); - this->Disconnect( wxEVT_PAINT, wxPaintEventHandler( DisplayManualDialogParent::OnPaint ) ); - this->Disconnect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( DisplayManualDialogParent::OnRightDown ) ); - minimum_text_ctrl->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DisplayManualDialogParent::OnLowChange ), NULL, this ); - maximum_text_ctrl->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DisplayManualDialogParent::OnHighChange ), NULL, this ); - histogram_checkbox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DisplayManualDialogParent::OnHistogramCheck ), NULL, this ); - live_checkbox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DisplayManualDialogParent::OnRealtimeCheck ), NULL, this ); - m_button94->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DisplayManualDialogParent::OnButtonOK ), NULL, this ); - m_button95->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DisplayManualDialogParent::OnButtonCancel ), NULL, this ); - +DisplayManualDialogParent::~DisplayManualDialogParent( ) { + // Disconnect Events + this->Disconnect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(DisplayManualDialogParent::OnClose)); + this->Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(DisplayManualDialogParent::OnLeftDown)); + this->Disconnect(wxEVT_MOTION, wxMouseEventHandler(DisplayManualDialogParent::OnMotion)); + this->Disconnect(wxEVT_PAINT, wxPaintEventHandler(DisplayManualDialogParent::OnPaint)); + this->Disconnect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(DisplayManualDialogParent::OnRightDown)); + minimum_text_ctrl->Disconnect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(DisplayManualDialogParent::OnLowChange), NULL, this); + maximum_text_ctrl->Disconnect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(DisplayManualDialogParent::OnHighChange), NULL, this); + histogram_checkbox->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(DisplayManualDialogParent::OnHistogramCheck), NULL, this); + live_checkbox->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(DisplayManualDialogParent::OnRealtimeCheck), NULL, this); + m_button94->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DisplayManualDialogParent::OnButtonOK), NULL, this); + m_button95->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DisplayManualDialogParent::OnButtonCancel), NULL, this); } diff --git a/src/programs/cisTEM_display/display_gui.h b/src/programs/cisTEM_display/display_gui.h index a24dee893..9712eba61 100644 --- a/src/programs/cisTEM_display/display_gui.h +++ b/src/programs/cisTEM_display/display_gui.h @@ -36,142 +36,162 @@ class DisplayPanel; /////////////////////////////////////////////////////////////////////////////// /// Class DisplayPanelParent /////////////////////////////////////////////////////////////////////////////// -class DisplayPanelParent : public wxPanel -{ - private: +class DisplayPanelParent : public wxPanel { + private: - protected: - wxBoxSizer* MainSizer; - wxToolBar* Toolbar; + protected: + wxBoxSizer* MainSizer; + wxToolBar* Toolbar; - // Virtual event handlers, override them in your derived class - virtual void OnMiddleUp( wxMouseEvent& event ) { event.Skip(); } + // Virtual event handlers, override them in your derived class + virtual void OnMiddleUp(wxMouseEvent& event) { event.Skip( ); } + public: + DisplayPanelParent(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(500, 300), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString); - public: - - DisplayPanelParent( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString ); - - ~DisplayPanelParent(); - + ~DisplayPanelParent( ); }; /////////////////////////////////////////////////////////////////////////////// /// Class DisplayFrameParent /////////////////////////////////////////////////////////////////////////////// -class DisplayFrameParent : public wxFrame -{ - private: - - protected: - wxMenuBar* m_menubar2; - wxMenu* DisplayFileMenu; - wxMenuItem* DisplayFileOpen; - wxMenuItem* DisplayCloseTab; - wxMenuItem* SaveDisplayedImages; - wxMenuItem* SaveDisplayedImagesWithLegend; - wxMenuItem* SelectOpenTxt; - wxMenuItem* SelectSaveTxt; - wxMenuItem* SelectSaveTxtAs; - wxMenuItem* DisplayExit; - wxMenu* DisplayLabelMenu; - wxMenuItem* LabelLocationNumber; - wxMenu* DisplaySelectMenu; - wxMenuItem* SelectImageSelectionMode; - wxMenuItem* SelectCoordsSelectionMode; - wxMenuItem* SelectInvertSelection; - wxMenuItem* SelectClearSelection; - wxMenu* DisplayOptionsMenu; - wxMenu* OptionsSetPointSize; - wxMenuItem* CoordSize3; - wxMenuItem* CoordSize5; - wxMenuItem* CoordSize7; - wxMenuItem* CoordSize10; - wxMenuItem* OptionsSingleImageMode; - wxMenuItem* OptionsShowSelectionDistances; - wxMenuItem* OptionsShowResolution; - wxMenu* DisplayHelpMenu; - wxMenuItem* HelpDisplayControls; - wxMenuItem* HelpAbout; - - // Virtual event handlers, override them in your derived class - virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); } - virtual void OnFileOpenClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCloseTabClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSaveDisplayedImagesClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSaveDisplayedImagesWithLegendClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnOpenTxtClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSaveTxtClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSaveTxtAsClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnExitClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnLocationNumberClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnImageSelectionModeClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCoordsSelectionModeClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnInvertSelectionClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnClearSelectionClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSize3( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSize5( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSize7( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSize10( wxCommandEvent& event ) { event.Skip(); } - virtual void OnSingleImageModeClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnShowSelectionDistancesClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnShowResolution( wxCommandEvent& event ) { event.Skip(); } - virtual void OnDisplayControlsClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnDocumentationClick( wxCommandEvent& event ) { event.Skip(); } - - - public: - wxBoxSizer* bSizer631; - DisplayPanel* cisTEMDisplayPanel; - - DisplayFrameParent( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("cisTEM Display"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); - - ~DisplayFrameParent(); +class DisplayFrameParent : public wxFrame { + private: + + protected: + wxMenuBar* m_menubar2; + wxMenu* DisplayFileMenu; + wxMenuItem* DisplayFileOpen; + wxMenuItem* DisplayCloseTab; + wxMenuItem* SaveDisplayedImages; + wxMenuItem* SaveDisplayedImagesWithLegend; + wxMenuItem* SelectOpenTxt; + wxMenuItem* SelectSaveTxt; + wxMenuItem* SelectSaveTxtAs; + wxMenuItem* DisplayExit; + wxMenu* DisplayLabelMenu; + wxMenuItem* LabelLocationNumber; + wxMenu* DisplaySelectMenu; + wxMenuItem* SelectImageSelectionMode; + wxMenuItem* SelectCoordsSelectionMode; + wxMenuItem* SelectInvertSelection; + wxMenuItem* SelectClearSelection; + wxMenu* DisplayOptionsMenu; + wxMenu* OptionsSetPointSize; + wxMenuItem* CoordSize3; + wxMenuItem* CoordSize5; + wxMenuItem* CoordSize7; + wxMenuItem* CoordSize10; + wxMenuItem* OptionsSingleImageMode; + wxMenuItem* OptionsShowSelectionDistances; + wxMenuItem* OptionsShowResolution; + wxMenu* DisplayHelpMenu; + wxMenuItem* HelpDisplayControls; + wxMenuItem* HelpAbout; + + // Virtual event handlers, override them in your derived class + virtual void OnUpdateUI(wxUpdateUIEvent& event) { event.Skip( ); } + + virtual void OnFileOpenClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnCloseTabClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnSaveDisplayedImagesClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnSaveDisplayedImagesWithLegendClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnOpenTxtClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnSaveTxtClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnSaveTxtAsClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnExitClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnLocationNumberClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnImageSelectionModeClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnCoordsSelectionModeClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnInvertSelectionClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnClearSelectionClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnSize3(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnSize5(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnSize7(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnSize10(wxCommandEvent& event) { event.Skip( ); } + virtual void OnSingleImageModeClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnShowSelectionDistancesClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnShowResolution(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnDisplayControlsClick(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnDocumentationClick(wxCommandEvent& event) { event.Skip( ); } + + public: + wxBoxSizer* bSizer631; + DisplayPanel* cisTEMDisplayPanel; + + DisplayFrameParent(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("cisTEM Display"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(500, 300), long style = wxDEFAULT_FRAME_STYLE | wxTAB_TRAVERSAL); + + ~DisplayFrameParent( ); }; /////////////////////////////////////////////////////////////////////////////// /// Class DisplayManualDialogParent /////////////////////////////////////////////////////////////////////////////// -class DisplayManualDialogParent : public wxDialog -{ - private: - - protected: - wxBoxSizer* MainSizer; - wxStaticLine* m_staticline58; - wxStaticText* m_staticText315; - wxTextCtrl* minimum_text_ctrl; - wxStaticText* m_staticText316; - wxTextCtrl* maximum_text_ctrl; - wxStaticText* m_staticText317; - wxToolBar* Toolbar; - wxStaticLine* m_staticline61; - wxCheckBox* histogram_checkbox; - wxCheckBox* live_checkbox; - wxStaticLine* m_staticline63; - wxButton* m_button94; - wxButton* m_button95; - - // Virtual event handlers, override them in your derived class - virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } - virtual void OnLeftDown( wxMouseEvent& event ) { event.Skip(); } - virtual void OnMotion( wxMouseEvent& event ) { event.Skip(); } - virtual void OnPaint( wxPaintEvent& event ) { event.Skip(); } - virtual void OnRightDown( wxMouseEvent& event ) { event.Skip(); } - virtual void OnLowChange( wxCommandEvent& event ) { event.Skip(); } - virtual void OnHighChange( wxCommandEvent& event ) { event.Skip(); } - virtual void OnHistogramCheck( wxCommandEvent& event ) { event.Skip(); } - virtual void OnRealtimeCheck( wxCommandEvent& event ) { event.Skip(); } - virtual void OnButtonOK( wxCommandEvent& event ) { event.Skip(); } - virtual void OnButtonCancel( wxCommandEvent& event ) { event.Skip(); } - - - public: - - DisplayManualDialogParent( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Manual Grey Settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - - ~DisplayManualDialogParent(); +class DisplayManualDialogParent : public wxDialog { + private: -}; + protected: + wxBoxSizer* MainSizer; + wxStaticLine* m_staticline58; + wxStaticText* m_staticText315; + wxTextCtrl* minimum_text_ctrl; + wxStaticText* m_staticText316; + wxTextCtrl* maximum_text_ctrl; + wxStaticText* m_staticText317; + wxToolBar* Toolbar; + wxStaticLine* m_staticline61; + wxCheckBox* histogram_checkbox; + wxCheckBox* live_checkbox; + wxStaticLine* m_staticline63; + wxButton* m_button94; + wxButton* m_button95; + + // Virtual event handlers, override them in your derived class + virtual void OnClose(wxCloseEvent& event) { event.Skip( ); } + + virtual void OnLeftDown(wxMouseEvent& event) { event.Skip( ); } + + virtual void OnMotion(wxMouseEvent& event) { event.Skip( ); } + virtual void OnPaint(wxPaintEvent& event) { event.Skip( ); } + + virtual void OnRightDown(wxMouseEvent& event) { event.Skip( ); } + + virtual void OnLowChange(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnHighChange(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnHistogramCheck(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnRealtimeCheck(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnButtonOK(wxCommandEvent& event) { event.Skip( ); } + + virtual void OnButtonCancel(wxCommandEvent& event) { event.Skip( ); } + + public: + DisplayManualDialogParent(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Manual Grey Settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE); + + ~DisplayManualDialogParent( ); +}; diff --git a/src/programs/measure_template_bias/measure_template_bias.cpp b/src/programs/measure_template_bias/measure_template_bias.cpp index 0dcbeec31..bc839103b 100644 --- a/src/programs/measure_template_bias/measure_template_bias.cpp +++ b/src/programs/measure_template_bias/measure_template_bias.cpp @@ -20,15 +20,16 @@ void MeasureTemplateBiasApp::DoInteractiveUserInput( ) { wxString input_diff_template; wxString input_full_template; wxString input_omit_template; - bool input_diff_map; + bool input_diff_map; UserInput* my_input = new UserInput("MeasureTemplateBias", 1.0); input_diff_map = my_input->GetYesNoFromUser("Input template diff map?", "If No, the difference map will be calculated from the full and omit templates", "No"); if ( input_diff_map == true ) { - input_diff_template = my_input->GetFilenameFromUser("Input diff template", "The difference map, full - omit template", "diff_template.mrc", true); - } else{ + input_diff_template = my_input->GetFilenameFromUser("Input diff template", "The difference map, full - omit template", "diff_template.mrc", true); + } + else { input_full_template = my_input->GetFilenameFromUser("Input full template", "The 3D map of the full template", "full_template.mrc", true); input_omit_template = my_input->GetFilenameFromUser("Input omit template", "The 3D map of the omit template", "omit_template.mrc", true); } @@ -37,12 +38,12 @@ void MeasureTemplateBiasApp::DoInteractiveUserInput( ) { delete my_input; my_current_job.ManualSetArguments("bttttt", - input_diff_map, - input_diff_template.ToUTF8( ).data( ), - input_full_template.ToUTF8( ).data( ), - input_omit_template.ToUTF8( ).data( ), - input_reconstruction_full_template.ToUTF8( ).data( ), - input_reconstruction_omit_template.ToUTF8( ).data( )); + input_diff_map, + input_diff_template.ToUTF8( ).data( ), + input_full_template.ToUTF8( ).data( ), + input_omit_template.ToUTF8( ).data( ), + input_reconstruction_full_template.ToUTF8( ).data( ), + input_reconstruction_omit_template.ToUTF8( ).data( )); } // override the do calculation method which will be what is actually run.. @@ -52,25 +53,25 @@ bool MeasureTemplateBiasApp::DoCalculation( ) { long count1 = 0; float correlation_3ds; float correlation_templates; -// float sigma_diff_template; -// float sigma_full_template; -// float sigma_omit_template; - float sum_3d_full = 0.0f; - float sum_3d_omit = 0.0f; + // float sigma_diff_template; + // float sigma_full_template; + // float sigma_omit_template; + float sum_3d_full = 0.0f; + float sum_3d_omit = 0.0f; float sum_difference = 0.0f; -// float mask_radius; + // float mask_radius; float max_value; Image input_3d_full; - Image input_3d_omit; - Image input_diff; - Image input_full; - Image input_omit; -// Image mask_3d; - - bool input_diff_map = my_current_job.arguments[0].ReturnBoolArgument( ); - wxString input_diff_template = my_current_job.arguments[1].ReturnStringArgument( ); - wxString input_full_template = my_current_job.arguments[2].ReturnStringArgument( ); - wxString input_omit_template = my_current_job.arguments[3].ReturnStringArgument( ); + Image input_3d_omit; + Image input_diff; + Image input_full; + Image input_omit; + // Image mask_3d; + + bool input_diff_map = my_current_job.arguments[0].ReturnBoolArgument( ); + wxString input_diff_template = my_current_job.arguments[1].ReturnStringArgument( ); + wxString input_full_template = my_current_job.arguments[2].ReturnStringArgument( ); + wxString input_omit_template = my_current_job.arguments[3].ReturnStringArgument( ); wxString input_reconstruction_full_template = my_current_job.arguments[4].ReturnStringArgument( ); wxString input_reconstruction_omit_template = my_current_job.arguments[5].ReturnStringArgument( ); @@ -78,7 +79,7 @@ bool MeasureTemplateBiasApp::DoCalculation( ) { MRCFile input_file_3d_omit(input_reconstruction_omit_template.ToStdString( ), false); if ( input_diff_map == true ) { MRCFile input_file_diff(input_diff_template.ToStdString( ), false); - if ( (input_file_3d_full.ReturnXSize( ) != input_file_diff.ReturnXSize( )) || (input_file_3d_full.ReturnYSize( ) != input_file_diff.ReturnYSize( )) || (input_file_3d_full.ReturnZSize( ) != input_file_diff.ReturnZSize( )) ) { + if ( (input_file_3d_full.ReturnXSize( ) != input_file_diff.ReturnXSize( )) || (input_file_3d_full.ReturnYSize( ) != input_file_diff.ReturnYSize( )) || (input_file_3d_full.ReturnZSize( ) != input_file_diff.ReturnZSize( )) ) { MyPrintWithDetails("Error: Input maps do not have the same dimensions\n"); DEBUG_ABORT; } @@ -86,14 +87,15 @@ bool MeasureTemplateBiasApp::DoCalculation( ) { // Making sure that the memory reserved for FFTs is also set to zero input_diff.SetToConstant(0.0f); input_diff.ReadSlices(&input_file_diff, 1, input_file_diff.ReturnZSize( )); - } else { + } + else { MRCFile input_file_full(input_full_template.ToStdString( ), false); MRCFile input_file_omit(input_omit_template.ToStdString( ), false); - if ( (input_file_3d_full.ReturnXSize( ) != input_file_full.ReturnXSize( )) || (input_file_3d_full.ReturnYSize( ) != input_file_full.ReturnYSize( )) || (input_file_3d_full.ReturnZSize( ) != input_file_full.ReturnZSize( )) ) { + if ( (input_file_3d_full.ReturnXSize( ) != input_file_full.ReturnXSize( )) || (input_file_3d_full.ReturnYSize( ) != input_file_full.ReturnYSize( )) || (input_file_3d_full.ReturnZSize( ) != input_file_full.ReturnZSize( )) ) { MyPrintWithDetails("Error: Input maps do not have the same dimensions\n"); DEBUG_ABORT; } - if ( (input_file_3d_full.ReturnXSize( ) != input_file_omit.ReturnXSize( )) || (input_file_3d_full.ReturnYSize( ) != input_file_omit.ReturnYSize( )) || (input_file_3d_full.ReturnZSize( ) != input_file_omit.ReturnZSize( )) ) { + if ( (input_file_3d_full.ReturnXSize( ) != input_file_omit.ReturnXSize( )) || (input_file_3d_full.ReturnYSize( ) != input_file_omit.ReturnYSize( )) || (input_file_3d_full.ReturnZSize( ) != input_file_omit.ReturnZSize( )) ) { MyPrintWithDetails("Error: Input maps do not have the same dimensions\n"); DEBUG_ABORT; } @@ -106,50 +108,51 @@ bool MeasureTemplateBiasApp::DoCalculation( ) { input_omit.ReadSlices(&input_file_omit, 1, input_file_omit.ReturnZSize( )); } - if ( (input_file_3d_full.ReturnXSize( ) != input_file_3d_omit.ReturnXSize( )) || (input_file_3d_full.ReturnYSize( ) != input_file_3d_omit.ReturnYSize( )) || (input_file_3d_full.ReturnZSize( ) != input_file_3d_omit.ReturnZSize( )) ) { + if ( (input_file_3d_full.ReturnXSize( ) != input_file_3d_omit.ReturnXSize( )) || (input_file_3d_full.ReturnYSize( ) != input_file_3d_omit.ReturnYSize( )) || (input_file_3d_full.ReturnZSize( ) != input_file_3d_omit.ReturnZSize( )) ) { MyPrintWithDetails("Error: Input maps do not have the same dimensions\n"); DEBUG_ABORT; } input_3d_full.Allocate(input_file_3d_full.ReturnXSize( ), input_file_3d_full.ReturnYSize( ), input_file_3d_full.ReturnZSize( ), true); input_3d_omit.Allocate(input_file_3d_omit.ReturnXSize( ), input_file_3d_omit.ReturnYSize( ), input_file_3d_omit.ReturnZSize( ), true); -// mask_3d.Allocate(input_file_3d_full.ReturnXSize( ), input_file_3d_full.ReturnYSize( ), input_file_3d_full.ReturnZSize( ), true); + // mask_3d.Allocate(input_file_3d_full.ReturnXSize( ), input_file_3d_full.ReturnYSize( ), input_file_3d_full.ReturnZSize( ), true); // Making sure that the memory reserved for FFTs is also set to zero input_3d_full.SetToConstant(0.0f); input_3d_omit.SetToConstant(0.0f); -// mask_3d.SetToConstant(0.0f); + // mask_3d.SetToConstant(0.0f); input_3d_full.ReadSlices(&input_file_3d_full, 1, input_file_3d_full.ReturnZSize( )); input_3d_omit.ReadSlices(&input_file_3d_omit, 1, input_file_3d_omit.ReturnZSize( )); -// mask_radius = std::min(std::min(float(input_file_3d_full.ReturnXSize( )), float(input_file_3d_full.ReturnYSize( ))), float(input_file_3d_full.ReturnZSize( ))); + // mask_radius = std::min(std::min(float(input_file_3d_full.ReturnXSize( )), float(input_file_3d_full.ReturnYSize( ))), float(input_file_3d_full.ReturnZSize( ))); wxPrintf("\nStarting calculation...\n"); if ( input_diff_map == true ) { -// sigma_diff_template = sqrtf(input_diff.ReturnVarianceOfRealValues(mask_radius/2.0f, 0.0f, 0.0f, 0.0f, true)); + // sigma_diff_template = sqrtf(input_diff.ReturnVarianceOfRealValues(mask_radius/2.0f, 0.0f, 0.0f, 0.0f, true)); max_value = input_diff.ReturnAverageOfMaxN(100); for ( long address = 0; address < input_diff.real_memory_allocated; address++ ) { - if ( input_diff.real_values[address] > max_value / 10.0f) { - sum_3d_full += input_3d_full.real_values[address]; - sum_3d_omit += input_3d_omit.real_values[address]; - sum_difference += input_3d_full.real_values[address] - input_3d_omit.real_values[address]; -// mask_3d.real_values[address] = 1.0f; - count1++; + if ( input_diff.real_values[address] > max_value / 10.0f ) { + sum_3d_full += input_3d_full.real_values[address]; + sum_3d_omit += input_3d_omit.real_values[address]; + sum_difference += input_3d_full.real_values[address] - input_3d_omit.real_values[address]; + // mask_3d.real_values[address] = 1.0f; + count1++; } } - } else { -// sigma_full_template = sqrtf(input_full.ReturnVarianceOfRealValues( )); -// sigma_omit_template = sqrtf(input_omit.ReturnVarianceOfRealValues( )); -// max_value = 0.0f; + } + else { + // sigma_full_template = sqrtf(input_full.ReturnVarianceOfRealValues( )); + // sigma_omit_template = sqrtf(input_omit.ReturnVarianceOfRealValues( )); + // max_value = 0.0f; for ( long address = 0; address < input_full.real_memory_allocated; address++ ) { - input_full.real_values[address] -= input_omit.real_values[address]; -// max_value = std::max(max_value, input_full.real_values[address] - input_omit.real_values[address]); + input_full.real_values[address] -= input_omit.real_values[address]; + // max_value = std::max(max_value, input_full.real_values[address] - input_omit.real_values[address]); } max_value = input_full.ReturnAverageOfMaxN(100); -// wxPrintf("\nSigma full template = %g\n", sigma_full_template); -// wxPrintf("\nSigma omit template = %g\n", sigma_omit_template); -/* for ( long address = 0; address < input_full.real_memory_allocated; address++ ) { + // wxPrintf("\nSigma full template = %g\n", sigma_full_template); + // wxPrintf("\nSigma omit template = %g\n", sigma_omit_template); + /* for ( long address = 0; address < input_full.real_memory_allocated; address++ ) { if ( input_full.real_values[address] < sigma_full_template / 10.0f ) { input_3d_full.real_values[address] = 0.0f; input_3d_omit.real_values[address] = 0.0f; @@ -159,24 +162,24 @@ bool MeasureTemplateBiasApp::DoCalculation( ) { } */ for ( long address = 0; address < input_full.real_memory_allocated; address++ ) { - if ( input_full.real_values[address] > max_value / 10.0f) { -// if ( input_full.real_values[address] > sigma_full_template) { -// if ( input_omit.real_values[address] / input_full.real_values[address] < 0.5f ) { - sum_3d_full += input_3d_full.real_values[address]; - sum_3d_omit += input_3d_omit.real_values[address]; -// wxPrintf("\nAddress, value1, value 2 = %li, %g, %g\n", address, input_full.real_values[address], input_omit.real_values[address]); - sum_difference += input_3d_full.real_values[address] - input_3d_omit.real_values[address]; -// mask_3d.real_values[address] = 1.0f; - count1++; -// } else { -// input_3d_full.real_values[address] = 0.0f; -// input_3d_omit.real_values[address] = 0.0f; -// } + if ( input_full.real_values[address] > max_value / 10.0f ) { + // if ( input_full.real_values[address] > sigma_full_template) { + // if ( input_omit.real_values[address] / input_full.real_values[address] < 0.5f ) { + sum_3d_full += input_3d_full.real_values[address]; + sum_3d_omit += input_3d_omit.real_values[address]; + // wxPrintf("\nAddress, value1, value 2 = %li, %g, %g\n", address, input_full.real_values[address], input_omit.real_values[address]); + sum_difference += input_3d_full.real_values[address] - input_3d_omit.real_values[address]; + // mask_3d.real_values[address] = 1.0f; + count1++; + // } else { + // input_3d_full.real_values[address] = 0.0f; + // input_3d_omit.real_values[address] = 0.0f; + // } } } } -/* wxPrintf("\nWriting out map 1...\n"); + /* wxPrintf("\nWriting out map 1...\n"); input_3d_full.QuickAndDirtyWriteSlices("diff_full.mrc", 1, input_3d_full.logical_z_dimension); wxPrintf("\nWriting out map 2...\n"); input_3d_omit.QuickAndDirtyWriteSlices("diff_omit.mrc", 1, input_3d_omit.logical_z_dimension); @@ -185,12 +188,12 @@ bool MeasureTemplateBiasApp::DoCalculation( ) { wxPrintf("\nWriting out map 4...\n"); input_omit.QuickAndDirtyWriteSlices("omit.mrc", 1, input_omit.logical_z_dimension); */ -// wxPrintf("\nWriting out mask... Number of voxels set: %li\n", count1); -// mask_3d.QuickAndDirtyWriteSlices("mask.mrc", 1, mask_3d.logical_z_dimension); + // wxPrintf("\nWriting out mask... Number of voxels set: %li\n", count1); + // mask_3d.QuickAndDirtyWriteSlices("mask.mrc", 1, mask_3d.logical_z_dimension); - correlation_3ds = input_3d_full.ReturnCorrelationCoefficientUnnormalized(input_3d_omit, 0.0f)/sqrtf(input_3d_full.ReturnVarianceOfRealValues( ))/sqrtf(input_3d_omit.ReturnVarianceOfRealValues( )); + correlation_3ds = input_3d_full.ReturnCorrelationCoefficientUnnormalized(input_3d_omit, 0.0f) / sqrtf(input_3d_full.ReturnVarianceOfRealValues( )) / sqrtf(input_3d_omit.ReturnVarianceOfRealValues( )); if ( input_diff_map == false ) { - correlation_templates = input_full.ReturnCorrelationCoefficientUnnormalized(input_omit, 0.0f)/sqrtf(input_full.ReturnVarianceOfRealValues( ))/sqrtf(input_omit.ReturnVarianceOfRealValues( )); + correlation_templates = input_full.ReturnCorrelationCoefficientUnnormalized(input_omit, 0.0f) / sqrtf(input_full.ReturnVarianceOfRealValues( )) / sqrtf(input_omit.ReturnVarianceOfRealValues( )); } wxPrintf("\nAverage of densities of full reconstruction = %g\n", sum_3d_full / count1); @@ -198,8 +201,8 @@ bool MeasureTemplateBiasApp::DoCalculation( ) { wxPrintf("\nAverage of difference densities = %g\n", sum_difference / count1); wxPrintf("\nCorrelation coefficient of reconstructions = %g\n", correlation_3ds); if ( input_diff_map == false ) { - wxPrintf("\nCorrelation coefficient of templates = %g\n", correlation_templates); - wxPrintf("\nRatio of correlation coefficients = %g\n", correlation_3ds/correlation_templates); + wxPrintf("\nCorrelation coefficient of templates = %g\n", correlation_templates); + wxPrintf("\nRatio of correlation coefficients = %g\n", correlation_3ds / correlation_templates); } wxPrintf("\n\nDegree of bias = %g\n\n", ((sum_3d_full - sum_3d_omit) / sum_3d_full)); diff --git a/src/programs/sum_all_eer_files/sum_all_eer_files.cpp b/src/programs/sum_all_eer_files/sum_all_eer_files.cpp index ae8e94edc..72d0ff66c 100644 --- a/src/programs/sum_all_eer_files/sum_all_eer_files.cpp +++ b/src/programs/sum_all_eer_files/sum_all_eer_files.cpp @@ -20,8 +20,8 @@ void SumAllEer::DoInteractiveUserInput( ) { int max_threads; std::string output_dark_filename; std::string output_gain_filename; - int eer_super_res_factor; - int eer_frames_per_image; + int eer_super_res_factor; + int eer_frames_per_image; UserInput* my_input = new UserInput("SumAllEerfiles", 1.0); @@ -34,20 +34,20 @@ void SumAllEer::DoInteractiveUserInput( ) { output_gain_filename = my_input->GetFilenameFromUser("Output gain file name", "Filename of output gain image", "gain_image.mrc", false); } - max_threads = my_input->GetIntFromUser("Max number of threads to use", "maximum number of threads to use for processing.", "1", 1); - eer_super_res_factor = my_input-> GetIntFromUser("EER super resolution factor", "super resolution factor for pixels.", "1", 1); + max_threads = my_input->GetIntFromUser("Max number of threads to use", "maximum number of threads to use for processing.", "1", 1); + eer_super_res_factor = my_input->GetIntFromUser("EER super resolution factor", "super resolution factor for pixels.", "1", 1); eer_frames_per_image = my_input->GetIntFromUser("EER frames per image", "frames per image in eer file type", "0", 0); delete my_input; my_current_job.Reset(7); my_current_job.ManualSetArguments("tbttiii", output_filename.c_str( ), - make_dark_and_gain, - output_dark_filename.c_str( ), - output_gain_filename.c_str( ), - max_threads, - eer_super_res_factor, - eer_frames_per_image); + make_dark_and_gain, + output_dark_filename.c_str( ), + output_gain_filename.c_str( ), + max_threads, + eer_super_res_factor, + eer_frames_per_image); } // override the do calculation method which will be what is actually run.. @@ -67,8 +67,8 @@ bool SumAllEer::DoCalculation( ) { std::string output_dark_filename = my_current_job.arguments[2].ReturnStringArgument( ); std::string output_gain_filename = my_current_job.arguments[3].ReturnStringArgument( ); int max_threads = my_current_job.arguments[4].ReturnIntegerArgument( ); - int eer_super_res_factor = my_current_job.arguments[5].ReturnIntegerArgument( ); - int eer_frames_per_image = my_current_job.arguments[6].ReturnIntegerArgument( ); + int eer_super_res_factor = my_current_job.arguments[5].ReturnIntegerArgument( ); + int eer_frames_per_image = my_current_job.arguments[6].ReturnIntegerArgument( ); wxArrayString all_files; wxDir::GetAllFiles(".", &all_files, "*.eer", wxDIR_FILES); @@ -92,7 +92,7 @@ bool SumAllEer::DoCalculation( ) { wxPrintf("\nThere are %li eer files in this directory.\n", all_files.GetCount( )); - current_input_file = new EerFile(); + current_input_file = new EerFile( ); current_input_file->OpenFile(all_files.Item(0).ToStdString( ), false, false, false, eer_super_res_factor, eer_frames_per_image); file_x_size = current_input_file->ReturnXSize( ); @@ -141,9 +141,9 @@ bool SumAllEer::DoCalculation( ) { #pragma omp for for ( file_counter = 0; file_counter < all_files.GetCount( ); file_counter++ ) { //wxPrintf("Summing file %s...\n", all_files.Item(file_counter)); - //wxPrintf("Summing File %ld\n", file_counter); - current_input_file = new EerFile(); - current_input_file->OpenFile(all_files.Item(file_counter).ToStdString( ), false, false, false, eer_super_res_factor, eer_frames_per_image); + //wxPrintf("Summing File %ld\n", file_counter); + current_input_file = new EerFile( ); + current_input_file->OpenFile(all_files.Item(file_counter).ToStdString( ), false, false, false, eer_super_res_factor, eer_frames_per_image); for ( frame_counter = 0; frame_counter < current_input_file->ReturnNumberOfSlices( ); frame_counter++ ) { buffer_image.ReadSlice(current_input_file, frame_counter + 1); From 599a6315ff2b8bc9611ed8d75443af4d967bcc16 Mon Sep 17 00:00:00 2001 From: twagner9 Date: Mon, 27 Apr 2026 18:05:03 -0400 Subject: [PATCH 11/12] Adds ability to add scale bar to items in display when in single image mode. --- src/gui/DisplayFrame.cpp | 113 +++++++++++++++++++- src/gui/DisplayFrame.h | 2 + src/gui/DisplayPanel.cpp | 58 ++++++++++ src/gui/DisplayPanel.h | 1 + src/gui/wxformbuilder/cisTEM_display.fbp | 16 ++- src/programs/cisTEM_display/display_gui.cpp | 4 + src/programs/cisTEM_display/display_gui.h | 3 + 7 files changed, 192 insertions(+), 5 deletions(-) diff --git a/src/gui/DisplayFrame.cpp b/src/gui/DisplayFrame.cpp index fa29057af..ec8ad1f16 100644 --- a/src/gui/DisplayFrame.cpp +++ b/src/gui/DisplayFrame.cpp @@ -83,7 +83,7 @@ void DisplayFrame::OnSaveDisplayedImagesClick(wxCommandEvent& event) { // Crop out the blank space around the image: get the true width of the relevant area on the bitmap. wxBitmap sub_bitmap = CropImageForSaving( ); - + DrawScaleBarOnBitmap(sub_bitmap); sub_bitmap.SaveFile(save_file_dialog.GetPath( ), wxBITMAP_TYPE_PNG); } @@ -107,9 +107,10 @@ void DisplayFrame::OnSaveDisplayedImagesWithLegendClick(wxCommandEvent& event) { } // Crop out the blank space around the image: get the true width of the relevant area on the bitmap. - wxBitmap sub_bitmap = CropImageForSaving( ); - int sub_bmp_width = sub_bitmap.GetWidth( ); - int sub_bmp_height = sub_bitmap.GetHeight( ); + wxBitmap sub_bitmap = CropImageForSaving( ); + DrawScaleBarOnBitmap(sub_bitmap); + int sub_bmp_width = sub_bitmap.GetWidth( ); + int sub_bmp_height = sub_bitmap.GetHeight( ); // Create legend, width of 80 pixels int legend_width = 80; @@ -242,6 +243,43 @@ void DisplayFrame::OnLocationNumberClick(wxCommandEvent& event) { cisTEMDisplayPanel->ReturnCurrentPanel( )->ReDrawPanel( ); } +void DisplayFrame::OnLabelScaleBarClick(wxCommandEvent& event) { + if ( ! cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image ) + return; + + // Turning the scale bar off needs no pixel size check + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->draw_scale_bar ) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->draw_scale_bar = false; + cisTEMDisplayPanel->ReturnCurrentPanel( )->ReDrawPanel( ); + return; + } + + // Turning it on: we need a real pixel size. If none has been set yet, + // prompt the user exactly as OnShowResolution does. + if ( ! cisTEMDisplayPanel->ReturnCurrentPanel( )->resolution_instead_of_radius ) { + double wanted_pixel_size; + wxTextEntryDialog text_dialog(this, wxT("Pixel Size (Angstroms)"), wxT("Select Pixel Size"), + wxString::Format(wxT("%.2f"), cisTEMDisplayPanel->ReturnCurrentPanel( )->pixel_size), + wxOK | wxCANCEL | wxCENTRE, wxDefaultPosition); + if ( text_dialog.ShowModal( ) != wxID_OK ) { + // User cancelled — uncheck the menu item and bail + LabelScaleBar->Check(false); + return; + } + wxString current_value = text_dialog.GetValue( ); + if ( current_value.ToDouble(&wanted_pixel_size) && wanted_pixel_size > 0.0 ) { + cisTEMDisplayPanel->ReturnCurrentPanel( )->pixel_size = wanted_pixel_size; + } + else { + LabelScaleBar->Check(false); + return; + } + } + + cisTEMDisplayPanel->ReturnCurrentPanel( )->draw_scale_bar = true; + cisTEMDisplayPanel->ReturnCurrentPanel( )->ReDrawPanel( ); +} + void DisplayFrame::OnImageSelectionModeClick(wxCommandEvent& event) { // if we are already in selections mode, we don't want to do anything, so // make a check. @@ -689,6 +727,7 @@ void DisplayFrame::DisableAllToolbarButtons( ) { // Label menu LabelLocationNumber->Enable(false); + LabelScaleBar->Enable(false); // Select menu SelectImageSelectionMode->Enable(false); @@ -714,6 +753,7 @@ void DisplayFrame::EnableAllToolbarButtons( ) { // Label menu LabelLocationNumber->Enable( ); + LabelScaleBar->Enable( ); // Select menu SelectImageSelectionMode->Enable(true); @@ -768,6 +808,16 @@ void DisplayFrame::OnUpdateUI(wxUpdateUIEvent& event) { else if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->selected_point_size == 10 ) CoordSize10->Check(true); + LabelScaleBar->Enable(cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image); + if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->draw_scale_bar ) { + if ( ! LabelScaleBar->IsChecked( ) ) + LabelScaleBar->Check(true); + } + else { + if ( LabelScaleBar->IsChecked( ) ) + LabelScaleBar->Check(false); + } + // Make sure single image mode is checked/unchecked based on current panel if ( cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image ) { if ( ! OptionsSingleImageMode->IsChecked( ) ) @@ -922,4 +972,59 @@ wxBitmap DisplayFrame::CropImageForSaving( ) { sub_bitmap = cisTEMDisplayPanel->ReturnCurrentPanel( )->panel_bitmap.GetSubBitmap(sub_bmp_dims); } return sub_bitmap; +} + +void DisplayFrame::DrawScaleBarOnBitmap(wxBitmap& target_bitmap) { + if ( ! cisTEMDisplayPanel->ReturnCurrentPanel( )->draw_scale_bar || + ! cisTEMDisplayPanel->ReturnCurrentPanel( )->single_image ) + return; + + const int bmp_width = target_bitmap.GetWidth( ); + const int bmp_height = target_bitmap.GetHeight( ); + const float actual_scale_factor = cisTEMDisplayPanel->ReturnCurrentPanel( )->actual_scale_factor; + const float pixel_size = cisTEMDisplayPanel->ReturnCurrentPanel( )->pixel_size; + const float image_in_bitmap_pixel_size = pixel_size / actual_scale_factor; + + int scalebar_length; + { + const float bar_must_be_multiple_of = 5.0f; + float ideal_length_in_pixels = float(bmp_width) * 0.1f; + float ideal_length_in_nm = ideal_length_in_pixels * image_in_bitmap_pixel_size * 0.1f; + ideal_length_in_nm = roundf(ideal_length_in_nm / bar_must_be_multiple_of) * bar_must_be_multiple_of; + if ( ideal_length_in_nm < bar_must_be_multiple_of ) + ideal_length_in_nm = bar_must_be_multiple_of; + ideal_length_in_pixels = ideal_length_in_nm * 10.0f / image_in_bitmap_pixel_size; + scalebar_length = myroundint(ideal_length_in_pixels); + } + + int scalebar_thickness = int(float(bmp_height) / 50.0f); + if ( scalebar_thickness < 2 ) + scalebar_thickness = 2; + + int scalebar_x_start = int(float(bmp_width) * 0.85f) - scalebar_length / 2; + int scalebar_y_pos = int(float(bmp_height) * 0.95f) - scalebar_thickness; + + if ( scalebar_x_start < 0 ) + scalebar_x_start = 0; + if ( scalebar_x_start + scalebar_length > bmp_width ) + scalebar_x_start = bmp_width - scalebar_length; + + wxMemoryDC dc(target_bitmap); + dc.SetPen(wxPen(*wxWHITE)); + dc.SetBrush(*wxWHITE_BRUSH); + dc.DrawRectangle(scalebar_x_start, scalebar_y_pos, scalebar_length, scalebar_thickness); + + dc.SetTextForeground(*wxWHITE); + int label_font_size = std::max(9, int(float(scalebar_thickness) * 0.75f)); + dc.SetFont(wxFont(label_font_size, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD)); + + wxString scalebar_label = wxString::Format("%.0f nm", float(scalebar_length) * image_in_bitmap_pixel_size * 0.1f); + int scalebar_label_width; + int scalebar_label_height; + dc.GetTextExtent(scalebar_label, &scalebar_label_width, &scalebar_label_height); + dc.DrawText(scalebar_label, + scalebar_x_start + scalebar_length / 2 - scalebar_label_width / 2, + scalebar_y_pos - scalebar_label_height - scalebar_thickness / 8); + + dc.SelectObject(wxNullBitmap); } \ No newline at end of file diff --git a/src/gui/DisplayFrame.h b/src/gui/DisplayFrame.h index c2e7ddbde..d8070496d 100644 --- a/src/gui/DisplayFrame.h +++ b/src/gui/DisplayFrame.h @@ -28,6 +28,7 @@ class DisplayFrame : public DisplayFrameParent { // Label menu void OnLocationNumberClick(wxCommandEvent& event); + void OnLabelScaleBarClick(wxCommandEvent& event); // Select menu void OnImageSelectionModeClick(wxCommandEvent& event); @@ -58,6 +59,7 @@ class DisplayFrame : public DisplayFrameParent { bool LoadImageSelections(wxString current_line); void ClearTextFileFromPanel( ); wxBitmap CropImageForSaving( ); + void DrawScaleBarOnBitmap(wxBitmap& target_bitmap); }; #endif \ No newline at end of file diff --git a/src/gui/DisplayPanel.cpp b/src/gui/DisplayPanel.cpp index 6cd26046e..1a2862ba2 100644 --- a/src/gui/DisplayPanel.cpp +++ b/src/gui/DisplayPanel.cpp @@ -1433,6 +1433,7 @@ DisplayNotebookPanel::DisplayNotebookPanel(wxWindow* parent, wxWindowID id, cons use_7bit_greys = false; show_selection_distances = false; resolution_instead_of_radius = false; + draw_scale_bar = false; blue_selection_square_location = -1; @@ -2908,6 +2909,63 @@ void DisplayNotebookPanel::OnPaint(wxPaintEvent& evt) { } } } + + // Scale bar overlay (single-image mode only) + if ( draw_scale_bar && single_image ) { + // Compute the actual screen-pixel extent of the drawn image, + // which may be smaller than the window if the image is small. + int image_screen_width = panel_image->GetWidth( ) - int(single_image_x * actual_scale_factor); + int image_screen_height = panel_image->GetHeight( ) - int(single_image_y * actual_scale_factor); + if ( image_screen_width > window_x_size ) + image_screen_width = window_x_size; + if ( image_screen_height > window_y_size ) + image_screen_height = window_y_size; + + // Å per screen pixel, then *0.1 converts Å→nm in the formula + const float image_in_bitmap_pixel_size = pixel_size / actual_scale_factor; + + int scalebar_length; + { + const float bar_must_be_multiple_of = 5.0f; // nm + float ideal_length_in_pixels = float(image_screen_width) * 0.1f; + float ideal_length_in_nm = ideal_length_in_pixels * image_in_bitmap_pixel_size * 0.1f; + ideal_length_in_nm = roundf(ideal_length_in_nm / bar_must_be_multiple_of) * bar_must_be_multiple_of; + if ( ideal_length_in_nm < bar_must_be_multiple_of ) + ideal_length_in_nm = bar_must_be_multiple_of; + ideal_length_in_pixels = ideal_length_in_nm * 10.0f / image_in_bitmap_pixel_size; + scalebar_length = myroundint(ideal_length_in_pixels); + } + + int scalebar_thickness = int(float(image_screen_height) / 50.0f); + if ( scalebar_thickness < 2 ) + scalebar_thickness = 2; + + int scalebar_x_start = int(float(image_screen_width) * 0.85f) - scalebar_length / 2; + int scalebar_y_pos = int(float(image_screen_height) * 0.95f) - scalebar_thickness; + + // Clamp so the bar never spills outside the image area + if ( scalebar_x_start < 0 ) + scalebar_x_start = 0; + if ( scalebar_x_start + scalebar_length > image_screen_width ) + scalebar_x_start = image_screen_width - scalebar_length; + + wxPen scalebar_pen(*wxWHITE); + dc.SetPen(scalebar_pen); + dc.SetBrush(*wxWHITE_BRUSH); + dc.DrawRectangle(scalebar_x_start, scalebar_y_pos, scalebar_length, scalebar_thickness); + + dc.SetTextForeground(*wxWHITE); + int label_font_size = std::max(9, int(float(scalebar_thickness) * 0.75f)); + dc.SetFont(wxFont(label_font_size, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD)); + + wxString scalebar_label = wxString::Format("%.0f nm", float(scalebar_length) * image_in_bitmap_pixel_size * 0.1f); + int scalebar_label_width; + int scalebar_label_height; + dc.GetTextExtent(scalebar_label, &scalebar_label_width, &scalebar_label_height); + dc.DrawText(scalebar_label, + scalebar_x_start + scalebar_length / 2 - scalebar_label_width / 2, + scalebar_y_pos - scalebar_label_height - scalebar_thickness / 8); + } } } diff --git a/src/gui/DisplayPanel.h b/src/gui/DisplayPanel.h index 59eebd981..6dd0aedef 100644 --- a/src/gui/DisplayPanel.h +++ b/src/gui/DisplayPanel.h @@ -369,6 +369,7 @@ class bool show_label; bool show_crosshair; bool single_image; + bool draw_scale_bar; bool txt_is_saved; bool have_txt_filename; diff --git a/src/gui/wxformbuilder/cisTEM_display.fbp b/src/gui/wxformbuilder/cisTEM_display.fbp index d9d1cc2fc..cebb99be2 100644 --- a/src/gui/wxformbuilder/cisTEM_display.fbp +++ b/src/gui/wxformbuilder/cisTEM_display.fbp @@ -301,7 +301,7 @@ OnExitClick - + Label DisplayLabelMenu protected @@ -319,6 +319,20 @@ OnLocationNumberClick + + + 0 + 1 + + wxID_ANY + wxITEM_CHECK + Show Scale Bar + LabelScaleBar + protected + + + OnLabelScaleBarClick + Select diff --git a/src/programs/cisTEM_display/display_gui.cpp b/src/programs/cisTEM_display/display_gui.cpp index ab24ad8e1..e9e2acf5a 100644 --- a/src/programs/cisTEM_display/display_gui.cpp +++ b/src/programs/cisTEM_display/display_gui.cpp @@ -80,6 +80,9 @@ DisplayFrameParent::DisplayFrameParent(wxWindow* parent, wxWindowID id, const wx LabelLocationNumber->Enable(false); LabelLocationNumber->Check(true); + LabelScaleBar = new wxMenuItem(DisplayLabelMenu, wxID_ANY, wxString(wxT("Show Scale Bar")), wxEmptyString, wxITEM_CHECK); + DisplayLabelMenu->Append(LabelScaleBar); + m_menubar2->Append(DisplayLabelMenu, wxT("Label")); DisplaySelectMenu = new wxMenu( ); @@ -169,6 +172,7 @@ DisplayFrameParent::DisplayFrameParent(wxWindow* parent, wxWindowID id, const wx DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnSaveTxtAsClick), this, SelectSaveTxtAs->GetId( )); DisplayFileMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnExitClick), this, DisplayExit->GetId( )); DisplayLabelMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnLocationNumberClick), this, LabelLocationNumber->GetId( )); + DisplayLabelMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnLabelScaleBarClick), this, LabelScaleBar->GetId( )); DisplaySelectMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnImageSelectionModeClick), this, SelectImageSelectionMode->GetId( )); DisplaySelectMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnCoordsSelectionModeClick), this, SelectCoordsSelectionMode->GetId( )); DisplaySelectMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DisplayFrameParent::OnInvertSelectionClick), this, SelectInvertSelection->GetId( )); diff --git a/src/programs/cisTEM_display/display_gui.h b/src/programs/cisTEM_display/display_gui.h index 9712eba61..183c84bc6 100644 --- a/src/programs/cisTEM_display/display_gui.h +++ b/src/programs/cisTEM_display/display_gui.h @@ -71,6 +71,7 @@ class DisplayFrameParent : public wxFrame { wxMenuItem* DisplayExit; wxMenu* DisplayLabelMenu; wxMenuItem* LabelLocationNumber; + wxMenuItem* LabelScaleBar; wxMenu* DisplaySelectMenu; wxMenuItem* SelectImageSelectionMode; wxMenuItem* SelectCoordsSelectionMode; @@ -110,6 +111,8 @@ class DisplayFrameParent : public wxFrame { virtual void OnLocationNumberClick(wxCommandEvent& event) { event.Skip( ); } + virtual void OnLabelScaleBarClick(wxCommandEvent& event) { event.Skip( ); } + virtual void OnImageSelectionModeClick(wxCommandEvent& event) { event.Skip( ); } virtual void OnCoordsSelectionModeClick(wxCommandEvent& event) { event.Skip( ); } From caa6a2abd102fe6f1d556262aa22c3e75cac7066 Mon Sep 17 00:00:00 2001 From: twagner9 Date: Tue, 12 May 2026 11:43:44 -0400 Subject: [PATCH 12/12] Added info to display controls manual for saving with scale bar. --- src/gui/DisplayFrame.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/gui/DisplayFrame.cpp b/src/gui/DisplayFrame.cpp index ec8ad1f16..53dce186c 100644 --- a/src/gui/DisplayFrame.cpp +++ b/src/gui/DisplayFrame.cpp @@ -697,7 +697,14 @@ void DisplayFrame::OnDisplayControlsClick(wxCommandEvent& event) { text_ctrl->BeginBold( ); text_ctrl->WriteText("3. Middle Mouse Button"); text_ctrl->EndBold( ); - text_ctrl->WriteText(": When in Single Image Mode (selected from the Options menu), dragging the mouse will shift the displayed window in the direction of the drag."); + text_ctrl->WriteText(": When in Single Image Mode (selected from the Options menu), dragging the mouse will shift the displayed window in the direction of the drag.\n\n"); + + text_ctrl->BeginBold( ); + text_ctrl->BeginFontSize(12); + text_ctrl->WriteText("\nSaving with Scale Bar\n\n\n"); + text_ctrl->EndFontSize( ); + text_ctrl->EndBold( ); + text_ctrl->WriteText("To save a displayed image or slice with a scale bar, first make sure the display is in Single Image Mode to enable the scale bar option.\n\nThen, select the Label Menu and select the scale bar option. A prompt will appear requesting the pixel size of the image or volume, and upon entering the scale bar will be drawn on the image, adjusting for different scaling levels.\n\nWhen saving as a PNG, the scale bar will be present on the image.\n"); wxStdDialogButtonSizer* button_sizer = new wxStdDialogButtonSizer( ); wxButton* ok_button = new wxButton(manual_dialog, wxID_OK);