source: sasview/src/sas/qtgui/Plotting/Masks/BoxMask.py @ e0da307

Last change on this file since e0da307 was e20870bc, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

Masking dialog for fitting

  • Property mode set to 100644
File size: 8.5 KB
Line 
1import numpy as np
2
3from sas.qtgui.Plotting.Slicers.BaseInteractor import BaseInteractor
4from sas.qtgui.Plotting.Slicers.BoxSum import PointInteractor
5from sas.qtgui.Plotting.Slicers.BoxSum import VerticalDoubleLine
6from sas.qtgui.Plotting.Slicers.BoxSum import HorizontalDoubleLine
7
8
9class BoxMask(BaseInteractor):
10    """
11    BoxMask Class: determine 2 rectangular area to find the pixel of
12    a Data inside of box.
13
14    Uses PointerInteractor , VerticalDoubleLine,HorizontalDoubleLine.
15
16    :param zorder:  Artists with lower zorder values are drawn first.
17    :param x_min: the minimum value of the x coordinate
18    :param x_max: the maximum value of the x coordinate
19    :param y_min: the minimum value of the y coordinate
20    :param y_max: the maximum value of the y coordinate
21
22    """
23    def __init__(self, base, axes, color='black', zorder=3, side=None,
24                 x_min=0.008, x_max=0.008, y_min=0.0025, y_max=0.0025):
25        """
26        """
27        BaseInteractor.__init__(self, base, axes, color=color)
28        # list of Boxmask markers
29        self.markers = []
30        self.axes = axes
31        self.mask = None
32        self.is_inside = side
33        # connect the artist for the motion
34        self.connect = self.base.connect
35        # when qmax is reached the selected line is reset
36        self.qmax = min(self.base.data.xmax, self.base.data.xmin)
37        # Define the box limits
38        self.xmin = -1 * 0.5 * min(np.fabs(self.base.data.xmax),
39                                   np.fabs(self.base.data.xmin))
40        self.ymin = -1 * 0.5 * min(np.fabs(self.base.data.xmax),
41                                   np.fabs(self.base.data.xmin))
42        self.xmax = 0.5 * min(np.fabs(self.base.data.xmax),
43                              np.fabs(self.base.data.xmin))
44        self.ymax = 0.5 * min(np.fabs(self.base.data.xmax),
45                              np.fabs(self.base.data.xmin))
46        # center of the box
47        self.center_x = 0.0002
48        self.center_y = 0.0003
49        # Number of points on the plot
50        self.nbins = 20
51        # Define initial result the summation
52        self.count = 0
53        self.error = 0
54        self.data = self.base.data
55        # Flag to determine if the current figure has moved
56        # set to False == no motion , set to True== motion
57        self.has_move = False
58        # Create Box edges
59        self.horizontal_lines = HorizontalDoubleLine(self,
60                                                     self.axes,
61                                                     color='blue',
62                                                     zorder=zorder,
63                                                     y=self.ymax,
64                                                     x=self.xmax,
65                                                     center_x=self.center_x,
66                                                     center_y=self.center_y)
67        self.horizontal_lines.qmax = self.qmax
68
69        self.vertical_lines = VerticalDoubleLine(self,
70                                                 self.axes,
71                                                 color='grey',
72                                                 zorder=zorder,
73                                                 y=self.ymax,
74                                                 x=self.xmax,
75                                                 center_x=self.center_x,
76                                                 center_y=self.center_y)
77        self.vertical_lines.qmax = self.qmax
78
79        self.center = PointInteractor(self,
80                                      self.axes, color='grey',
81                                      zorder=zorder,
82                                      center_x=self.center_x,
83                                      center_y=self.center_y)
84        # Save the name of the slicer panel associate with this slicer
85        self.panel_name = ""
86        # Update and post slicer parameters
87        self.update()
88        self._post_data()
89
90    def clear(self):
91        """
92        Clear the slicer and all connected events related to this slicer
93        """
94        self.clear_markers()
95        self.horizontal_lines.clear()
96        self.vertical_lines.clear()
97        self.center.clear()
98        self.base.connect.clearall()
99
100    def update(self):
101        """
102        Respond to changes in the model by recalculating the profiles and
103        resetting the widgets.
104        """
105        # check if the center point has moved and update the figure accordingly
106        if self.center.has_move:
107            self.center.update()
108            self.horizontal_lines.update(center=self.center)
109            self.vertical_lines.update(center=self.center)
110        # # check if the horizontal lines have moved and update
111        # the figure accordingly
112        if self.horizontal_lines.has_move:
113            self.horizontal_lines.update()
114            self.vertical_lines.update(y1=self.horizontal_lines.y1,
115                                       y2=self.horizontal_lines.y2,
116                                       height=self.horizontal_lines.half_height)
117        # # check if the vertical lines have moved and update
118        # the figure accordingly
119        if self.vertical_lines.has_move:
120            self.vertical_lines.update()
121            self.horizontal_lines.update(x1=self.vertical_lines.x1,
122                                         x2=self.vertical_lines.x2,
123                                         width=self.vertical_lines.half_width)
124        # if self.is_inside is not None:
125        out = self._post_data()
126        return out
127
128    def save(self, ev):
129        """
130        Remember the roughness for this layer and the next so that we
131        can restore on Esc.
132        """
133        self.horizontal_lines.save(ev)
134        self.vertical_lines.save(ev)
135        self.center.save(ev)
136
137    def _post_data(self):
138        """
139        Get the limits of the boxsum and compute the sum of the pixel
140        contained in that region and the error on that sum
141        """
142        from sas.sascalc.dataloader.manipulations import Boxcut
143        # # Data 2D for which the pixel will be summed
144        data = self.base.data
145        mask = data.mask
146        # # the region of the summation
147        x_min = self.horizontal_lines.x2
148        x_max = self.horizontal_lines.x1
149        y_min = self.vertical_lines.y2
150        y_max = self.vertical_lines.y1
151        mask = Boxcut(x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max)
152
153        if self.is_inside:
154            out = (mask(data) == False)
155        else:
156            out = (mask(data))
157        # self.base.data.mask=out
158        self.mask = mask
159        return out
160
161    def moveend(self, ev):
162        """
163        After a dragging motion this function is called to compute
164        the error and the sum of pixel of a given data 2D
165        """
166        self._post_data()
167
168    def restore(self):
169        """
170        Restore the roughness for this layer.
171        """
172        self.horizontal_lines.restore()
173        self.vertical_lines.restore()
174        self.center.restore()
175
176    def move(self, x, y, ev):
177        """
178        Process move to a new position, making sure that the move is allowed.
179        """
180        pass
181
182    def set_cursor(self, x, y):
183        pass
184
185    def get_params(self):
186        """
187        Store a copy of values of parameters of the slicer into a dictionary.
188
189        :return params: the dictionary created
190        """
191        params = {}
192        params["Width"] = np.fabs(self.vertical_lines.half_width) * 2
193        params["Height"] = np.fabs(self.horizontal_lines.half_height) * 2
194        params["center_x"] = self.center.x
195        params["center_y"] = self.center.y
196        return params
197
198    def get_mask(self):
199        """
200        return mask as a result of boxcut
201        """
202        mask = self.mask
203        return mask
204
205    def set_params(self, params):
206        """
207        Receive a dictionary and reset the slicer with values contained
208        in the values of the dictionary.
209
210        :param params: a dictionary containing name of slicer parameters and
211           values the user assigned to the slicer.
212        """
213        x_max = np.fabs(params["Width"]) / 2
214        y_max = np.fabs(params["Height"]) / 2
215
216        self.center_x = params["center_x"]
217        self.center_y = params["center_y"]
218        # update the slicer given values of params
219        self.center.update(center_x=self.center_x, center_y=self.center_y)
220        self.horizontal_lines.update(center=self.center, width=x_max, height=y_max)
221        self.vertical_lines.update(center=self.center, width=x_max, height=y_max)
222        # compute the new error and sum given values of params
223        self._post_data()
224
225    def draw(self):
226        self.base.update()
227
228
Note: See TracBrowser for help on using the repository browser.