Changeset 6b0fc72 in sasview for src/sas/perspectives/invariant
- Timestamp:
- Mar 9, 2015 11:31:19 AM (10 years ago)
- Branches:
- master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
- Children:
- d26dea0
- Parents:
- 418e59f (diff), b1e609c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Location:
- src/sas/perspectives/invariant
- Files:
-
- 1 deleted
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/perspectives/invariant/invariant.py
rb9a5f0e r824e488 3 3 4 4 ################################################################################ 5 # This software was developed by the University of Tennessee as part of the6 # Distributed Data Analysis of Neutron Scattering Experiments (DANSE)7 # project funded by the US National Science Foundation.5 # This software was developed by the University of Tennessee as part of the 6 # Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 7 # project funded by the US National Science Foundation. 8 8 # 9 # See the license text in license.txt9 # See the license text in license.txt 10 10 # 11 # copyright 2009, University of Tennessee11 # copyright 2009, University of Tennessee 12 12 ################################################################################ 13 13 … … 30 30 """ 31 31 This class defines the interface for invariant Plugin class 32 that can be used by the gui_manager. 32 that can be used by the gui_manager. 33 33 """ 34 34 35 35 def __init__(self, standalone=False): 36 36 PluginBase.__init__(self, name="Invariant", standalone=standalone) 37 38 # dictionary containing data name and error on dy of that data37 38 # dictionary containing data name and error on dy of that data 39 39 self.err_dy = {} 40 41 # default state objects42 self.state_reader = None 40 41 # default state objects 42 self.state_reader = None 43 43 self._extensions = '.inv' 44 self.temp_state = None 45 self.__data = None 46 44 self.temp_state = None 45 self.__data = None 46 47 47 # Log startup 48 48 logging.info("Invariant plug-in started") 49 50 def help(self, evt): 51 """ 52 Show a general help dialog. 53 """ 54 from help_panel import HelpWindow 55 frame = HelpWindow(None, -1) 56 if hasattr(frame, "IsIconized"): 57 if not frame.IsIconized(): 58 try: 59 icon = self.parent.GetIcon() 60 frame.SetIcon(icon) 61 except: 62 pass 63 frame.Show(True) 64 49 65 50 def get_data(self): 66 51 """ 67 52 """ 68 53 return self.__data 69 54 70 55 def get_panels(self, parent): 71 56 """ 72 57 Create and return the list of wx.Panels for your plug-in. 73 58 Define the plug-in perspective. 74 59 75 60 Panels should inherit from DefaultPanel defined below, 76 61 or should present the same interface. They must define 77 62 "window_caption" and "window_name". 78 63 79 64 :param parent: parent window 80 65 81 66 :return: list of panels 82 67 """ 83 # # Save a reference to the parent68 # # Save a reference to the parent 84 69 self.parent = parent 85 self.frame = MDIFrame(self.parent, None, 'None', (100, 200)) 86 self.invariant_panel = InvariantPanel(parent=self.frame) 70 self.frame = MDIFrame(self.parent, None, 'None', (100, 200)) 71 self.invariant_panel = InvariantPanel(parent=self.frame) 87 72 self.frame.set_panel(self.invariant_panel) 88 73 self._frame_set_helper() 89 74 self.invariant_panel.set_manager(manager=self) 90 self.perspective.append(self.invariant_panel.window_name) 91 # Create reader when fitting panel are created92 self.state_reader = reader(self.set_state) 93 # append that reader to list of available reader75 self.perspective.append(self.invariant_panel.window_name) 76 # Create reader when fitting panel are created 77 self.state_reader = reader(self.set_state) 78 # append that reader to list of available reader 94 79 loader = Loader() 95 80 loader.associate_file_reader(".inv", self.state_reader) 96 # loader.associate_file_reader(".svs", self.state_reader)81 # loader.associate_file_reader(".svs", self.state_reader) 97 82 # Return the list of panels 98 83 return [self.invariant_panel] 99 84 100 85 def get_context_menu(self, plotpanel=None): 101 86 """ 102 87 This method is optional. 103 104 When the context menu of a plot is rendered, the 105 get_context_menu method will be called to give you a 88 89 When the context menu of a plot is rendered, the 90 get_context_menu method will be called to give you a 106 91 chance to add a menu item to the context menu. 107 92 108 93 A ref to a Graph object is passed so that you can 109 94 investigate the plot content and decide whether you 110 need to add items to the context menu. 111 95 need to add items to the context menu. 96 112 97 This method returns a list of menu items. 113 Each item is itself a list defining the text to 98 Each item is itself a list defining the text to 114 99 appear in the menu, a tool-tip help text, and a 115 100 call-back method. 116 101 117 102 :param graph: the Graph object to which we attach the context menu 118 103 119 104 :return: a list of menu items with call-back function 120 105 """ … … 123 108 invariant_hint = "Will displays the invariant panel for" 124 109 invariant_hint += " further computation" 125 110 126 111 if graph.selected_plottable not in plotpanel.plots: 127 112 return [] 128 113 data = plotpanel.plots[graph.selected_plottable] 129 114 130 115 if issubclass(data.__class__, Data1D): 131 if data.name != "$I_{obs}(q)$" and data.name != " $P_{fit}(r)$": 132 return [[invariant_option, invariant_hint, 133 self._compute_invariant]] 116 if data.name != "$I_{obs}(q)$" and data.name != " $P_{fit}(r)$": 117 return [[invariant_option, invariant_hint, self._compute_invariant]] 134 118 return [] 135 119 136 def _compute_invariant(self, event): 120 def _compute_invariant(self, event): 137 121 """ 138 122 Open the invariant panel to invariant computation … … 147 131 name = data.__class__.__name__ 148 132 msg = "Invariant use only Data1D got: [%s] " % str(name) 149 raise ValueError, msg 133 raise ValueError, msg 150 134 self.compute_helper(data=data) 151 135 152 136 def set_data(self, data_list=None): 153 137 """ … … 172 156 else: 173 157 error_msg += " %s type %s \n" % (str(data.name), 174 str(data.__class__.__name__))158 str(data.__class__.__name__)) 175 159 data_2d_list.append(data) 176 160 if len(data_2d_list) > 0: … … 178 162 msg += error_msg 179 163 if len(data_1d_list) == 0: 180 wx.PostEvent(self.parent, 181 StatusEvent(status=msg, info='error')) 164 wx.PostEvent(self.parent, StatusEvent(status=msg, info='error')) 182 165 return 183 166 msg += "Invariant panel does not allow multiple data!\n" … … 194 177 if data is None: 195 178 msg += "invariant receives no data. \n" 196 wx.PostEvent(self.parent, 197 StatusEvent(status=msg, info='error')) 179 wx.PostEvent(self.parent, StatusEvent(status=msg, info='error')) 198 180 return 199 181 if not issubclass(data.__class__, Data1D): 200 msg += "invariant cannot be computed for data of " 201 msg += "type %s\n" % (data.__class__.__name__) 202 wx.PostEvent(self.parent, 203 StatusEvent(status=msg, info='error')) 204 return 182 msg += "invariant cannot be computed for data of " 183 msg += "type %s\n" % (data.__class__.__name__) 184 wx.PostEvent(self.parent, StatusEvent(status=msg, info='error')) 185 return 205 186 else: 206 wx.PostEvent(self.parent, NewPlotEvent(plot=data, 207 title=data.title)) 187 wx.PostEvent(self.parent, NewPlotEvent(plot=data, title=data.title)) 208 188 try: 209 189 self.compute_helper(data) 210 190 except: 211 191 msg = "Invariant Set_data: " + str(sys.exc_value) 212 wx.PostEvent(self.parent, StatusEvent(status=msg, 213 info="error")) 214 else: 192 wx.PostEvent(self.parent, StatusEvent(status=msg, info="error")) 193 else: 215 194 msg = "invariant cannot be computed for data of " 216 195 msg += "type %s" % (data.__class__.__name__) 217 wx.PostEvent(self.parent, 218 StatusEvent(status=msg, info='error')) 196 wx.PostEvent(self.parent, StatusEvent(status=msg, info='error')) 197 219 198 def delete_data(self, data_id): 220 199 """ … … 225 204 if id == self.__data.id: 226 205 self.clear_panel() 227 206 228 207 def clear_panel(self): 229 208 """ 230 209 """ 231 210 self.invariant_panel.clear_panel() 232 211 233 212 def compute_helper(self, data): 234 213 """ 235 214 """ 236 215 if data is None: 237 return 216 return 238 217 # set current data if not it's a state data 239 218 if not self.invariant_panel.is_state_data: … … 242 221 # Set the data set to be user for invariant calculation 243 222 self.invariant_panel.set_data(data=data) 244 223 245 224 def save_file(self, filepath, state=None): 246 225 """ 247 226 Save data in provided state object. 248 227 249 228 :param filepath: path of file to write to 250 :param state: invariant state 251 """ 229 :param state: invariant state 230 """ 252 231 # Write the state to file 253 232 # First, check that the data is of the right type … … 258 237 else: 259 238 msg = "invariant.save_file: the data being saved is" 260 msg += " not a sas.dataloader.data_info.Data1D object" 239 msg += " not a sas.dataloader.data_info.Data1D object" 261 240 raise RuntimeError, msg 262 241 263 def set_state(self, state=None, datainfo=None): 242 def set_state(self, state=None, datainfo=None): 264 243 """ 265 244 Call-back method for the state reader. 266 245 This method is called when a .inv/.svs file is loaded. 267 246 268 247 :param state: State object 269 248 """ … … 279 258 raise RuntimeError, msg 280 259 # Make sure the user sees the invariant panel after loading 281 # self.parent.set_perspective(self.perspective)260 # self.parent.set_perspective(self.perspective) 282 261 self.on_perspective(event=None) 283 262 name = data.meta_data['invstate'].file … … 286 265 data.filename = name 287 266 288 data = self.parent.create_gui_data(data, None)267 data = self.parent.create_gui_data(data, None) 289 268 self.__data = data 290 269 wx.PostEvent(self.parent, NewPlotEvent(plot=self.__data, 291 reset=True, title=self.__data.title))270 reset=True, title=self.__data.title)) 292 271 data_dict = {self.__data.id:self.__data} 293 272 self.parent.add_data(data_list=data_dict) 294 273 # set state 295 274 self.invariant_panel.is_state_data = True 296 275 297 276 # Load the invariant states 298 277 self.temp_state = state … … 300 279 self.on_set_state_helper(None) 301 280 302 except: 281 except: 303 282 logging.error("invariant.set_state: %s" % sys.exc_value) 304 283 305 284 def on_set_state_helper(self, event=None): 306 285 """ 307 286 Set the state when called by EVT_STATE_UPDATE event from guiframe 308 after a .inv/.svs file is loaded 287 after a .inv/.svs file is loaded 309 288 """ 310 289 self.invariant_panel.set_state(state=self.temp_state, 311 290 data=self.__data) 312 291 self.temp_state = None 313 314 292 293 315 294 def plot_theory(self, data=None, name=None): 316 295 """ 317 296 Receive a data set and post a NewPlotEvent to parent. 318 297 319 298 :param data: extrapolated data to be plotted 320 299 :param name: Data's name to use for the legend 321 300 """ 322 # import copy301 # import copy 323 302 if data is None: 324 303 id = str(self.__data.id) + name 325 304 group_id = self.__data.group_id 326 wx.PostEvent(self.parent, NewPlotEvent(id=id, 327 group_id=group_id, 328 action='Remove')) 329 return 330 305 wx.PostEvent(self.parent, NewPlotEvent(id=id, group_id=group_id, action='Remove')) 306 return 307 331 308 new_plot = Data1D(x=[], y=[], dy=None) 332 309 new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM 333 310 scale = self.invariant_panel.get_scale() 334 311 background = self.invariant_panel.get_background() 335 312 336 313 if scale != 0: 337 314 # Put back the sacle and bkg for plotting 338 data.y = (data.y + background) /scale315 data.y = (data.y + background) / scale 339 316 new_plot = Data1D(x=data.x, y=data.y, dy=None) 340 317 new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM … … 342 319 msg = "Scale can not be zero." 343 320 raise ValueError, msg 344 if len(new_plot.x) == 0:345 return 346 321 if len(new_plot.x) == 0: 322 return 323 347 324 new_plot.name = name 348 325 new_plot.xaxis(self.__data._xaxis, self.__data._xunit) … … 357 334 self.invariant_panel.state.theory_lowQ = copy.deepcopy(new_plot) 358 335 elif name_head[0] == 'High': 359 self.invariant_panel.state.theory_highQ = copy.deepcopy(new_plot)360 336 self.invariant_panel.state.theory_highQ = copy.deepcopy(new_plot) 337 361 338 self.parent.update_theory(data_id=self.__data.id, theory=new_plot) 362 339 wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, 363 340 title=self.__data.title)) 364 341 365 342 def plot_data(self, scale, background): 366 343 """ … … 370 347 new_plot.name = self.__data.name 371 348 new_plot.group_id = self.__data.group_id 372 new_plot.id = self.__data.id 349 new_plot.id = self.__data.id 373 350 new_plot.title = self.__data.title 374 375 # Save data in a state: but seems to never happen 351 352 # Save data in a state: but seems to never happen 376 353 if new_plot != None: 377 354 self.invariant_panel.state.data = copy.deepcopy(new_plot) 378 355 wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, 379 356 title=new_plot.title)) 380 357 -
src/sas/perspectives/invariant/invariant_details.py
r79492222 r78a205a 8 8 from invariant_widgets import OutputTextCtrl 9 9 # Dimensions related to chart 10 RECTANGLE_WIDTH = 400.010 RECTANGLE_WIDTH = 400.0 11 11 RECTANGLE_HEIGHT = 20 12 # Invariant panel size12 # Invariant panel size 13 13 _BOX_WIDTH = 76 14 14 15 # scale to use for a bar of value zero16 RECTANGLE_SCALE 17 DEFAULT_QSTAR = 1.0 18 15 # scale to use for a bar of value zero 16 RECTANGLE_SCALE = 0.0001 17 DEFAULT_QSTAR = 1.0 18 19 19 if sys.platform.count("win32") > 0: 20 20 _STATICBOX_WIDTH = 450 … … 27 27 PANEL_HEIGHT = 430 28 28 FONT_VARIANT = 1 29 30 ERROR_COLOR = wx.Colour(255, 31 EXTRAPOLATION_COLOR = wx.Colour(169, 32 INVARIANT_COLOR = wx.Colour(67, 208, 128, 128)33 34 29 30 ERROR_COLOR = wx.Colour(255, 0, 0, 128) 31 EXTRAPOLATION_COLOR = wx.Colour(169, 169, 168, 128) 32 INVARIANT_COLOR = wx.Colour(67, 208, 128, 128) 33 34 35 35 class InvariantContainer(wx.Object): 36 36 """ 37 37 This class stores some values resulting resulting from invariant 38 calculations. Given the value of total invariant, this class can also 38 calculations. Given the value of total invariant, this class can also 39 39 determine the percentage of invariants resulting from extrapolation. 40 40 """ 41 41 def __init__(self): 42 # invariant at low range42 # invariant at low range 43 43 self.qstar_low = None 44 # invariant at low range error44 # invariant at low range error 45 45 self.qstar_low_err = None 46 # invariant46 # invariant 47 47 self.qstar = None 48 # invariant error48 # invariant error 49 49 self.qstar_err = None 50 # invariant at high range50 # invariant at high range 51 51 self.qstar_high = None 52 # invariant at high range error52 # invariant at high range error 53 53 self.qstar_high_err = None 54 # invariant total54 # invariant total 55 55 self.qstar_total = None 56 # invariant error56 # invariant error 57 57 self.qstar_total_err = None 58 # scale58 # scale 59 59 self.qstar_low_percent = None 60 60 self.qstar_high_percent = None … … 63 63 self.existing_warning = False 64 64 self.warning_msg = "No Details on calculations available...\n" 65 65 66 66 def compute_percentage(self): 67 67 """ … … 73 73 self.qstar_high = None 74 74 self.check_values() 75 return 76 77 # compute invariant percentage75 return 76 77 # compute invariant percentage 78 78 if self.qstar is None: 79 79 self.qstar_percent = None 80 80 else: 81 81 try: 82 self.qstar_percent = float(self.qstar) /float(self.qstar_total)82 self.qstar_percent = float(self.qstar) / float(self.qstar_total) 83 83 except: 84 84 self.qstar_percent = 'error' 85 # compute low q invariant percentage85 # compute low q invariant percentage 86 86 if self.qstar_low is None: 87 87 self.qstar_low_percent = None … … 89 89 try: 90 90 self.qstar_low_percent = float(self.qstar_low)\ 91 / float(self.qstar_total)91 / float(self.qstar_total) 92 92 except: 93 93 self.qstar_low_percent = 'error' 94 # compute high q invariant percentage94 # compute high q invariant percentage 95 95 if self.qstar_high is None: 96 96 self.qstar_high_percent = None … … 98 98 try: 99 99 self.qstar_high_percent = float(self.qstar_high)\ 100 / float(self.qstar_total)100 / float(self.qstar_total) 101 101 except: 102 102 self.qstar_high_percent = 'error' 103 103 wx.CallAfter(self.check_values) 104 104 105 105 def check_values(self): 106 106 """ … … 109 109 if self.qstar_total is None and self.qstar is None: 110 110 self.warning_msg = "Invariant not calculated.\n" 111 return 111 return 112 112 if self.qstar_total == 0: 113 113 self.existing_warning = True … … 115 115 self.warning_msg += "The calculations are likely " 116 116 self.warning_msg += "to be unreliable!\n" 117 return 118 # warning to the user when the extrapolated invariant is greater than %5117 return 118 # warning to the user when the extrapolated invariant is greater than %5 119 119 msg = '' 120 120 if self.qstar_percent == 'error': … … 135 135 msg += "Error occurred when computing extrapolated invariant" 136 136 msg += " at low-Q region.\n" 137 elif self.qstar_low_percent is not None 137 elif self.qstar_low_percent is not None: 138 138 if self.qstar_low_percent >= 0.05: 139 139 self.existing_warning = True … … 172 172 msg += "The sum of all extrapolated contributions is higher " 173 173 msg += "than 5% of the invariant.\n" 174 174 175 175 if self.existing_warning: 176 176 self.warning_msg = '' 177 self.warning_msg += msg 177 self.warning_msg += msg 178 178 self.warning_msg += "The calculations are likely to be" 179 179 self.warning_msg += " unreliable!\n" 180 180 else: 181 181 self.warning_msg = "No Details on calculations available...\n" 182 182 183 183 class InvariantDetailsPanel(wx.Dialog): 184 184 """ 185 This panel describes proportion of invariants 185 This panel describes proportion of invariants 186 186 """ 187 def __init__(self, parent=None, id=-1, qstar_container=None, 188 189 187 def __init__(self, parent=None, id=-1, qstar_container=None, 188 title="Invariant Details", 189 size=(PANEL_WIDTH, PANEL_HEIGHT)): 190 190 wx.Dialog.__init__(self, parent=parent, id=id, title=title, size=size) 191 192 # Font size191 192 # Font size 193 193 self.SetWindowVariant(variant=FONT_VARIANT) 194 194 self.parent = parent 195 # self.qstar_container195 # self.qstar_container 196 196 self.qstar_container = qstar_container 197 # warning message197 # warning message 198 198 self.warning_msg = self.qstar_container.warning_msg 199 200 # Define scale of each bar199 200 # Define scale of each bar 201 201 self.low_inv_percent = self.qstar_container.qstar_low_percent 202 202 self.low_scale = self.get_scale(percentage=self.low_inv_percent, 203 203 scale_name="Extrapolated at Low Q") 204 204 self.inv_percent = self.qstar_container.qstar_percent 205 self.inv_scale = self.get_scale(percentage=self.inv_percent, 206 205 self.inv_scale = self.get_scale(percentage=self.inv_percent, 206 scale_name="Inv in Q range") 207 207 self.high_inv_percent = self.qstar_container.qstar_high_percent 208 208 self.high_scale = self.get_scale(percentage=self.high_inv_percent, 209 209 scale_name="Extrapolated at High Q") 210 211 # Default color the extrapolation bar is grey210 211 # Default color the extrapolation bar is grey 212 212 self.extrapolation_color_low = EXTRAPOLATION_COLOR 213 213 self.extrapolation_color_high = EXTRAPOLATION_COLOR 214 214 self.invariant_color = INVARIANT_COLOR 215 # change color of high and low bar when necessary215 # change color of high and low bar when necessary 216 216 self.set_color_bar() 217 # draw the panel itself217 # draw the panel itself 218 218 self._do_layout() 219 219 self.set_values() 220 220 221 221 def _define_structure(self): 222 222 """ 223 223 Define main sizers needed for this panel 224 224 """ 225 # Box sizers must be defined first before defining buttons/textctrls225 # Box sizers must be defined first before defining buttons/textctrls 226 226 # (MAC). 227 227 self.main_sizer = wx.BoxSizer(wx.VERTICAL) 228 # Sizer related to chart228 # Sizer related to chart 229 229 chart_box = wx.StaticBox(self, -1, "Invariant Chart") 230 230 self.chart_sizer = wx.StaticBoxSizer(chart_box, wx.VERTICAL) 231 231 self.chart_sizer.SetMinSize((PANEL_WIDTH - 50, 110)) 232 # Sizer related to invariant values233 self.invariant_sizer = 232 # Sizer related to invariant values 233 self.invariant_sizer = wx.GridBagSizer(4, 4) 234 234 invariant_box = wx.StaticBox(self, -1, "Numerical Values") 235 self.invariant_box_sizer = wx.StaticBoxSizer(invariant_box, 236 wx.HORIZONTAL) 235 self.invariant_box_sizer = wx.StaticBoxSizer(invariant_box, wx.HORIZONTAL) 237 236 238 237 self.invariant_box_sizer.SetMinSize((PANEL_WIDTH - 50, -1)) 239 # Sizer related to warning message238 # Sizer related to warning message 240 239 warning_box = wx.StaticBox(self, -1, "Warning") 241 240 self.warning_sizer = wx.StaticBoxSizer(warning_box, wx.VERTICAL) 242 self.warning_sizer.SetMinSize((PANEL_WIDTH -50, -1))243 # Sizer related to button241 self.warning_sizer.SetMinSize((PANEL_WIDTH - 50, -1)) 242 # Sizer related to button 244 243 self.button_sizer = wx.BoxSizer(wx.HORIZONTAL) 245 244 246 245 def _layout_shart(self): 247 246 """ … … 250 249 self.panel_chart = wx.Panel(self) 251 250 self.panel_chart.Bind(wx.EVT_PAINT, self.on_paint) 252 self.chart_sizer.Add(self.panel_chart, 1, wx.EXPAND |wx.ALL, 0)253 251 self.chart_sizer.Add(self.panel_chart, 1, wx.EXPAND | wx.ALL, 0) 252 254 253 def _layout_invariant(self): 255 254 """ 256 255 Draw widgets related to invariant 257 256 """ 258 uncertainty = "+/-" 257 uncertainty = "+/-" 259 258 unit_invariant = '[1/(cm * A^3)]' 260 259 261 260 invariant_txt = wx.StaticText(self, -1, 'Q* from Data ') 262 261 invariant_txt.SetToolTipString("Invariant in the data set's Q range.") … … 270 269 hint_msg = "Unit of the invariant from data's Q range" 271 270 invariant_units_txt.SetToolTipString(hint_msg) 272 271 273 272 invariant_low_txt = wx.StaticText(self, -1, 'Q* from Low-Q') 274 273 hint_msg = "Extrapolated invariant from low-Q range." … … 284 283 hint_msg = "Unit of the extrapolated invariant from low-Q range" 285 284 invariant_low_units_txt.SetToolTipString(hint_msg) 286 285 287 286 invariant_high_txt = wx.StaticText(self, -1, 'Q* from High-Q') 288 287 hint_msg = "Extrapolated invariant from high-Q range" … … 299 298 hint_msg = "Unit of the extrapolated invariant from high-Q range" 300 299 invariant_high_units_txt.SetToolTipString(hint_msg) 301 302 # Invariant low300 301 # Invariant low 303 302 iy = 0 304 ix = 0 303 ix = 0 305 304 self.invariant_sizer.Add(invariant_low_txt, (iy, ix), (1, 1), 306 wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)305 wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 307 306 ix += 1 308 307 self.invariant_sizer.Add(self.invariant_low_tcl, (iy, ix), (1, 1), 309 wx.EXPAND|wx.ADJUST_MINSIZE, 0)310 ix += 1 311 self.invariant_sizer.Add( 312 (iy, ix), (1, 1),wx.EXPAND|wx.ADJUST_MINSIZE, 0)308 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 309 ix += 1 310 self.invariant_sizer.Add(wx.StaticText(self, -1, uncertainty), 311 (iy, ix), (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0) 313 312 ix += 1 314 313 self.invariant_sizer.Add(self.invariant_low_err_tcl, (iy, ix), (1, 1), 315 wx.EXPAND|wx.ADJUST_MINSIZE, 0)316 ix += 1 317 self.invariant_sizer.Add(invariant_low_units_txt 318 ,(iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)319 # Invariant314 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 315 ix += 1 316 self.invariant_sizer.Add(invariant_low_units_txt, 317 (iy, ix), (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0) 318 # Invariant 320 319 iy += 1 321 ix = 0 320 ix = 0 322 321 self.invariant_sizer.Add(invariant_txt, (iy, ix), (1, 1), 323 wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)322 wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 324 323 ix += 1 325 324 self.invariant_sizer.Add(self.invariant_tcl, (iy, ix), (1, 1), 326 wx.EXPAND|wx.ADJUST_MINSIZE, 0)325 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 327 326 ix += 1 328 327 self.invariant_sizer.Add(wx.StaticText(self, -1, uncertainty), 329 (iy, ix), (1, 1),wx.EXPAND|wx.ADJUST_MINSIZE, 0)328 (iy, ix), (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0) 330 329 ix += 1 331 330 self.invariant_sizer.Add(self.invariant_err_tcl, (iy, ix), (1, 1), 332 wx.EXPAND|wx.ADJUST_MINSIZE, 0)333 ix += 1334 self.invariant_sizer.Add(invariant_units_txt 335 ,(iy, ix), (1, 1),wx.EXPAND|wx.ADJUST_MINSIZE, 0)336 # Invariant high331 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 332 ix += 1 333 self.invariant_sizer.Add(invariant_units_txt, 334 (iy, ix), (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0) 335 # Invariant high 337 336 iy += 1 338 ix = 0 337 ix = 0 339 338 self.invariant_sizer.Add(invariant_high_txt, (iy, ix), (1, 1), 340 wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)339 wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 341 340 ix += 1 342 341 self.invariant_sizer.Add(self.invariant_high_tcl, (iy, ix), (1, 1), 343 wx.EXPAND|wx.ADJUST_MINSIZE, 0)342 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 344 343 ix += 1 345 344 self.invariant_sizer.Add(wx.StaticText(self, -1, uncertainty), 346 (iy, ix), (1, 1),wx.EXPAND|wx.ADJUST_MINSIZE, 0)345 (iy, ix), (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0) 347 346 ix += 1 348 347 self.invariant_sizer.Add(self.invariant_high_err_tcl, (iy, ix), (1, 1), 349 wx.EXPAND|wx.ADJUST_MINSIZE, 0) 350 ix += 1 351 self.invariant_sizer.Add(invariant_high_units_txt 352 ,(iy, ix), (1, 1),wx.EXPAND|wx.ADJUST_MINSIZE, 0) 353 self.invariant_box_sizer.Add(self.invariant_sizer, 0, 354 wx.TOP|wx.BOTTOM, 10) 355 348 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 349 ix += 1 350 self.invariant_sizer.Add(invariant_high_units_txt, 351 (iy, ix), (1, 1), wx.EXPAND | wx.ADJUST_MINSIZE, 0) 352 self.invariant_box_sizer.Add(self.invariant_sizer, 0, wx.TOP | wx.BOTTOM, 10) 353 356 354 def _layout_warning(self): 357 355 """ 358 356 Draw widgets related to warning 359 357 """ 360 # Warning [string]361 self.warning_msg_txt = wx.StaticText(self, -1, self.warning_msg) 358 # Warning [string] 359 self.warning_msg_txt = wx.StaticText(self, -1, self.warning_msg) 362 360 if self.qstar_container.existing_warning: 363 self.warning_msg_txt.SetForegroundColour('red') 361 self.warning_msg_txt.SetForegroundColour('red') 364 362 self.warning_sizer.AddMany([(self.warning_msg_txt, 0, 365 wx.LEFT |wx.EXPAND|wx.ADJUST_MINSIZE, 10)])366 363 wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 10)]) 364 367 365 def _layout_button(self): 368 366 """ 369 367 Draw widgets related to button 370 368 """ 371 # Close button369 # Close button 372 370 id = wx.NewId() 373 371 button_ok = wx.Button(self, id, "Ok") 374 372 button_ok.SetToolTipString("Give Details on Computation") 375 373 self.Bind(wx.EVT_BUTTON, self.on_close, id=id) 376 self.button_sizer.AddMany([((20, 20), 0 377 (button_ok, 0 374 self.button_sizer.AddMany([((20, 20), 0, wx.LEFT, 350), 375 (button_ok, 0, wx.RIGHT, 10)]) 378 376 def _do_layout(self): 379 377 """ … … 386 384 self._layout_button() 387 385 self.main_sizer.AddMany([(self.chart_sizer, 0, wx.ALL, 10), 388 ( 389 390 386 (self.invariant_box_sizer, 0, wx.ALL, 10), 387 (self.warning_sizer, 0, wx.ALL, 10), 388 (self.button_sizer, 0, wx.ALL, 10)]) 391 389 self.SetSizer(self.main_sizer) 392 393 390 391 394 392 def set_values(self): 395 393 """ … … 399 397 self.invariant_tcl.SetValue(value) 400 398 value = format_number(self.qstar_container.qstar_err) 401 self.invariant_err_tcl.SetValue(value) 399 self.invariant_err_tcl.SetValue(value) 402 400 value = format_number(self.qstar_container.qstar_low) 403 401 self.invariant_low_tcl.SetValue(value) 404 402 value = format_number(self.qstar_container.qstar_low_err) 405 self.invariant_low_err_tcl.SetValue(value) 403 self.invariant_low_err_tcl.SetValue(value) 406 404 value = format_number(self.qstar_container.qstar_high) 407 405 self.invariant_high_tcl.SetValue(value) 408 406 value = format_number(self.qstar_container.qstar_high_err) 409 self.invariant_high_err_tcl.SetValue(value) 407 self.invariant_high_err_tcl.SetValue(value) 410 408 411 409 def get_scale(self, percentage, scale_name='scale'): 412 410 """ 413 Check scale receive in this panel. 411 Check scale receive in this panel. 414 412 """ 415 413 scale = RECTANGLE_SCALE 416 try: 414 try: 417 415 if percentage in [None, 0.0, "error"]: 418 419 416 scale = RECTANGLE_SCALE 417 return scale 420 418 elif percentage < 0: 421 419 scale = RECTANGLE_SCALE … … 427 425 self.warning_msg += "check this value : %s\n" % str(percentage) 428 426 return scale 429 427 430 428 def set_color_bar(self): 431 429 """ … … 435 433 self.extrapolation_color_high = EXTRAPOLATION_COLOR 436 434 self.invariant_color = INVARIANT_COLOR 437 # warning to the user when the extrapolated invariant is greater than %5435 # warning to the user when the extrapolated invariant is greater than %5 438 436 if self.low_scale >= 0.05 or self.low_scale > 1 or self.low_scale < 0: 439 self.extrapolation_color_low = ERROR_COLOR 437 self.extrapolation_color_low = ERROR_COLOR 440 438 if self.high_scale >= 0.05 or self.high_scale > 1 or self.high_scale < 0: 441 self.extrapolation_color_high = ERROR_COLOR 439 self.extrapolation_color_high = ERROR_COLOR 442 440 if self.inv_scale > 1 or self.inv_scale < 0: 443 self.invariant_color = ERROR_COLOR 444 441 self.invariant_color = ERROR_COLOR 442 445 443 def on_close(self, event): 446 444 """ … … 448 446 """ 449 447 self.Close() 450 448 451 449 def on_paint(self, event): 452 450 """ … … 461 459 dc.DrawText(msg, 25, 25) 462 460 return 463 # Start the drawing461 # Start the drawing 464 462 font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) 465 463 font.SetWeight(wx.BOLD) … … 467 465 # Draw a rectangle 468 466 path = gc.CreatePath() 469 path.AddRectangle(-RECTANGLE_WIDTH /2,-RECTANGLE_HEIGHT/2,470 RECTANGLE_WIDTH /2,RECTANGLE_HEIGHT/2)467 path.AddRectangle(-RECTANGLE_WIDTH / 2, -RECTANGLE_HEIGHT / 2, 468 RECTANGLE_WIDTH / 2, RECTANGLE_HEIGHT / 2) 471 469 x_origine = 20 472 470 y_origine = 15 473 # Draw low rectangle474 gc.PushState() 471 # Draw low rectangle 472 gc.PushState() 475 473 label = "Q* from Low-Q " 476 474 PathFunc = gc.DrawPath 477 475 w, h = gc.GetTextExtent(label) 478 476 gc.DrawText(label, x_origine, y_origine) 479 # Translate the rectangle480 x_center = x_origine + RECTANGLE_WIDTH * self.low_scale /2 + w +10477 # Translate the rectangle 478 x_center = x_origine + RECTANGLE_WIDTH * self.low_scale / 2 + w + 10 481 479 y_center = y_origine + h 482 gc.Translate(x_center, y_center) 480 gc.Translate(x_center, y_center) 483 481 gc.SetPen(wx.Pen("black", 1)) 484 482 gc.SetBrush(wx.Brush(self.extrapolation_color_low)) … … 488 486 low_percent = 'Error' 489 487 else: 490 low_percent = format_number(self.low_inv_percent *100)+ '%'488 low_percent = format_number(self.low_inv_percent * 100) + '%' 491 489 x_center = 20 492 490 y_center = -h 493 491 gc.DrawText(low_percent, x_center, y_center) 494 492 # Increase width by self.low_scale 495 gc.Scale(self.low_scale, 1.0) 493 gc.Scale(self.low_scale, 1.0) 496 494 PathFunc(path) 497 gc.PopState() 498 # Draw rectangle for invariant499 gc.PushState() 500 y_origine += 20 495 gc.PopState() 496 # Draw rectangle for invariant 497 gc.PushState() # save it again 498 y_origine += 20 501 499 gc.DrawText("Q* from Data ", x_origine, y_origine) 502 500 # offset to the lower part of the window 503 x_center = x_origine + RECTANGLE_WIDTH * self.inv_scale /2 + w + 10501 x_center = x_origine + RECTANGLE_WIDTH * self.inv_scale / 2 + w + 10 504 502 y_center = y_origine + h 505 503 gc.Translate(x_center, y_center) 506 504 # 128 == half transparent 507 gc.SetBrush(wx.Brush(self.invariant_color)) 505 gc.SetBrush(wx.Brush(self.invariant_color)) 508 506 # Increase width by self.inv_scale 509 507 if self.inv_percent is None: … … 512 510 inv_percent = 'Error' 513 511 else: 514 inv_percent = format_number(self.inv_percent *100)+ '%'515 x_center = 20 512 inv_percent = format_number(self.inv_percent * 100) + '%' 513 x_center = 20 516 514 y_center = -h 517 515 gc.DrawText(inv_percent, x_center, y_center) 518 gc.Scale(self.inv_scale, 1.0) 516 gc.Scale(self.inv_scale, 1.0) 519 517 gc.DrawPath(path) 520 518 gc.PopState() 521 519 # restore saved state 522 # Draw rectangle for high invariant523 gc.PushState() 524 y_origine += 20 525 gc.DrawText("Q* from High-Q ", x_origine, y_origine) 526 # define the position of the new rectangle527 x_center = x_origine + RECTANGLE_WIDTH * self.high_scale /2 + w + 10520 # Draw rectangle for high invariant 521 gc.PushState() 522 y_origine += 20 523 gc.DrawText("Q* from High-Q ", x_origine, y_origine) 524 # define the position of the new rectangle 525 x_center = x_origine + RECTANGLE_WIDTH * self.high_scale / 2 + w + 10 528 526 y_center = y_origine + h 529 527 gc.Translate(x_center, y_center) 530 gc.SetBrush(wx.Brush(self.extrapolation_color_high)) 528 gc.SetBrush(wx.Brush(self.extrapolation_color_high)) 531 529 # increase scale by self.high_scale 532 530 if self.high_inv_percent is None: … … 535 533 high_percent = 'Error' 536 534 else: 537 high_percent = format_number(self.high_inv_percent *100)+ '%'535 high_percent = format_number(self.high_inv_percent * 100) + '%' 538 536 x_center = 20 539 537 y_center = -h 540 538 gc.DrawText(high_percent, x_center, y_center) 541 542 gc.Scale(self.high_scale, 1.0) 539 540 gc.Scale(self.high_scale, 1.0) 543 541 gc.DrawPath(path) 544 542 gc.PopState() -
src/sas/perspectives/invariant/invariant_panel.py
r1128bd31 rc4f6851 802 802 for key in comp_state: 803 803 value = comp_state[key] 804 try: 805 exec "self.%s.SetValue(str(%s))" % (key, value) 806 except TypeError: 807 exec "self.%s.SetValue(%s)" % (key, value) 808 except: 809 logging.error(sys.exc_value) 804 self._set_property_value(key, value) 810 805 811 806 self.compute_invariant(event=None) … … 815 810 # set the inputs and boxes 816 811 value = current_state[key] 817 try: 818 exec 'self.%s.SetValue(str(%s))' % (key, value) 819 except TypeError: 820 exec 'self.%s.SetValue(%s)' % (key, value) 821 except: 822 logging.error(sys.exc_value) 812 self._set_property_value(key, value) 823 813 824 814 self._enable_high_q_section(event=None) … … 828 818 self.state.state_num = state_num 829 819 820 def _set_property_value(self, key, value): 821 """ 822 Set a property value 823 :param key: property name 824 :param value: value of the property 825 """ 826 try: 827 attr = getattr(self, key) 828 attr.SetValue(str(value)) 829 except: 830 logging.error("Invariant state: %s", sys.exc_value) 830 831 831 832 def get_bookmark_by_num(self, num=None): … … 850 851 for key in comp_state: 851 852 value = comp_state[key] 852 try: 853 exec "self.%s.SetValue(str(%s))" % (key, value) 854 except TypeError: 855 exec "self.%s.SetValue(%s)" % (key, value) 856 except: 857 logging.error(sys.exc_value) 853 self._set_property_value(key, value) 858 854 859 855 self.compute_invariant(event=None) … … 861 857 for key in current_state: 862 858 value = current_state[key] 863 try: 864 exec 'self.%s.SetValue(str(%s))' % (key, value) 865 except TypeError: 866 exec 'self.%s.SetValue(%s)' % (key, value) 867 except: 868 logging.error(sys.exc_value) 859 self._set_property_value(key, value) 869 860 self.state.saved_state = copy.deepcopy(current_state) 870 861 … … 925 916 if value == None or value.lstrip().rstrip() == '': 926 917 value = 'None' 927 exec 'self.state.%s = %s' % (name, value)928 exec "self.state.saved_state['%s'] = %s" % (name,value)918 setattr(self.state, name, str(value)) 919 self.state.saved_state[name] = str(value) 929 920 930 921 # set the count part of radio button clicked … … 937 928 name = title 938 929 value = False 939 exec "self.state.saved_state['%s'] = %s" % (name,value)930 self.state.saved_state[name] = str(value) 940 931 941 932 # Instead of changing the future, create a new future. … … 1059 1050 logging.error(sys.exc_value) 1060 1051 1061 # Instead of changing the future, create a new future.1062 #max_state_num = len(self.state.state_list)-11063 #self.state.saved_state['state_num'] = max_state_num1064 1065 1052 # try to add new state of the text changes in the state_list 1066 1053 try: 1067 1054 if value.strip() == None: 1068 1055 value = '' 1069 exec "self.state.%s = '%s'" % (name, value)1070 exec "self.state.saved_state['%s'] = '%s'" % (name,value)1071 exec "self.state.input_list['%s'] = '%s'" % (name,value)1056 setattr(self.state, name, str(value)) 1057 self.state.saved_state[name] = str(value) 1058 self.state.input_list[name] = str(value) 1072 1059 if not self.is_power_out: 1073 1060 if name != 'power_low_tcl' and name != 'power_high_tcl': 1074 1061 self.state.saved_state['state_num'] += 1 1075 1062 self.state.state_num = self.state.saved_state['state_num'] 1076 #copy.deepcopy(self.state.saved_state) 1077 self.state.state_list[str(self.state.state_num)] = \ 1078 self.state.clone_state() 1063 self.state.state_list[str(self.state.state_num)] = self.state.clone_state() 1079 1064 except: 1080 1065 logging.error(sys.exc_value) 1081 1066 1082 #event.Skip()1083 1067 self._set_undo_flag(True) 1084 1068 self._set_redo_flag(False) … … 1098 1082 value = str(obj.GetValue()) 1099 1083 try: 1100 exec "self.state.saved_state['%s'] = '%s'" % (name, value) 1101 self.state.state_list[str(self.state.state_num)] = \ 1102 self.state.clone_state() 1084 self.state.saved_state[name] = str(value) 1085 self.state.state_list[str(self.state.state_num)] = self.state.clone_state() 1103 1086 except: 1104 1087 logging.error(sys.exc_value) 1105 #if event != None: event.Skip()1106 1088 1107 1089 def _get_input_list(self): -
src/sas/perspectives/invariant/invariant_state.py
rb9a5f0e r78a205a 1 1 """ 2 State class for the invariant UI 2 3 """ 3 4 4 # import time5 # import time 5 6 import os 6 7 import sys … … 8 9 import copy 9 10 import sas.dataloader 10 # from xml.dom.minidom import parse11 # from xml.dom.minidom import parse 11 12 from lxml import etree 12 13 from sas.dataloader.readers.cansas_reader import Reader as CansasReader … … 20 21 21 22 # default state 22 list= {'file': 'None',23 'compute_num':0,24 'state_num':0,25 'is_time_machine':False,26 'background_tcl':0.0,27 'scale_tcl':1.0,28 'contrast_tcl':1.0,29 'porod_constant_tcl':'',30 'npts_low_tcl':10,31 'npts_high_tcl':10,32 'power_high_tcl':4.0,33 'power_low_tcl': 4.0,34 'enable_high_cbox':False,35 'enable_low_cbox':False,36 'guinier': True,37 'power_law_high': False,38 'power_law_low': False,39 'fit_enable_high': False,40 'fit_enable_low': False,41 'fix_enable_high':True,42 'fix_enable_low':True,43 'volume_tcl':'',44 'volume_err_tcl':'',45 'surface_tcl':'',46 'surface_err_tcl':''}47 # list of states: This list will be filled as panel 23 DEFAULT_STATE = {'file': 'None', 24 'compute_num':0, 25 'state_num':0, 26 'is_time_machine':False, 27 'background_tcl':0.0, 28 'scale_tcl':1.0, 29 'contrast_tcl':1.0, 30 'porod_constant_tcl':'', 31 'npts_low_tcl':10, 32 'npts_high_tcl':10, 33 'power_high_tcl':4.0, 34 'power_low_tcl': 4.0, 35 'enable_high_cbox':False, 36 'enable_low_cbox':False, 37 'guinier': True, 38 'power_law_high': False, 39 'power_law_low': False, 40 'fit_enable_high': False, 41 'fit_enable_low': False, 42 'fix_enable_high':True, 43 'fix_enable_low':True, 44 'volume_tcl':'', 45 'volume_err_tcl':'', 46 'surface_tcl':'', 47 'surface_err_tcl':''} 48 # list of states: This list will be filled as panel 48 49 # init and the number of states increases 49 50 state_list = {} 50 51 bookmark_list = {} 51 # list of input parameters (will be filled up on panel init) used by __str__ 52 # list of input parameters (will be filled up on panel init) used by __str__ 52 53 input_list = {'background_tcl':0, 53 'scale_tcl':0,54 'contrast_tcl':0,55 'porod_constant_tcl':'',56 'npts_low_tcl':0,57 'npts_high_tcl':0,58 'power_high_tcl':0,59 'power_low_tcl': 0}60 # list of output parameters (order sensitive) used by __str__ 61 output_list = [["qstar_low", 62 ["qstar_low_err", 63 ["qstar_low_percent", 64 ["qstar", 65 ["qstar_err", 66 ["qstar_percent", 67 ["qstar_high", 68 ["qstar_high_err", 54 'scale_tcl':0, 55 'contrast_tcl':0, 56 'porod_constant_tcl':'', 57 'npts_low_tcl':0, 58 'npts_high_tcl':0, 59 'power_high_tcl':0, 60 'power_low_tcl': 0} 61 # list of output parameters (order sensitive) used by __str__ 62 output_list = [["qstar_low", "Q* from low Q extrapolation [1/(cm*A)]"], 63 ["qstar_low_err", "dQ* from low Q extrapolation"], 64 ["qstar_low_percent", "Q* percent from low Q extrapolation"], 65 ["qstar", "Q* from data [1/(cm*A)]"], 66 ["qstar_err", "dQ* from data"], 67 ["qstar_percent", "Q* percent from data"], 68 ["qstar_high", "Q* from high Q extrapolation [1/(cm*A)]"], 69 ["qstar_high_err", "dQ* from high Q extrapolation"], 69 70 ["qstar_high_percent", "Q* percent from low Q extrapolation"], 70 ["qstar_total", 71 ["qstar_total_err", 72 ["volume", 73 ["volume_err", 74 ["surface", 75 ["surface_err", 76 77 71 ["qstar_total", "total Q* [1/(cm*A)]"], 72 ["qstar_total_err", "total dQ*"], 73 ["volume", "volume fraction"], 74 ["volume_err", "volume fraction error"], 75 ["surface", "specific surface"], 76 ["surface_err", "specific surface error"]] 77 78 78 79 79 80 class InvariantState(object): … … 85 86 Default values 86 87 """ 87 # Input 88 self.file 88 # Input 89 self.file = None 89 90 self.data = Data1D(x=[], y=[], dx=None, dy=None) 90 self.theory_lowQ = 91 self.theory_lowQ = Data1D(x=[], y=[], dy=None) 91 92 self.theory_lowQ.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM 92 93 self.theory_highQ = Data1D(x=[], y=[], dy=None) 93 94 self.theory_highQ.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM 94 # self.is_time_machine = False95 self.saved_state = list95 # self.is_time_machine = False 96 self.saved_state = DEFAULT_STATE 96 97 self.state_list = state_list 97 98 self.bookmark_list = bookmark_list 98 99 self.input_list = input_list 99 100 self.output_list = output_list 100 101 101 102 self.compute_num = 0 102 103 self.state_num = 0 103 104 self.timestamp = ('00:00:00', '00/00/0000') 104 105 self.container = None 105 # plot image106 # plot image 106 107 self.wximbmp = None 107 108 # report_html strings 108 109 import sas.perspectives.invariant as invariant 109 110 path = invariant.get_data_path(media='media') 110 path_report_html = os.path.join(path, "report_template.html")111 html_template = open(path_report_html, "r")111 path_report_html = os.path.join(path, "report_template.html") 112 html_template = open(path_report_html, "r") 112 113 self.template_str = html_template.read() 113 114 self.report_str = self.template_str 114 # self.report_str_save = None115 # self.report_str_save = None 115 116 html_template.close() 116 117 117 118 def __str__(self): 118 119 """ 119 120 Pretty print 120 121 121 122 : return: string representing the state 122 123 """ … … 132 133 state += "State No.: %d \n" % state_num 133 134 state += "\n=== Inputs ===\n" 134 135 135 136 # text ctl general inputs ( excluding extrapolation text ctl) 136 for key, value in self.input_list.iteritems(): 137 for key, value in self.input_list.iteritems(): 137 138 if value == '': 138 139 continue 139 key_split = key.split('_') 140 max_ind = len(key_split) -1141 if key_split[max_ind] == 'tcl': 140 key_split = key.split('_') 141 max_ind = len(key_split) - 1 142 if key_split[max_ind] == 'tcl': 142 143 name = "" 143 144 if key_split[1] == 'low' or key_split[1] == 'high': … … 146 147 name += " %s" % key_split[ind] 147 148 state += "%s: %s\n" % (name.lstrip(" "), value) 148 149 # other input parameters 149 150 # other input parameters 150 151 extra_lo = compute_state['enable_low_cbox'] 151 152 if compute_state['enable_low_cbox']: … … 157 158 if compute_state['enable_high_cbox']: 158 159 extra_hi = 'Power law' 159 state += "\nExtrapolation: High=%s; Low=%s\n" % (extra_hi, extra_lo)160 state += "\nExtrapolation: High=%s; Low=%s\n" % (extra_hi, extra_lo) 160 161 low_off = False 161 162 high_off = False 162 for key, value in self.input_list.iteritems(): 163 key_split = key.split('_') 164 max_ind = len(key_split) - 1 165 if key_split[max_ind] == 'tcl': 166 name = "" 163 for key, value in self.input_list.iteritems(): 164 key_split = key.split('_') 165 max_ind = len(key_split) - 1 166 if key_split[max_ind] == 'tcl': 167 name = "" 167 168 # check each buttons whether or not ON or OFF 168 169 if key_split[1] == 'low' or key_split[1] == 'high': 169 170 if not compute_state['enable_low_cbox'] and \ 170 key_split[max_ind -1] == 'low':171 key_split[max_ind - 1] == 'low': 171 172 low_off = True 172 continue 173 continue 173 174 elif not compute_state['enable_high_cbox'] and \ 174 key_split[max_ind -1] == 'high':175 key_split[max_ind - 1] == 'high': 175 176 high_off = True 176 177 continue 177 178 elif extra_lo == 'Guinier' and key_split[0] == 'power' and \ 178 key_split[max_ind -1] == 'low':179 key_split[max_ind - 1] == 'low': 179 180 continue 180 181 for ind in range(0, max_ind): 181 182 name += " %s" % key_split[ind] 182 183 name = name.lstrip(" ") 183 if name == "power low" 184 if name == "power low": 184 185 if compute_state['fix_enable_low']: 185 186 name += ' (Fixed)' 186 187 else: 187 188 name += ' (Fitted)' 188 if name == "power high" 189 if name == "power high": 189 190 if compute_state['fix_enable_high']: 190 191 name += ' (Fixed)' … … 195 196 state += "\n=== Outputs ===" 196 197 for item in output_list: 197 item_split = item[0].split('_') 198 item_split = item[0].split('_') 198 199 # Exclude the extrapolation that turned off 199 200 if len(item_split) > 1: … … 204 205 max_ind = len(item_split) - 1 205 206 value = None 206 try:207 if hasattr(self.container, item[0]): 207 208 # Q* outputs 208 exec "value = self.container.%s\n" % item[0]209 e xcept:209 value = getattr(self.container, item[0]) 210 else: 210 211 # other outputs than Q* 211 212 name = item[0] + "_tcl" 212 213 if name in self.saved_state.keys(): 213 exec "value = self.saved_state['%s']" % name214 215 # Exclude the outputs w/'' 214 value = self.saved_state[name] 215 216 # Exclude the outputs w/'' 216 217 if value == '': 217 continue 218 continue 218 219 # Error outputs 219 220 if item_split[max_ind] == 'err': … … 221 222 # Percentage outputs 222 223 elif item_split[max_ind] == 'percent': 223 try: 224 value = float(value) * 100 225 except: 226 pass 224 value = float(value) * 100 227 225 state += "(%s %s)" % (format_number(value), '%') 228 226 # Outputs 229 227 else: 230 state += "\n%s: %s " % (item[1], 231 format_number(value, high=True))228 state += "\n%s: %s " % (item[1], 229 format_number(value, high=True)) 232 230 # Include warning msg 233 231 if self.container is not None: … … 244 242 """ 245 243 Writes the state of the InversionControl panel to file, as XML. 246 244 247 245 Compatible with standalone writing, or appending to an 248 246 already existing XML document. In that case, the XML document 249 is required. An optional entry node in the XML document 247 is required. An optional entry node in the XML document 250 248 may also be given. 251 249 252 250 : param file: file to write to 253 251 : param doc: XML document object [optional] 254 : param entry_node: XML node within the XMLdocument at which we will append the data [optional]252 : param entry_node: XML node within the document at which we will append the data [optional] 255 253 """ 256 254 # TODO: Get this to work … … 261 259 if doc is None: 262 260 impl = getDOMImplementation() 263 264 doc_type = impl.createDocumentType(INVNODE_NAME, "1.0", "1.0") 265 261 262 doc_type = impl.createDocumentType(INVNODE_NAME, "1.0", "1.0") 263 266 264 newdoc = impl.createDocument(None, INVNODE_NAME, doc_type) 267 265 top_element = newdoc.documentElement … … 274 272 else: 275 273 entry_node.appendChild(top_element) 276 274 277 275 attr = newdoc.createAttribute("version") 278 276 attr.nodeValue = '1.0' 279 277 top_element.setAttributeNode(attr) 280 278 281 279 # File name 282 280 element = newdoc.createElement("filename") … … 286 284 element.appendChild(newdoc.createTextNode(str(file))) 287 285 top_element.appendChild(element) 288 286 289 287 element = newdoc.createElement("timestamp") 290 288 element.appendChild(newdoc.createTextNode(time.ctime(timestamp))) … … 293 291 element.setAttributeNode(attr) 294 292 top_element.appendChild(element) 295 293 296 294 # Current state 297 295 state = newdoc.createElement("state") 298 296 top_element.appendChild(state) 299 300 for name, value in self.saved_state.iteritems():297 298 for name, value in self.saved_state.iteritems(): 301 299 element = newdoc.createElement(str(name)) 302 300 element.appendChild(newdoc.createTextNode(str(value))) 303 301 state.appendChild(element) 304 302 305 303 # State history list 306 304 history = newdoc.createElement("history") 307 305 top_element.appendChild(history) 308 306 309 307 for name, value in self.state_list.iteritems(): 310 308 history_element = newdoc.createElement('state_' + str(name)) 311 for state_name, state_value in value.iteritems():309 for state_name, state_value in value.iteritems(): 312 310 state_element = newdoc.createElement(str(state_name)) 313 311 child = newdoc.createTextNode(str(state_value)) 314 312 state_element.appendChild(child) 315 313 history_element.appendChild(state_element) 316 # history_element.appendChild(state_list_element)314 # history_element.appendChild(state_list_element) 317 315 history.appendChild(history_element) 318 316 319 317 # Bookmarks bookmark_list[self.bookmark_num] = [\ 320 # my_time,date,state,comp_state]318 # my_time,date,state,comp_state] 321 319 bookmark = newdoc.createElement("bookmark") 322 320 top_element.appendChild(bookmark) 323 item_list = ['time', 'date','state','comp_state']321 item_list = ['time', 'date', 'state', 'comp_state'] 324 322 for name, value_list in self.bookmark_list.iteritems(): 325 element = newdoc.createElement('mark_' + str(name))326 _, date,state,comp_state = value_list323 element = newdoc.createElement('mark_' + str(name)) 324 _, date, state, comp_state = value_list 327 325 time_element = newdoc.createElement('time') 328 326 time_element.appendChild(newdoc.createTextNode(str(value_list[0]))) … … 354 352 else: 355 353 return newdoc 356 354 357 355 def fromXML(self, file=None, node=None): 358 356 """ 359 357 Load invariant states from a file 360 358 361 359 : param file: .inv file 362 : param node: node of a XML document to read from 360 : param node: node of a XML document to read from 363 361 """ 364 362 if file is not None: … … 366 364 msg += " format for invariant files" 367 365 raise RuntimeError, msg 368 366 369 367 if node.get('version')\ 370 368 and node.get('version') == '1.0': … … 384 382 msg += " timestamp\n %s" % sys.exc_value 385 383 logging.error(msg) 386 384 387 385 # Parse bookmarks 388 386 entry_bookmark = get_content('ns:bookmark', node) … … 391 389 temp_state = {} 392 390 temp_bookmark = {} 393 entry = get_content('ns:mark_%s' % ind, entry_bookmark) 394 391 entry = get_content('ns:mark_%s' % ind, entry_bookmark) 392 395 393 if entry is not None: 396 394 my_time = get_content('ns:time', entry) … … 399 397 val_date = str(date.text.strip()) 400 398 state_entry = get_content('ns:state', entry) 401 for item in list: 402 399 for item in DEFAULT_STATE: 403 400 input_field = get_content('ns:%s' % item, state_entry) 404 401 val = str(input_field.text.strip()) 405 402 if input_field is not None: 406 try: 407 exec "temp_state['%s'] = %s" % (item, val) 408 except: 409 exec "temp_state['%s'] = '%s'" % (item, val) 403 temp_state[item] = val 410 404 comp_entry = get_content('ns:comp_state', entry) 411 412 for item in list:405 406 for item in DEFAULT_STATE: 413 407 input_field = get_content('ns:%s' % item, comp_entry) 414 408 val = str(input_field.text.strip()) 415 409 if input_field is not None: 416 try: 417 exec "temp_bookmark['%s'] = %s" % (item, val) 418 except: 419 exec "temp_bookmark['%s'] = '%s'" % (item, val) 410 temp_bookmark[item] = val 420 411 try: 421 cmd = "self.bookmark_list[%s] = [val_time," 422 cmd += "val_date,temp_state,temp_bookmark]" 423 exec cmd % ind 412 self.bookmark_list[ind] = [val_time, val_date, temp_state, temp_bookmark] 424 413 except: 425 414 raise "missing components of bookmarks..." … … 429 418 for ind in range(0, len(entry_history)): 430 419 temp_state = {} 431 entry = get_content('ns:state_%s' % ind, entry_history) 420 entry = get_content('ns:state_%s' % ind, entry_history) 432 421 433 422 if entry is not None: 434 for item in list:435 input_field = get_content('ns:%s' % item, entry 423 for item in DEFAULT_STATE: 424 input_field = get_content('ns:%s' % item, entry) 436 425 val = str(input_field.text.strip()) 437 438 426 if input_field is not None: 439 try: 440 exec "temp_state['%s'] = %s" % (item, val) 441 except: 442 exec "temp_state['%s'] = '%s'" % (item, val) 443 finally: 444 exec "self.state_list['%s'] = temp_state" % ind 427 temp_state[item] = val 428 self.state_list[ind] = temp_state 429 445 430 # Parse current state (ie, saved_state) 446 entry = get_content('ns:state', node) 431 entry = get_content('ns:state', node) 447 432 if entry is not None: 448 for item in list:433 for item in DEFAULT_STATE: 449 434 input_field = get_content('ns:%s' % item, entry) 450 435 val = str(input_field.text.strip()) … … 452 437 self.set_saved_state(name=item, value=val) 453 438 self.file = file_name 454 439 455 440 def set_report_string(self): 456 441 """ 457 Get the values (strings) from __str__ for report 442 Get the values (strings) from __str__ for report 458 443 """ 459 444 strings = self.__str__() 460 445 461 446 # default string values 462 for num in range 447 for num in range(1, 19): 463 448 exec "s_%s = 'NA'" % str(num) 464 449 lines = strings.split('\n') … … 491 476 s_10 = item[1] 492 477 elif item[0] == "volume fraction": 493 val =item[1].split("+-")[0].strip()478 val = item[1].split("+-")[0].strip() 494 479 error = item[1].split("+-")[1].strip() 495 480 s_17 = val + " ± " + error … … 499 484 s_18 = val + " ± " + error 500 485 elif item[0].split("(")[0].strip() == "power low": 501 s_11 = item[0] +" ="+item[1]486 s_11 = item[0] + " =" + item[1] 502 487 elif item[0].split("(")[0].strip() == "power high": 503 s_12 = item[0] +" ="+item[1]488 s_12 = item[0] + " =" + item[1] 504 489 elif item[0].split("[")[0].strip() == "Q* from low Q extrapolation": 505 # looks messy but this way the symbols +_ and % work on html490 # looks messy but this way the symbols +_ and % work on html 506 491 val = item[1].split("+-")[0].strip() 507 492 error = item[1].split("+-")[1].strip() … … 532 517 533 518 # make plot image 534 self.set_plot_state(extra_high=bool_0[1], extra_low=bool_1[1])519 self.set_plot_state(extra_high=bool_0[1], extra_low=bool_1[1]) 535 520 # get ready for report with setting all the html strings 536 521 self.report_str = str(self.template_str) % (s_1, s_2, 537 s_3, s_4, s_5, s_6, s_7, s_8,538 s_9, s_10, s_11, s_12, s_13, s_14, s_15,539 s_16, s_17, s_18, file_name, "%s")522 s_3, s_4, s_5, s_6, s_7, s_8, 523 s_9, s_10, s_11, s_12, s_13, s_14, s_15, 524 s_16, s_17, s_18, file_name, "%s") 540 525 541 526 def _check_html_format(self, name): … … 545 530 if name.count('%'): 546 531 name = name.replace('%', '%') 547 532 548 533 return name 549 534 550 535 def set_saved_state(self, name, value): 551 536 """ 552 Set the state list 553 537 Set the state list 538 554 539 : param name: name of the state component 555 540 : param value: value of the state component 556 541 """ 557 rb_list = [['power_law_low','guinier'], 558 ['fit_enable_low','fix_enable_low'], 559 ['fit_enable_high','fix_enable_high']] 560 561 try: 562 if value == None or value.lstrip().rstrip() == '': 563 exec "self.%s = '%s'" % (name, value) 564 exec "self.saved_state['%s'] = '%s'" % (name, value) 565 else: 566 exec 'self.%s = %s' % (name, value) 567 exec "self.saved_state['%s'] = %s" % (name, value) 568 # set the count part of radio button clicked 569 # False for the saved_state 570 for title, content in rb_list: 571 if name == title: 572 name = content 573 value = False 574 elif name == content: 575 name = title 576 value = False 577 exec "self.saved_state['%s'] = '%s'" % (name, value) 578 self.state_num = self.saved_state['state_num'] 579 except: 580 pass 542 rb_list = [['power_law_low', 'guinier'], 543 ['fit_enable_low', 'fix_enable_low'], 544 ['fit_enable_high', 'fix_enable_high']] 545 546 self.name = value 547 self.saved_state[name] = value 548 # set the count part of radio button clicked 549 # False for the saved_state 550 for title, content in rb_list: 551 if name == title: 552 name = content 553 value = False 554 elif name == content: 555 name = title 556 value = False 557 self.saved_state[name] = value 558 self.state_num = self.saved_state['state_num'] 581 559 582 560 def set_plot_state(self, extra_high=False, extra_low=False): … … 584 562 Build image state that wx.html understand 585 563 by plotting, putting it into wx.FileSystem image object 586 564 587 565 : extrap_high,extra_low: low/high extrapolations 588 566 are possible extra-plots … … 593 571 from matplotlib.backends.backend_agg import FigureCanvasAgg 594 572 595 # we use simple plot, not plotpanel596 # make matlab figure573 # we use simple plot, not plotpanel 574 # make matlab figure 597 575 fig = plt.figure() 598 576 fig.set_facecolor('w') 599 577 graph = fig.add_subplot(111) 600 578 601 # data plot579 # data plot 602 580 graph.errorbar(self.data.x, self.data.y, yerr=self.data.dy, fmt='o') 603 # low Q extrapolation fit plot581 # low Q extrapolation fit plot 604 582 if not extra_low == 'False': 605 graph.plot(self.theory_lowQ.x, self.theory_lowQ.y)606 # high Q extrapolation fit plot583 graph.plot(self.theory_lowQ.x, self.theory_lowQ.y) 584 # high Q extrapolation fit plot 607 585 if not extra_high == 'False': 608 graph.plot(self.theory_highQ.x, self.theory_highQ.y)586 graph.plot(self.theory_highQ.x, self.theory_highQ.y) 609 587 graph.set_xscale("log", nonposx='clip') 610 588 graph.set_yscale("log", nonposy='clip') 611 graph.set_xlabel('$\\rm{Q}(\\AA^{-1})$', fontsize =12)612 graph.set_ylabel('$\\rm{Intensity}(cm^{-1})$', fontsize =12)589 graph.set_xlabel('$\\rm{Q}(\\AA^{-1})$', fontsize=12) 590 graph.set_ylabel('$\\rm{Intensity}(cm^{-1})$', fontsize=12) 613 591 canvas = FigureCanvasAgg(fig) 614 # actually make image592 # actually make image 615 593 canvas.draw() 616 617 # make python.Image object618 # size594 595 # make python.Image object 596 # size 619 597 w, h = canvas.get_width_height() 620 # convert to wx.Image621 wximg = wx.EmptyImage(w, h)622 # wxim.SetData(img.convert('RGB').tostring() )623 wximg.SetData(canvas.tostring_rgb()) 624 # get the dynamic image for the htmlwindow598 # convert to wx.Image 599 wximg = wx.EmptyImage(w, h) 600 # wxim.SetData(img.convert('RGB').tostring() ) 601 wximg.SetData(canvas.tostring_rgb()) 602 # get the dynamic image for the htmlwindow 625 603 wximgbmp = wx.BitmapFromImage(wximg) 626 # store the image in wx.FileSystem Object604 # store the image in wx.FileSystem Object 627 605 wx.FileSystem.AddHandler(wx.MemoryFSHandler()) 628 606 # use wx.MemoryFSHandler 629 607 self.imgRAM = wx.MemoryFSHandler() 630 # AddFile, image can be retrieved with 'memory:filename'608 # AddFile, image can be retrieved with 'memory:filename' 631 609 self.imgRAM.AddFile('img_inv.png', wximgbmp, wx.BITMAP_TYPE_PNG) 632 610 633 611 self.wximgbmp = 'memory:img_inv.png' 634 612 self.image = fig … … 638 616 Class to load a .inv invariant file 639 617 """ 640 # # File type618 # # File type 641 619 type_name = "Invariant" 642 643 # # Wildcards620 621 # # Wildcards 644 622 type = ["Invariant file (*.inv)|*.inv", 645 623 "SASView file (*.svs)|*.svs"] 646 # # List of allowed extensions647 ext = ['.inv', '.INV', '.svs', 'SVS'] 648 624 # # List of allowed extensions 625 ext = ['.inv', '.INV', '.svs', 'SVS'] 626 649 627 def __init__(self, call_back, cansas=True): 650 628 """ 651 629 Initialize the call-back method to be called 652 630 after we load a file 653 631 654 632 : param call_back: call-back method 655 633 : param cansas: True = files will be written/read in CanSAS format 656 False = write CanSAS format 657 """ 658 # # Call back method to be executed after a file is read634 False = write CanSAS format 635 """ 636 # # Call back method to be executed after a file is read 659 637 self.call_back = call_back 660 # # CanSAS format flag638 # # CanSAS format flag 661 639 self.cansas = cansas 662 640 self.state = None 663 641 664 642 def read(self, path): 665 """ 643 """ 666 644 Load a new invariant state from file 667 645 668 646 : param path: file path 669 647 : return: None … … 673 651 else: 674 652 return self._read_standalone(path) 675 653 676 654 def _read_standalone(self, path): 677 """ 655 """ 678 656 Load a new invariant state from file. 679 657 The invariant node is assumed to be the top element. 680 658 681 659 : param path: file path 682 660 : return: None … … 686 664 687 665 state.fromXML(file=path) 688 666 689 667 # Call back to post the new state 690 668 self.call_back(state) 691 669 return None 692 670 693 671 def _parse_state(self, entry): 694 672 """ 695 673 Read an invariant result from an XML node 696 697 : param entry: XML node to read from 674 675 : param entry: XML node to read from 698 676 : return: InvariantState object 699 677 """ … … 710 688 msg = "XML document does not contain invariant" 711 689 msg += " information.\n %s" % sys.exc_value 712 logging.info(msg) 690 logging.info(msg) 713 691 return state 714 692 715 693 def _read_cansas(self, path): 716 """ 694 """ 717 695 Load data and invariant information from a CanSAS XML file. 718 696 719 697 : param path: file path 720 : return: Data1D object if a single SASentry was found, 698 : return: Data1D object if a single SASentry was found, 721 699 or a list of Data1D objects if multiple entries were found, 722 700 or None of nothing was found … … 726 704 output = [] 727 705 if os.path.isfile(path): 728 basename 706 basename = os.path.basename(path) 729 707 root, extension = os.path.splitext(basename) 730 708 731 709 if extension.lower() in self.ext or \ 732 710 extension.lower() == '.xml': 733 711 tree = etree.parse(path, parser=etree.ETCompatXMLParser()) 734 712 735 713 # Check the format version number 736 # Specifying the namespace will take care of 737 # the file format version 714 # Specifying the namespace will take care of 715 # the file format version 738 716 root = tree.getroot() 739 717 740 718 entry_list = root.xpath('/ns:SASroot/ns:SASentry', 741 719 namespaces={'ns': CANSAS_NS}) 742 720 743 721 for entry in entry_list: 744 722 745 723 sas_entry, _ = self._parse_entry(entry) 746 724 invstate = self._parse_state(entry) 747 748 # invstate could be None when .svs file is loaded749 # in this case, skip appending to output725 726 # invstate could be None when .svs file is loaded 727 # in this case, skip appending to output 750 728 if invstate != None: 751 729 sas_entry.meta_data['invstate'] = invstate … … 762 740 self.state = output[0].meta_data['invstate'] 763 741 self.call_back(state=output[0].meta_data['invstate'], 764 datainfo =output[0])742 datainfo=output[0]) 765 743 return output[0] 766 744 else: 767 return output 768 745 return output 746 769 747 def get_state(self): 770 748 return self.state 771 749 772 750 def write(self, filename, datainfo=None, invstate=None): 773 751 """ 774 752 Write the content of a Data1D as a CanSAS XML file 775 753 776 754 : param filename: name of the file to write 777 755 : param datainfo: Data1D object … … 780 758 # Sanity check 781 759 if self.cansas == True: 782 doc = self.write_toXML(datainfo, invstate)760 doc = self.write_toXML(datainfo, invstate) 783 761 # Write the XML document 784 762 fd = open(filename, 'w') … … 787 765 else: 788 766 invstate.toXML(file=filename) 789 767 790 768 def write_toXML(self, datainfo=None, state=None): 791 769 """ 792 770 Write toXML, a helper for write() 793 771 794 772 : return: xml doc 795 773 """ 796 774 if datainfo is None: 797 datainfo = sas.dataloader.data_info.Data1D(x=[], y=[]) 775 datainfo = sas.dataloader.data_info.Data1D(x=[], y=[]) 798 776 elif not issubclass(datainfo.__class__, sas.dataloader.data_info.Data1D): 799 777 msg = "The cansas writer expects a Data1D" 800 778 msg += " instance: %s" % str(datainfo.__class__.__name__) 801 779 raise RuntimeError, msg 802 # make sure title and data run is filled up.780 # make sure title and data run is filled up. 803 781 if datainfo.title == None or datainfo.title == '': 804 782 datainfo.title = datainfo.name 805 if datainfo.run_name == None or datainfo.run_name == {}: 783 if datainfo.run_name == None or datainfo.run_name == {}: 806 784 datainfo.run = [str(datainfo.name)] 807 785 datainfo.run_name[0] = datainfo.name … … 810 788 # Add the invariant information to the XML document 811 789 if state is not None: 812 doc = state.toXML(datainfo.name, doc=doc, entry_node=sasentry)790 doc = state.toXML(datainfo.name, doc=doc, entry_node=sasentry) 813 791 return doc 814 792 -
src/sas/perspectives/invariant/invariant_widgets.py
r79492222 r78a205a 1 2 3 4 1 ################################################################################ 5 # This software was developed by the University of Tennessee as part of the6 # Distributed Data Analysis of Neutron Scattering Experiments (DANSE)7 # project funded by the US National Science Foundation.2 # This software was developed by the University of Tennessee as part of the 3 # Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 4 # project funded by the US National Science Foundation. 8 5 # 9 # See the license text in license.txt6 # See the license text in license.txt 10 7 # 11 # copyright 2009, University of Tennessee8 # copyright 2009, University of Tennessee 12 9 ################################################################################ 13 14 10 15 11 import wx … … 23 19 ScrolledPanel.__init__(self, *args, **kwds) 24 20 self.SetupScrolling() 25 21 26 22 class InvTextCtrl(wx.TextCtrl): 27 23 """ … … 31 27 def __init__(self, *args, **kwds): 32 28 wx.TextCtrl.__init__(self, *args, **kwds) 33 # # Set to True when the mouse is clicked while34 # the whole string is selected29 # # Set to True when the mouse is clicked while 30 # the whole string is selected 35 31 self.full_selection = False 36 # # Call back for EVT_SET_FOCUS events32 # # Call back for EVT_SET_FOCUS events 37 33 _on_set_focus_callback = None 38 34 … … 40 36 self.Bind(wx.EVT_LEFT_UP, self._highlight_text) 41 37 self.Bind(wx.EVT_SET_FOCUS, self._on_set_focus) 42 38 43 39 def _on_set_focus(self, event): 44 40 """ 45 41 Catch when the text control is set in focus to highlight the whole 46 42 text if necessary 47 43 48 44 :param event: mouse event 49 45 """ 50 46 event.Skip() 51 47 self.full_selection = True 52 48 53 49 def _highlight_text(self, event): 54 50 """ 55 51 Highlight text of a TextCtrl only of no text has be selected 56 52 57 53 :param event: mouse event 58 54 """ 59 55 # Make sure the mouse event is available to other listeners 60 56 event.Skip() 61 control 57 control = event.GetEventObject() 62 58 if self.full_selection: 63 59 self.full_selection = False 64 60 # Check that we have a TextCtrl 65 61 if issubclass(control.__class__, wx.TextCtrl): 66 # Check whether text has been selected, 62 # Check whether text has been selected, 67 63 # if not, select the whole string 68 64 (start, end) = control.GetSelection() 69 65 if start == end: 70 66 control.SetSelection(-1, -1) 71 67 72 68 73 69 class OutputTextCtrl(wx.TextCtrl): 74 70 """ 75 71 Text control used to display outputs. 76 No editing allowed. The background is 72 No editing allowed. The background is 77 73 grayed out. User can't select text. 78 74 """ … … 81 77 self.SetEditable(False) 82 78 self.SetBackgroundColour(self.GetParent().GetBackgroundColour()) 83 79 84 80 # Bind to mouse event to avoid text highlighting 85 81 # The event will be skipped once the call-back 86 82 # is called. 87 83 88 84 self.Bind(wx.EVT_MOUSE_EVENTS, self._click) 89 85 90 86 91 87 def _click(self, event): 92 88 """ 93 89 Prevent further handling of the mouse event 94 90 by not calling Skip(). 95 """ 91 """ 96 92 pass 97 93 98 94 class DataDialog(wx.Dialog): 99 95 """ … … 110 106 self._choice_sizer = wx.GridBagSizer(5, 5) 111 107 self._panel = DialogPanel(self, style=wx.RAISED_BORDER, 112 size=(WIDTH-20, HEIGHT/3))108 size=(WIDTH - 20, HEIGHT / 3)) 113 109 self.SetSizer(self._sizer_main) 114 110 self.__do_layout(data_list, text=text) 115 111 self.Layout() 116 112 117 113 def __do_layout(self, data_list, text=''): 118 114 """ 119 115 layout the dialog 120 116 """ 121 # add text117 # add text 122 118 if text.strip() == "": 123 119 text = "This Perspective does not allow multiple data !\n" 124 120 text += "Please select only one Data.\n" 125 121 text_ctrl = wx.TextCtrl(self, -1, str(text), style=wx.TE_MULTILINE, 126 size=(-1, HEIGHT /3))122 size=(-1, HEIGHT / 3)) 127 123 text_ctrl.SetEditable(False) 128 self._sizer_txt.Add(text_ctrl , 1, wx.EXPAND|wx.ALL, 10)124 self._sizer_txt.Add(text_ctrl, 1, wx.EXPAND | wx.ALL, 10) 129 125 iy = 0 130 126 ix = 0 131 rbox = wx.RadioButton(self._panel, -1, str(data_list[0].name), 132 (10, 10), style=wx.RB_GROUP)127 rbox = wx.RadioButton(self._panel, -1, str(data_list[0].name), 128 (10, 10), style=wx.RB_GROUP) 133 129 rbox.SetValue(True) 134 130 self.list_of_ctrl.append((rbox, data_list[0])) 135 131 self._choice_sizer.Add(rbox, (iy, ix), (1, 1), 136 wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)132 wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 137 133 for i in range(1, len(data_list)): 138 134 iy += 1 139 rbox = wx.RadioButton(self._panel, -1, 135 rbox = wx.RadioButton(self._panel, -1, 140 136 str(data_list[i].name), (10, 10)) 141 137 rbox.SetValue(False) 142 138 self.list_of_ctrl.append((rbox, data_list[i])) 143 139 self._choice_sizer.Add(rbox, (iy, ix), 144 (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)140 (1, 1), wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 145 141 self._panel.SetSizer(self._choice_sizer) 146 # add sizer147 self._sizer_button.Add((20, 20), 1, wx.EXPAND |wx.ADJUST_MINSIZE, 0)142 # add sizer 143 self._sizer_button.Add((20, 20), 1, wx.EXPAND | wx.ADJUST_MINSIZE, 0) 148 144 button_cancel = wx.Button(self, wx.ID_CANCEL, "Cancel") 149 145 self._sizer_button.Add(button_cancel, 0, 150 wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)146 wx.LEFT | wx.RIGHT | wx.ADJUST_MINSIZE, 10) 151 147 button_OK = wx.Button(self, wx.ID_OK, "Ok") 152 148 button_OK.SetFocus() 153 149 self._sizer_button.Add(button_OK, 0, 154 wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)150 wx.LEFT | wx.RIGHT | wx.ADJUST_MINSIZE, 10) 155 151 static_line = wx.StaticLine(self, -1) 156 157 self._sizer_txt.Add(self._panel, 0, wx.EXPAND |wx.ALL, 5)158 self._sizer_main.Add(self._sizer_txt, 0, wx.EXPAND |wx.ALL, 5)152 153 self._sizer_txt.Add(self._panel, 0, wx.EXPAND | wx.ALL, 5) 154 self._sizer_main.Add(self._sizer_txt, 0, wx.EXPAND | wx.ALL, 5) 159 155 self._sizer_main.Add(static_line, 0, wx.EXPAND, 0) 160 self._sizer_main.Add(self._sizer_button, 0, wx.EXPAND|wx.ALL, 10) 161 162 156 self._sizer_main.Add(self._sizer_button, 0, wx.EXPAND | wx.ALL, 10) 157 163 158 def get_data(self): 164 159 """ … … 168 163 rbox, data = item 169 164 if rbox.GetValue(): 170 return data 171 172 173 174 165 return data -
src/sas/perspectives/invariant/report_dialog.py
re8bb5b6 r78a205a 1 1 2 2 ################################################################################ 3 # This software was developed by the University of Tennessee as part of the4 # Distributed Data Analysis of Neutron Scattering Experiments (DANSE)5 # project funded by the US National Science Foundation.3 # This software was developed by the University of Tennessee as part of the 4 # Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 5 # project funded by the US National Science Foundation. 6 6 # 7 # See the license text in license.txt7 # See the license text in license.txt 8 8 # 9 # copyright 2009, University of Tennessee9 # copyright 2009, University of Tennessee 10 10 ################################################################################ 11 11 12 12 """ 13 Dialog report panel to show and summarize the results of 13 Dialog report panel to show and summarize the results of 14 14 the invariant calculation. 15 15 """ 16 16 import wx 17 17 import os 18 import wx.html as html 19 18 import sys 19 import logging 20 20 21 from sas.guiframe.report_dialog import BaseReportDialog 21 22 22 23 class ReportDialog(BaseReportDialog): 23 24 """ 24 The report dialog box. 25 The report dialog box. 25 26 """ 26 27 def __init__(self, 27 28 def __init__(self, report_list, *args, **kwds): 28 29 """ 29 30 Initialization. The parameters added to Dialog are: 30 31 31 32 :param report_list: list of html_str, text_str, image 32 33 from invariant_state … … 46 47 Save 47 48 """ 48 # todo: complete saving fig file and as a txt file49 # todo: complete saving fig file and as a txt file 49 50 dlg = wx.FileDialog(self, "Choose a file", 50 51 wildcard=self.wild_card, 51 style=wx.SAVE |wx.OVERWRITE_PROMPT|wx.CHANGE_DIR)52 dlg.SetFilterIndex(0) #Set .html files to be default52 style=wx.SAVE | wx.OVERWRITE_PROMPT | wx.CHANGE_DIR) 53 dlg.SetFilterIndex(0) # Set .html files to be default 53 54 54 55 if dlg.ShowModal() != wx.ID_OK: … … 57 58 58 59 fName = dlg.GetPath() 59 ext_num = dlg.GetFilterIndex() 60 # set file extensions60 ext_num = dlg.GetFilterIndex() 61 # set file extensions 61 62 if ext_num == (0 + 2 * self.index_offset): 62 63 # TODO: Sort this case out … … 66 67 dlg.Destroy() 67 68 68 # pic (png) file path/name69 # pic (png) file path/name 69 70 pic_fname = os.path.splitext(fName)[0] + img_ext 70 71 # save the image for use with pdf writer … … 73 74 # put the image file path in the html data 74 75 html = self.report_list[0] % str(pic_fname) 75 76 76 77 # make/open file in case of absence 77 78 f = open(fName, 'w') … … 79 80 # write pdf as a pdf file 80 81 pdf = self.HTML2PDF(data=html, filename=fName) 81 82 # open pdf82 83 # open pdf 83 84 if pdf: 84 85 try: 85 # Windows86 # Windows 86 87 os.startfile(str(fName)) 87 88 except: 88 89 try: 89 # Mac90 os.system("open %s" % fName)90 # Mac 91 os.system("open %s" % fName) 91 92 except: 92 # DO not open93 pass94 # delete image file93 # DO not open 94 logging.error("Could not open file: %s" % sys.exc_value) 95 # delete image file 95 96 os.remove(pic_fname) 96 97 return … … 100 101 report_frame = self.report_list[0] 101 102 elif ext_num == (2 - self.index_offset): 102 ext = '.txt' 103 ext = '.txt' 103 104 # changing the image extension actually changes the image 104 105 # format on saving … … 108 109 return 109 110 110 # file name111 # file name 111 112 fName = os.path.splitext(fName)[0] + ext 112 113 dlg.Destroy() 113 # pic (png) file path/name114 # pic (png) file path/name 114 115 pic_fname = os.path.splitext(fName)[0] + img_ext 115 # put the image path in html string116 # put the image path in html string 116 117 if ext_num == (1 - self.index_offset): 117 118 report = report_frame % os.path.basename(pic_fname) … … 120 121 f.write(report) 121 122 f.close() 122 # save png file using pic_fname123 # save png file using pic_fname 123 124 self.report_list[2].savefig(pic_fname) 124
Note: See TracChangeset
for help on using the changeset viewer.