@@ -314,3 +314,147 @@ def test_changing_lut_identifier_in_analysis_view_plots(qtbot):
314314 qtbot .mouseClick (pv .pushButton_apply , QtCore .Qt .MouseButton .LeftButton )
315315
316316 assert pv .comboBox_lut .currentData () == "HE-3D-FEM-22"
317+
318+
319+ def test_zoomin_contours (qtbot ):
320+ """Test that zooming in on contours works correctly"""
321+ mw = DCscope ()
322+ qtbot .addWidget (mw )
323+
324+ # Add test dataset and create plot
325+ slot_id = mw .add_dataslot (paths = [datapath / "calibration_beads_47.rtdc" ])
326+ plot_id = mw .add_plot ()
327+
328+ # Activate slot-plot pair
329+ pe = mw .block_matrix .get_widget (filt_plot_id = plot_id , slot_id = slot_id [0 ])
330+ qtbot .mouseClick (pe , QtCore .Qt .MouseButton .LeftButton )
331+
332+ # Get range before zoom-in
333+ mw .add_plot_window (plot_id )
334+ plot_widget = mw .subwindows_plots [plot_id ].widget ()
335+ view_range_before = plot_widget .plot_items [- 1 ].getViewBox ().viewRange ()
336+ x_range_before = view_range_before [0 ]
337+ y_range_before = view_range_before [1 ]
338+
339+ # Switch to plot tab
340+ mw .widget_ana_view .tabWidget .setCurrentWidget (mw .widget_ana_view .tab_plot )
341+ pv = mw .widget_ana_view .widget_plot
342+
343+ # Enable contour zoom-in and apply
344+ pv .checkBox_zoomin .setChecked (True )
345+ qtbot .mouseClick (pv .pushButton_apply , QtCore .Qt .MouseButton .LeftButton )
346+
347+ # Get range after zoom-in
348+ plot_widget = mw .subwindows_plots [plot_id ].widget ()
349+ view_range_after = plot_widget .plot_items [- 1 ].getViewBox ().viewRange ()
350+ x_range_after = view_range_after [0 ]
351+ y_range_after = view_range_after [1 ]
352+
353+ # Verify zoom-in reduced both X and Y ranges
354+ assert x_range_after [1 ] < x_range_before [1 ], "x-max should decrease"
355+ assert y_range_after [1 ] < y_range_before [1 ], "y-max should decrease"
356+
357+
358+ def test_only_contours_division (qtbot ):
359+ """Test that 'onlycontours' division mode works correctly"""
360+ mw = DCscope ()
361+ qtbot .addWidget (mw )
362+
363+ # Add multiple datasets
364+ path = datapath / "calibration_beads_47.rtdc"
365+ mw .add_dataslot (paths = [path , path ]) # Add same dataset twice for testing
366+
367+ # Add a plot
368+ plot_id = mw .add_plot ()
369+
370+ # Activate analysis view
371+ pe = mw .block_matrix .get_widget (filt_plot_id = plot_id )
372+ qtbot .mouseClick (pe .toolButton_modify , QtCore .Qt .MouseButton .LeftButton )
373+
374+ # Switch to plot tab
375+ mw .widget_ana_view .tabWidget .setCurrentWidget (mw .widget_ana_view .tab_plot )
376+ pv = mw .widget_ana_view .widget_plot
377+
378+ # Get the initial plot state
379+ plot_state = mw .pipeline .get_plot (plot_id ).__getstate__ ()
380+
381+ # Verify there is only one plot
382+ assert len (mw .pipeline .plot_ids ) == 1 , "Should have exactly one plot"
383+
384+ # Verify initial division mode
385+ assert plot_state ["layout" ]["division" ] == "multiscatter+contour"
386+
387+ # Set division to "onlycontours"
388+ idx = pv .comboBox_division .findData ("onlycontours" )
389+ pv .comboBox_division .setCurrentIndex (idx )
390+
391+ # Apply changes
392+ qtbot .mouseClick (pv .pushButton_apply , QtCore .Qt .MouseButton .LeftButton )
393+
394+ # Get the plot widget
395+ pw = mw .block_matrix .get_widget (filt_plot_id = plot_id )
396+
397+ # Activate plots for contour view
398+ qtbot .mouseClick (pw .toolButton_toggle , QtCore .Qt .MouseButton .LeftButton )
399+
400+ # Get the plot state
401+ plot_state = mw .pipeline .get_plot (plot_id ).__getstate__ ()
402+
403+ # Verify division mode
404+ assert plot_state ["layout" ]["division" ] == "onlycontours"
405+
406+
407+ def test_contour_plot_with_invalid_percentiles (qtbot ):
408+ """Test contour plot with edge case percentiles (e.g., 100% KDE)"""
409+ mw = DCscope ()
410+ qtbot .addWidget (mw )
411+
412+ # Add a dataset
413+ path = datapath / "calibration_beads_47.rtdc"
414+ slot_id = mw .add_dataslot (paths = [path ])[0 ]
415+
416+ # Add a plot
417+ plot_id = mw .add_plot ()
418+
419+ # Activate the slot-plot pair to show data
420+ pe = mw .block_matrix .get_widget (slot_id , plot_id )
421+ qtbot .mouseClick (pe , QtCore .Qt .MouseButton .LeftButton )
422+
423+ # Activate analysis view
424+ pe = mw .block_matrix .get_widget (filt_plot_id = plot_id )
425+ qtbot .mouseClick (pe .toolButton_modify , QtCore .Qt .MouseButton .LeftButton )
426+
427+ # Switch to plot tab
428+ mw .widget_ana_view .tabWidget .setCurrentWidget (mw .widget_ana_view .tab_plot )
429+ pv = mw .widget_ana_view .widget_plot
430+
431+ # Enable contours
432+ pv .groupBox_contour .setChecked (True )
433+
434+ # Set contour percentiles to extreme values (edge cases)
435+ # 100% percentile is at the maximum KDE value
436+ pv .doubleSpinBox_perc_1 .setValue (100.0 ) # Maximum percentile
437+ pv .doubleSpinBox_perc_2 .setValue (100.0 ) # Near maximum
438+
439+ # Apply changes
440+ qtbot .mouseClick (pv .pushButton_apply , QtCore .Qt .MouseButton .LeftButton )
441+
442+ # Verify the plot state was updated with the new percentiles
443+ plot_state = mw .pipeline .get_plot (plot_id ).__getstate__ ()
444+ con = plot_state ["contour" ]
445+
446+ # Check that percentiles were set
447+ assert con ["percentiles" ][0 ] == 100.0
448+ assert con ["percentiles" ][1 ] == 100.0
449+ assert con ["enabled" ] is True
450+
451+ # Open the plot window to verify rendering works
452+ mw .add_plot_window (plot_id )
453+
454+ # Get the plot widget
455+ plot_widget = mw .subwindows_plots [plot_id ].widget ()
456+
457+ # Check that plot items were created
458+ assert plot_widget is not None
459+ if plot_widget .plot_items :
460+ assert len (plot_widget .plot_items ) > 0
0 commit comments