· 8 years ago · Jul 27, 2018, 10:30 PM
1"""
2.. py:module:: dataview.methods.display.histogram
3
4=======================================
5Histogram
6=======================================
7
8This Display method displays a histogram from the currrent DataSelector in the
9viewer - same locators but views the distribution of points.
10"""
11'''
12:Version: 1
13:Author: Bill Dusch
14:Date: April 16, 2017
15'''
16
17from dataview.data.dataselector import DataSelector
18from dataview.methods.display.displaybase import DisplayMethodBase
19from dataview.main.dvaction import DVAction
20from dataview.main.dvlog import get_logger
21import dataview.data.dstasks as dst
22from dataview.utilities.analyze import add_viewer
23from copy import copy
24
25rootlog = get_logger('root')
26
27
28class Histogram(DisplayMethodBase):
29 """
30 Creates a histogram based on the dataselector from the current viewer.
31
32 Attributes
33 ----------
34 info : dict
35 This is one of two attributes which must be edited in each class
36 that inherits from the MethodBase base class.
37 A dictionary with the following entries:
38 version : float
39 The version number. This is important as it is used to determine
40 whether menus need to be regenerated and whether action lists can
41 be run in the same fashion (ie for automated Methods). Override
42 in implementation subclasses
43 submenu : string
44 Used for grouping together methods in a single submenu,
45 this can either be '', in which case the menuitem(s)
46 will be in the main part of the relevant menu (e.g. under
47 Process or Analyze depending on the `MethodType`) or
48 a menu name (e.g. 'Special') which will create that submenu
49 and put this and any other methods which list the same
50 submenu in it, or a submenu structure (e.g. 'Special.2015') in
51 which case a nested submenu structure will be created
52 menus : dict
53 A collection of menus, keyed by the `vista` (see `VISTAS`) in which
54 that menu is to be used. The menu format is flexible: see
55 DVMenu.add_item for details.
56
57 Menus (for DVMenu) can be defined by simple text, by a dict
58 with any subset of the following keys (you can abbreviate them):
59 ['text','icon','shortcut','tip','checked','whatsThis','name']
60 or with lists of multiple items or nested lists to make submenus.
61 Note that with lists that the first item is the menu name and the
62 other items show up as a sublist
63
64 Examples
65 --------
66 { '1D' : 'Line subtraction...' } # a simple string menu item
67 { '1D' : {'te':'Line subtraction...','sh':'Ctrl+L'} } # dict defined
68 { '2D' : ['Background Subtraction','Plane','2nd order'] }
69 { '1D' : 'Line sub', '2D' : 'Plane sub'}
70
71
72 Methods
73 -------
74 execute(action, viewer)
75 Execute the Method on the viewer, with details
76 in `action` (eg with the crop dvdim and given dataiterator)
77
78 create_action_from_menu(menuitem, menu, dataiterator)
79 Creates an action given a selected `menuitem` (and the `menu` from
80 which it was selected) and the `dataiterator` of the menu call
81 """
82
83 info = {
84 'version': 1.0, # Update version when you make substantive changes
85 'submenu': '' # Optional: allows grouping of some methods in submenu
86 }
87
88 userExplanation = ('Open up a histogram of data based on the distribution of data '
89 'in the current display')
90
91 menus = {'1D': 'Histogram',
92 '2D': 'Histogram'}
93
94#==============================================================================
95# Here are the vistas which should be considered in `menus`
96# VISTAS = [ # The different types
97# '1D', # 1 dvdim data (viewer if display method) or collection thereof
98# '2D', # 2 dimensional
99# '3D', # 3 dimensional
100# 'ND', # >3 dimensional
101# 'palette' # palette editor
102# ]
103#==============================================================================
104
105 @classmethod
106 def execute(cls, action, viewer):
107 """
108 Execute the Display (this should be the final execution method for
109 the Method regardless of entry point)
110
111 Parameters
112 ----------
113 action : DVAction
114 `action` specifies exactly how the Method is to be executed
115 as well as the dataSelector dataiterator
116 viewer : dataview.viewers.ViewerBase
117 Indicates the viewer on which the Method is to be executed
118
119 Returns
120 -------
121 bool
122 Was the execution successfully completed?
123 """
124 rootlog.info('Executing Method %s with action %s on viewer %s' %
125 (cls.__name__, action, viewer))
126 # Here's the question: Does an identical dataselector need to be copied or can we use the old one?
127 DS = viewer.viewObject
128 title = DS.name + ' (Histogram)'
129 new_viewer = cls.setup_hist_viewer(viewer, DS, parameters={'fourier': False, 'autoscale': True, 'title': title})
130 return True
131
132 @classmethod
133 def create_hist_dataselector(cls, dataset, oldDS, name=''):
134 """
135 Creates a new DataSelector from an originally existing dataset
136 Parameters
137 ----------
138 dataset
139 oldDS
140 name
141
142 Returns
143 -------
144
145 """
146 newDS = DataSelector(name, dataset)
147 locator_list = []
148 for task in oldDS:
149 if isinstance(task, dst.DSTaskLocator):
150 # these should be the same
151 destroy = task.parameters['destroy']
152 create = task.parameters['create']
153 # grab the old locator - we need to create a new one
154 old_locator = task.parameters['locator']
155 dimList = old_locator._dimList
156 locator = old_locator
157 if len(dimList) > 0:
158 parameters = {'locator': locator, 'create': create, 'destroy': destroy}
159 new_task = dst.DSTaskLocator(parameters=parameters)
160 newDS.append(new_task)
161 locator_list.append(locator)
162 elif not isinstance(task, dst.DSTaskLocatorHandler):
163 newDS.append(copy(task))
164 # And add the LocatorHandler
165 if len(newDS) > 0:
166 newDS.append(dst.DSTaskLocatorHandler(parameters={'locators': locator_list}))
167 newDS.process()
168 return newDS
169
170 @classmethod
171 def setup_hist_viewer(cls, orig_viewer, newDS, short=15, parameters=None):
172 """
173 Helper method to set up the viewer in an Analyze method.
174 Parameters
175 ----------
176 action: DVAction of the method, which stores viewgroup information
177 newDS: New DataSelector that the Analyze method created.
178 short: If one dimensional dataset, length of dimension for threshold to view as a Table instead of a Plot.
179
180 Returns
181 -------
182 viewer: Viewer
183 The viewer that is displayed.
184 """
185 parameters = {} if parameters is None else parameters
186 # Create viewer
187 new_viewer = add_viewer(orig_viewer.viewGroup)("HistViewer", newDS, parameters=parameters)
188 # Set up locatorwidgets
189 comboloc = [task.parameters['locator'].name for task in newDS if isinstance(task, dst.DSTaskLocator)
190 and len(task.parameters['locator']._dimList) == 1]
191 for name in comboloc:
192 new_viewer.addLWidget('ComboBox', newDS.get_locator(name), key='comboboxes')
193 new_viewer.display()
194 return new_viewer
195
196 @classmethod
197 def create_action_from_menu(cls, menuitem, viewer):
198 """
199 Creates an `action` based on a menu choice
200
201 Several things can happen here. In some cases the menu choice just
202 flips some parameter (like a checked menu item). In that case `None`
203 may be returned. In other cases the menu item will specifically
204 describe what action needs to be taken and that action will be returned
205 (note that the action should NOT be implemented at this point).
206 Finally, in some cases user interaction may be required to determine
207 the specifics of the action (e.g. menu commands ending in "..."). In
208 that case the gui should be presented to the user and the action
209 should be fleshed out. It can then either be returned OR cancelled
210 by returning `None`.
211
212 Parameters
213 ----------
214 menuitem : QAction
215 The menu item which was called. menuitem.text() is the text,
216 additional info may be in menuitem.data(), a dict which contains
217 at least "menu," the sub-QMenu in which this QAction exists
218 dataiterator : DataIterator
219 The object used to iterate over a dataset, containing information
220 about the dataiterator of the menu. This will include the dimensionality of
221 the data (and info about how to make it from the data selector) as well
222 as info about how it was called (e.g. from a display, or data list...)
223
224 Returns
225 -------
226 DVAction
227 The action to be performed based on the menu call (or None)
228 """
229 action = DVAction(method=cls, description='Histogram',
230 details={})
231 print('{}::create_action_from_menu, menuitem = {}'.format(cls.__name__, menuitem.text()))
232 return action