diff --git a/src/epicure/epiwidgets.py b/src/epicure/epiwidgets.py index fa5268368867fc3c0c81ddd41118389e8c25cce0..c37447afb8bb6a1425425f001b38ddd07a10e5a3 100644 --- a/src/epicure/epiwidgets.py +++ b/src/epicure/epiwidgets.py @@ -287,7 +287,7 @@ def listbox( func=None ): value.currentIndexChanged.connect( func ) return value -def slider_line( name, minval, maxval, step, value, slidefunc=None, descr="" ): +def slider_line( name, minval, maxval, step, value, show_value=False, slidefunc=None, descr="" ): """ Line with a text and a slider """ line = QHBoxLayout() ## add name if any @@ -305,27 +305,9 @@ def slider_line( name, minval, maxval, step, value, slidefunc=None, descr="" ): slider.valueChanged.connect( slidefunc ) if descr != "": slider.setToolTip( descr ) - line.addWidget( slider ) - return line, slider - - -def slider_line( name, minval, maxval, step, value, slidefunc=None, descr="" ): - """ Line with a text and a slider """ - line = QHBoxLayout() - ## add name if any - if name is not None: - lab = QLabel() - lab.setText( name ) + if show_value: + lab = QLabel(""+str(value)) line.addWidget( lab ) - ## add slider - slider = QSlider( Qt.Horizontal ) - slider.setMinimum( minval ) - slider.setMaximum( maxval ) - slider.setSingleStep( step ) - slider.setValue( value ) - if slidefunc is not None: - slider.valueChanged.connect( slidefunc ) - if descr != "": - slider.setToolTip( descr ) + slider.valueChanged.connect( lambda: lab.setText( ""+str(slider.value()) ) ) line.addWidget( slider ) return line, slider diff --git a/src/epicure/inspecting.py b/src/epicure/inspecting.py index 6f1491157d251e849c106fdc0a97a0beb7ae55e3..6dd59db74d3298fc0566f8d6741298c8827a36a5 100644 --- a/src/epicure/inspecting.py +++ b/src/epicure/inspecting.py @@ -258,7 +258,7 @@ class Inspecting(QWidget): if esize > 70: msize = 200 esize = min( esize, 100 ) - sizelay, self.event_size = wid.slider_line( "Point size:", minval=0, maxval=msize, step=1, value=esize, slidefunc=self.display_event_size, descr="Choose the current point size display" ) + sizelay, self.event_size = wid.slider_line( "Point size:", minval=0, maxval=msize, step=1, value=esize, show_value=True, slidefunc=self.display_event_size, descr="Choose the current point size display" ) disp_layout.addLayout(sizelay) ### Interface to select a event and zoom on it diff --git a/src/epicure/outputing.py b/src/epicure/outputing.py index c4c11cd41db07eba2d7ee3f9e3b81a3792f29bf4..07d1bcc0fdf0ab7e048a41e74db7bddf17d65cd9 100644 --- a/src/epicure/outputing.py +++ b/src/epicure/outputing.py @@ -28,7 +28,7 @@ class Outputing(QWidget): self.seglayer = self.viewer.layers["Segmentation"] self.movlayer = self.viewer.layers["Movie"] self.selection_choices = ["All cells", "Only selected cell"] - self.output_options = ["", "Export to extern plugins", "Export segmentations", "Measure cell features", "Measure track features", "Export/Measure events"] + self.output_options = ["", "Export to extern plugins", "Export segmentations", "Measure cell features", "Measure track features", "Export/Measure events", "Save screenshot movie"] self.tplots = None chanlist = ["Movie"] @@ -135,6 +135,79 @@ class Outputing(QWidget): self.handle_event_group.hide() all_layout.addWidget( self.handle_event_group ) + ## Save screenshots option + current_frame = ut.current_frame( self.epicure.viewer ) + self.screenshot_group, screenshot_layout = wid.group_layout( "Save screenshot movie" ) + self.show_scalebar = wid.add_check_tolayout( screenshot_layout, "With the scale bar", True, check_func=None, descr="Show the scale bar in the screenshots" ) + sframe_line, self.sframe = wid.slider_line( "From frame", 0, self.epicure.nframes, 1, value=current_frame, show_value=True, slidefunc=None, descr="Frame from which to start saving screenshots" ) + eframe_line, self.eframe = wid.slider_line( "To frame", 0, self.epicure.nframes, 1, value=current_frame+1, show_value=True, slidefunc=None, descr="Frame until which to save screenshots" ) + screenshot_layout.addLayout( sframe_line ) + screenshot_layout.addLayout( eframe_line ) + savescreen_btn = wid.add_button( "Save current view", self.screenshot_movie, "Save the current view (with current display parameters) for frame between the two specified frames in a movie" ) + + screenshot_layout.addWidget(savescreen_btn) + self.screenshot_group.setLayout(screenshot_layout) + all_layout.addWidget(self.screenshot_group) + self.screenshot_group.hide() + + ## Option to export segmentation results + self.export_seg_group, layout = wid.group_layout(self.output_options[2]) + save_line, self.save_choice = wid.button_list( "Save segmentation as", self.save_segmentation, "Save the current segmentation either as ROI, label image or skeleton" ) + self.save_choice.addItem( "labels" ) + self.save_choice.addItem( "ROI" ) + self.save_choice.addItem( "skeleton" ) + layout.addLayout( save_line ) + + self.export_seg_group.setLayout(layout) + all_layout.addWidget(self.export_seg_group) + + #### Features group + self.feature_group, featlayout = wid.group_layout(self.output_options[3]) + + self.choose_features_btn = wid.add_button( "Choose features...", self.choose_features, "Open a window to select the features to measure" ) + featlayout.addWidget(self.choose_features_btn) + + self.feature_table = wid.add_button( "Create features table", self.show_table, "Measure the selected features and display it as a clickable table" ) + featlayout.addWidget(self.feature_table) + self.featTable = FeaturesTable(self.viewer, self.epicure) + featlayout.addWidget(self.featTable) + + ######## Temporal option + self.temp_graph = wid.add_button( "Table to temporal graphs...", self.temporal_graphs, "Open a plot interface of measured features temporal evolution" ) + featlayout.addWidget(self.temp_graph) + self.temp_graph.setEnabled(False) + + ######## Drawing option + featmap, self.show_feature_map = wid.list_line( "Draw feature map:", descr="Add a layer with the cells colored by the selected feature value", func=self.show_feature ) + featlayout.addLayout(featmap) + orienbtn = wid.add_button( "Draw cell orientation", self.draw_orientation, "Add a layer with each cell main axis orientation and length " ) + featlayout.addWidget( orienbtn ) + + self.save_table = wid.add_button( "Save features table", self.save_measure_features, "Save the current table in a .csv file" ) + featlayout.addWidget(self.save_table) + + ## skrub table + self.stat_table = wid.add_button( "Open statistiques table...", self.skrub_features, "Open interactive table with the features statistiques (skrub library)" ) + featlayout.addWidget(self.stat_table) + + self.feature_group.setLayout(featlayout) + self.feature_group.hide() + all_layout.addWidget(self.feature_group) + + ## Track features + self.trackfeat_group, trackfeatlayout = wid.group_layout(self.output_options[4]) + self.trackfeat_table = wid.add_button( "Track features table", self.show_trackfeature_table, "Measure track-related feature and show a table by track" ) + trackfeatlayout.addWidget(self.trackfeat_table) + self.trackTable = FeaturesTable(self.viewer, self.epicure) + trackfeatlayout.addWidget(self.trackTable) + self.save_table_track = wid.add_button( "Save track table", self.save_table_tracks, "Save the current table in a .csv file" ) + trackfeatlayout.addWidget(self.save_table_track) + + self.trackfeat_group.setLayout(trackfeatlayout) + self.trackfeat_group.hide() + all_layout.addWidget(self.trackfeat_group) + + ## Finished self.setLayout(all_layout) self.show_output_option() @@ -144,6 +217,7 @@ class Outputing(QWidget): disp = {} disp["Apply on"] = self.output_mode.currentText() disp["Current option"] = self.choose_output.currentText() + disp["Show scalebar"] = self.show_scalebar.isChecked() disp = self.cell_features.get_current_settings( disp ) disp = self.event_classes.get_current_settings( disp ) return disp @@ -155,10 +229,33 @@ class Outputing(QWidget): self.output_mode.setCurrentText( val ) if setting == "Current option": self.choose_output.setCurrentText( val ) + if setting == "Show scalebar": + self.show_scalebar.setChecked( val ) self.cell_features.apply_settings( settings ) self.event_classes.apply_settings( settings ) + def screenshot_movie( self ): + """ Save screenshots of the current view """ + scale_visibility = self.viewer.scale_bar.visible + current_frame = ut.current_frame( self.epicure.viewer ) + self.viewer.scale_bar.visible = self.show_scalebar.isChecked() + start_frame = max( self.sframe.value(), 0 ) + end_frame = min( self.eframe.value(), self.epicure.nframes ) + outname = os.path.join( self.epicure.outdir, self.epicure.imgname+"_screenshots_f"+str(start_frame)+"-"+str(end_frame)+".tif" ) + if os.path.exists(outname): + os.remove(outname) + if start_frame > end_frame: + ut.show_warning("From frame > to frame, no screenshot saved") + return + for frame in range(start_frame, end_frame+1): + self.viewer.dims.set_point(0, frame) + shot = self.viewer.screenshot( canvas_only=True, flash=False ) + ut.appendToTif( shot, outname ) + self.viewer.scale_bar.visible = scale_visibility + self.viewer.dims.set_point(0, current_frame) + ut.show_info( "Screenshot movie saved in "+outname ) + def events_select( self, event, check ): """ Check/Uncheck the event in event types list """ if event in self.event_classes.evt_classes: @@ -174,6 +271,7 @@ class Outputing(QWidget): self.feature_group.setVisible( cur_option == "Measure cell features" ) self.trackfeat_group.setVisible( cur_option == "Measure track features" ) self.handle_event_group.setVisible( cur_option == "Export/Measure events" ) + self.screenshot_group.setVisible( cur_option == "Save screenshot movie" ) def get_current_labels( self ): """ Get the cell labels to process according to current selection of apply on"""