91
93
def get_cross_section(self, obj):
92
94
"""Get cross section data from source image"""
93
95
raise NotImplementedError
95
def update_item(self, obj):
99
source = self.get_source_image()
100
if source is None or not plot.isVisible():
97
def update_curve_data(self, obj):
102
98
sectx, secty = self.get_cross_section(obj)
103
99
if secty.size == 0 or np.all(np.isnan(secty)):
104
100
sectx, secty = np.array([]), np.array([])
105
101
if self._inverted:
106
self.set_data(secty, sectx)
102
self.process_curve_data(secty, sectx)
108
self.set_data(sectx, secty)
104
self.process_curve_data(sectx, secty)
106
def process_curve_data(self, x, y, dx=None, dy=None):
108
Override this method to process data
109
before updating the displayed curve
111
self.set_data(x, y, dx, dy)
113
def update_item(self, obj):
117
source = self.get_source_image()
118
if source is None or not plot.isVisible():
120
self.update_curve_data(obj)
121
self.plot().emit(SIG_CS_CURVE_CHANGED, self)
109
122
if not self.autoscale_mode:
110
123
self.update_scale()
112
125
def update_scale(self):
113
126
raise NotImplementedError
115
assert_interfaces_valid(CrossSectionItem)
118
129
def get_image_data(plot, p0, p1, apply_lut=False):
120
131
Save rectangular plot area
121
132
p0, p1: resp. top left and bottom right points (QPoint objects)
123
from guiqwt.image import (ImageItem, XYImageItem, TrImageItem,
124
get_image_from_plot, get_plot_source_rect)
126
items = [item for item in plot.items if isinstance(item, ImageItem)
127
and not isinstance(item, XYImageItem)]
134
from guiqwt.image import TrImageItem, get_image_from_plot, get_plot_qrect
135
items = plot.get_items(item_type=ICSImageItemType)
130
_src_x, _src_y, src_w, src_h = get_plot_source_rect(plot, p0, p1)
137
raise TypeError, _("There is no supported image item in current plot.")
138
_src_x, _src_y, src_w, src_h = get_plot_qrect(plot, p0, p1).getRect()
131
139
trparams = [item.get_transform() for item in items
132
140
if isinstance(item, TrImageItem)]
525
563
self.update_plot()
528
class XCrossSectionPlot(CrossSectionPlot):
529
"""X-axis cross section plot"""
531
CS_AXIS = CurvePlot.xBottom
532
Z_AXIS = CurvePlot.yLeft
566
class HorizontalCrossSectionPlot(CrossSectionPlot):
567
CS_AXIS = CurvePlot.X_BOTTOM
568
Z_AXIS = CurvePlot.Y_LEFT
533
569
CURVETYPE = "Yfx"
535
return QSize(self.width(), self._height)
537
def create_cross_section_item(self):
538
return XCrossSectionItem(self.curveparam)
540
570
def plot_labels_changed(self, plot):
541
571
"""Plot labels have changed"""
542
572
self.set_axis_title("left", plot.get_axis_title("right"))
543
573
self.set_axis_title("bottom", plot.get_axis_title("bottom"))
574
self.set_axis_color("left", plot.get_axis_color("right"))
575
self.set_axis_color("bottom", plot.get_axis_color("bottom"))
545
577
def axis_dir_changed(self, plot, axis_id):
546
578
"""An axis direction has changed"""
547
if axis_id == plot.xBottom:
579
if axis_id == plot.X_BOTTOM:
548
580
self.set_axis_direction("bottom", plot.get_axis_direction("bottom"))
552
class YCrossSectionPlot(CrossSectionPlot):
553
"""Y-axis cross section plot"""
555
CS_AXIS = CurvePlot.yLeft
556
Z_AXIS = CurvePlot.xBottom
583
class VerticalCrossSectionPlot(CrossSectionPlot):
584
CS_AXIS = CurvePlot.Y_LEFT
585
Z_AXIS = CurvePlot.X_BOTTOM
558
587
CURVETYPE = "Xfy"
560
return QSize(self._width, self.height())
562
def create_cross_section_item(self):
563
return YCrossSectionItem(self.curveparam)
565
588
def plot_labels_changed(self, plot):
566
589
"""Plot labels have changed"""
567
590
self.set_axis_title("bottom", plot.get_axis_title("right"))
568
591
self.set_axis_title("left", plot.get_axis_title("left"))
592
self.set_axis_color("bottom", plot.get_axis_color("right"))
593
self.set_axis_color("left", plot.get_axis_color("left"))
570
595
def axis_dir_changed(self, plot, axis_id):
571
596
"""An axis direction has changed"""
572
if axis_id == plot.yLeft:
597
if axis_id == plot.Y_LEFT:
573
598
self.set_axis_direction("left", plot.get_axis_direction("left"))
602
class XCrossSectionPlot(HorizontalCrossSectionPlot):
603
"""X-axis cross section plot"""
606
return QSize(self.width(), self._height)
608
def create_cross_section_item(self):
609
return XCrossSectionItem(self.curveparam)
611
class YCrossSectionPlot(VerticalCrossSectionPlot):
612
"""Y-axis cross section plot"""
615
return QSize(self._width, self.height())
617
def create_cross_section_item(self):
618
return YCrossSectionItem(self.curveparam)
577
621
class CrossSectionWidget(PanelWidget):
578
"""Cross section widget"""
623
PANEL_TITLE = _("Cross section tool")
624
PANEL_ICON = "csection.png"
579
625
CrossSectionPlotKlass = None
580
OTHER_PANEL_ID = None
582
627
__implements__ = (IPanel,)
584
629
def __init__(self, parent=None):
585
630
super(CrossSectionWidget, self).__init__(parent)
587
widget_title = _("Cross section tool")
588
widget_icon = "csection.png"
632
self.export_ac = None
633
self.autoscale_ac = None
634
self.refresh_ac = None
635
self.autorefresh_ac = None
590
637
self.manager = None # manager for the associated image plot
592
639
self.local_manager = PlotManager(self)
593
640
self.cs_plot = self.CrossSectionPlotKlass(parent)
595
self.spacer1 = QSpacerItem(0, 0)
596
self.spacer2 = QSpacerItem(0, 0)
598
self.toolbar = toolbar = QToolBar(self)
599
if self.CrossSectionPlotKlass is YCrossSectionPlot:
600
toolbar.setOrientation(Qt.Horizontal)
601
layout = QVBoxLayout()
602
layout.addSpacerItem(self.spacer1)
603
layout.addWidget(toolbar)
604
layout.addWidget(self.cs_plot)
605
layout.addSpacerItem(self.spacer2)
607
toolbar.setOrientation(Qt.Vertical)
608
layout = QHBoxLayout()
609
layout.addWidget(self.cs_plot)
610
layout.addWidget(toolbar)
611
layout.setContentsMargins(0, 0, 0, 0)
612
self.setLayout(layout)
614
self.local_manager.add_plot(self.cs_plot)
616
self.cs_plot.standard_tools(self.local_manager)
617
self.setWindowIcon(get_icon(widget_icon))
618
self.setWindowTitle(widget_title)
620
def set_options(self, peritem=None, applylut=None, autoscale=None):
641
self.connect(self.cs_plot, SIG_CS_CURVE_CHANGED,
642
self.cs_curve_has_changed)
644
# Configure the local manager
645
lman = self.local_manager
646
lman.add_plot(self.cs_plot)
647
lman.add_tool(SelectTool)
648
lman.add_tool(BasePlotMenuTool, "item")
649
lman.add_tool(BasePlotMenuTool, "axes")
650
lman.add_tool(BasePlotMenuTool, "grid")
651
lman.add_tool(AntiAliasingTool)
652
lman.add_tool(DeleteItemTool)
653
lman.get_default_tool().activate()
655
self.toolbar = QToolBar(self)
656
self.toolbar.setOrientation(Qt.Vertical)
660
def set_options(self, autoscale=None, autorefresh=None):
621
661
assert self.manager is not None, "Panel '%s' must be registered to plot manager before changing options" % self.PANEL_ID
622
if peritem is not None:
623
self.peritem_ac.setChecked(peritem)
624
if applylut is not None:
625
self.applylut_ac.setChecked(applylut)
626
662
if autoscale is not None:
627
663
self.autoscale_ac.setChecked(autoscale)
664
if autorefresh is not None:
665
self.autorefresh_ac.setChecked(autorefresh)
667
def setup_widget(self):
668
layout = QHBoxLayout()
669
layout.addWidget(self.cs_plot)
670
layout.addWidget(self.toolbar)
671
layout.setContentsMargins(0, 0, 0, 0)
672
self.setLayout(layout)
674
def cs_curve_has_changed(self, curve):
675
"""Cross section curve has just changed"""
676
# Do something with curve's data for example
629
679
def register_panel(self, manager):
630
680
"""Register panel to plot manager"""
631
681
self.manager = manager
632
682
for plot in manager.get_plots():
633
683
self.cs_plot.connect_plot(plot)
634
684
self.setup_actions()
635
other = manager.get_panel(self.OTHER_PANEL_ID)
685
self.add_actions_to_toolbar()
687
def configure_panel(self):
688
"""Configure panel"""
692
return self.manager.get_active_plot()
694
def setup_actions(self):
695
self.export_ac = create_action(self, _("Export"),
696
icon=get_std_icon("DialogSaveButton", 16),
697
triggered=self.cs_plot.export,
698
tip=_("Export cross section data"))
699
self.autoscale_ac = create_action(self, _("Auto-scale"),
700
icon=get_icon('csautoscale.png'),
701
toggled=self.cs_plot.toggle_autoscale)
702
self.autoscale_ac.setChecked(self.cs_plot.autoscale_mode)
703
self.refresh_ac = create_action(self, _("Refresh"),
704
icon=get_icon('refresh.png'),
705
triggered=lambda: self.cs_plot.update_plot())
706
self.autorefresh_ac = create_action(self, _("Auto-refresh"),
707
icon=get_icon('autorefresh.png'),
708
toggled=self.cs_plot.toggle_autorefresh)
709
self.autorefresh_ac.setChecked(self.cs_plot.autorefresh_mode)
711
def add_actions_to_toolbar(self):
712
add_actions(self.toolbar, (self.export_ac, self.autoscale_ac, None,
713
self.refresh_ac, self.autorefresh_ac))
715
def register_shape(self, shape, final):
716
plot = self.get_plot()
717
self.cs_plot.register_shape(plot, shape, final)
719
def unregister_shape(self, shape):
720
self.cs_plot.unregister_shape(shape)
722
def update_plot(self, obj=None):
724
Update cross section curve(s) associated to object *obj*
726
*obj* may be a marker or a rectangular shape
727
(see :py:class:`guiqwt.tools.CrossSectionTool`
728
and :py:class:`guiqwt.tools.AverageCrossSectionTool`)
730
If obj is None, update the cross sections of the last active object
732
self.cs_plot.update_plot(obj)
734
assert_interfaces_valid(CrossSectionWidget)
737
class XCrossSection(CrossSectionWidget):
738
"""X-axis cross section widget"""
740
OTHER_PANEL_ID = ID_YCS
741
CrossSectionPlotKlass = XCrossSectionPlot
742
def __init__(self, parent=None):
743
super(XCrossSection, self).__init__(parent)
744
self.peritem_ac = None
745
self.applylut_ac = None
747
def set_options(self, autoscale=None, autorefresh=None,
748
peritem=None, applylut=None):
749
assert self.manager is not None, "Panel '%s' must be registered to plot manager before changing options" % self.PANEL_ID
750
if autoscale is not None:
751
self.autoscale_ac.setChecked(autoscale)
752
if autorefresh is not None:
753
self.autorefresh_ac.setChecked(autorefresh)
754
if peritem is not None:
755
self.peritem_ac.setChecked(peritem)
756
if applylut is not None:
757
self.applylut_ac.setChecked(applylut)
759
def add_actions_to_toolbar(self):
760
other = self.manager.get_panel(self.OTHER_PANEL_ID)
636
761
if other is None:
637
762
add_actions(self.toolbar,
638
763
(self.peritem_ac, self.applylut_ac, None,
639
self.export_ac, self.autoscale_ac, self.refresh_ac))
764
self.export_ac, self.autoscale_ac,
765
self.refresh_ac, self.autorefresh_ac))
641
767
add_actions(self.toolbar,
642
768
(other.peritem_ac, other.applylut_ac, None,
643
self.export_ac, other.autoscale_ac, other.refresh_ac))
769
self.export_ac, other.autoscale_ac,
770
other.refresh_ac, other.autorefresh_ac))
644
771
self.connect(other.peritem_ac, SIGNAL("toggled(bool)"),
645
772
self.cs_plot.toggle_perimage_mode)
646
773
self.connect(other.applylut_ac, SIGNAL("toggled(bool)"),