Changeset c1c14ba in sasview for src/sas/perspectives/pr
- Timestamp:
- Mar 6, 2015 12:25:51 PM (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:
- 8b21fa7
- Parents:
- c4f6851
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/perspectives/pr/pr.py
r79492222 rc1c14ba 1 1 """ 2 P(r) perspective for SasView 3 """ 2 4 ################################################################################ 3 5 #This software was developed by the University of Tennessee as part of the 4 6 #Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 5 #project funded by the US National Science Foundation. 7 #project funded by the US National Science Foundation. 6 8 # 7 9 #See the license text in license.txt … … 11 13 12 14 13 # Make sure the option of saving each curve is available 15 # Make sure the option of saving each curve is available 14 16 # Use the I(q) curve as input and compare the output to P(r) 15 17 16 import os17 18 import sys 18 19 import wx … … 25 26 from sas.guiframe.dataFitting import Data1D 26 27 from sas.guiframe.events import NewPlotEvent 27 from sas.guiframe.events import StatusEvent 28 from sas.guiframe.gui_style import GUIFRAME_ID 28 from sas.guiframe.events import StatusEvent 29 from sas.guiframe.gui_style import GUIFRAME_ID 29 30 from sas.pr.invertor import Invertor 30 31 from sas.dataloader.loader import Loader 31 32 import sas.dataloader 32 33 33 from pr_widgets import load_error 34 from pr_widgets import load_error 34 35 from sas.guiframe.plugin_base import PluginBase 35 36 36 37 37 PR_FIT_LABEL 38 PR_LOADED_LABEL 39 IQ_DATA_LABEL 40 IQ_FIT_LABEL 41 IQ_SMEARED_LABEL 38 PR_FIT_LABEL = r"$P_{fit}(r)$" 39 PR_LOADED_LABEL = r"$P_{loaded}(r)$" 40 IQ_DATA_LABEL = r"$I_{obs}(q)$" 41 IQ_FIT_LABEL = r"$I_{fit}(q)$" 42 IQ_SMEARED_LABEL = r"$I_{smeared}(q)$" 42 43 GROUP_ID_IQ_DATA = r"$I_{obs}(q)$" 43 44 GROUP_ID_PR_FIT = r"$P_{fit}(r)$" … … 51 52 DEFAULT_ALPHA = 0.0001 52 53 DEFAULT_NFUNC = 10 53 DEFAULT_DMAX 54 54 DEFAULT_DMAX = 140.0 55 55 56 def __init__(self, standalone=True): 56 57 PluginBase.__init__(self, name="Pr Inversion", standalone=standalone) 57 58 ## Simulation window manager 58 59 self.simview = None 59 60 60 61 ## State data 61 self.alpha 62 self.nfunc 62 self.alpha = self.DEFAULT_ALPHA 63 self.nfunc = self.DEFAULT_NFUNC 63 64 self.max_length = self.DEFAULT_DMAX 64 self.q_min 65 self.q_max 66 self.has_bck 65 self.q_min = None 66 self.q_max = None 67 self.has_bck = False 67 68 self.slit_height = 0 68 self.slit_width 69 self.slit_width = 0 69 70 ## Remember last plottable processed 70 self.last_data = "sphere_60_q0_2.txt"71 self.last_data = "" 71 72 self._current_file_data = None 72 73 ## Time elapsed for last computation [sec] … … 74 75 self.elapsed = 0.022 75 76 self.iq_data_shown = False 76 77 77 78 ## Current invertor 78 self.invertor 79 self.pr 80 self.data_id = IQ_DATA_LABEL 79 self.invertor = None 80 self.pr = None 81 self.data_id = IQ_DATA_LABEL 81 82 # Copy of the last result in case we need to display it. 82 self._last_pr 83 self._last_out 84 self._last_cov 83 self._last_pr = None 84 self._last_out = None 85 self._last_cov = None 85 86 ## Calculation thread 86 87 self.calc_thread = None … … 97 98 self._normalize_output = False 98 99 self._scale_output_unity = False 99 100 100 101 ## List of added P(r) plots 101 102 self._added_plots = {} 102 self._default_Iq 103 self._default_Iq = {} 103 104 self.list_plot_id = [] 104 105 105 106 # Associate the inversion state reader with .prv files 106 107 from inversion_state import Reader 107 108 108 109 # Create a CanSAS/Pr reader 109 110 self.state_reader = Reader(self.set_state) … … 112 113 l.associate_file_reader('.prv', self.state_reader) 113 114 #l.associate_file_reader(".svs", self.state_reader) 114 115 115 116 # Log startup 116 117 logging.info("Pr(r) plug-in started") 117 118 118 119 def delete_data(self, data_id): 119 120 """ … … 121 122 """ 122 123 self.control_panel.clear_panel() 123 124 124 125 def get_data(self): 125 126 """ … … 127 128 """ 128 129 return self.current_plottable 129 130 130 131 def set_state(self, state=None, datainfo=None): 131 132 """ 132 133 Call-back method for the inversion state reader. 133 134 This method is called when a .prv file is loaded. 134 135 135 136 :param state: InversionState object 136 137 :param datainfo: Data1D object [optional] 137 138 138 139 """ 139 140 try: … … 146 147 data = datainfo 147 148 if data is None: 148 msg = 149 msg = "Pr.set_state: datainfo parameter cannot " 149 150 msg += "be None in standalone mode" 150 151 raise RuntimeError, msg 151 152 152 153 # Ensuring that plots are coordinated correctly 153 154 t = time.localtime(data.meta_data['prstate'].timestamp) 154 155 time_str = time.strftime("%b %d %H:%M", t) 155 156 156 157 # Check that no time stamp is already appended 157 158 max_char = data.meta_data['prstate'].file.find("[") 158 159 if max_char < 0: 159 160 max_char = len(data.meta_data['prstate'].file) 160 161 datainfo.meta_data['prstate'].file = \161 162 datainfo.meta_data['prstate'].file = \ 162 163 data.meta_data['prstate'].file[0:max_char]\ 163 164 + ' [' + time_str + ']' 164 165 165 166 data.filename = data.meta_data['prstate'].file 166 167 # TODO: … … 170 171 self.current_plottable = self.parent.create_gui_data(data, None) 171 172 self.current_plottable.group_id = data.meta_data['prstate'].file 172 173 173 174 # Make sure the user sees the P(r) panel after loading 174 #self.parent.set_perspective(self.perspective) 175 self.on_perspective(event=None) 175 #self.parent.set_perspective(self.perspective) 176 self.on_perspective(event=None) 176 177 # Load the P(r) results 177 178 #state = self.state_reader.get_state() … … 179 180 self.parent.add_data(data_list=data_dict) 180 181 wx.PostEvent(self.parent, NewPlotEvent(plot=self.current_plottable, 181 title=self.current_plottable.title))182 title=self.current_plottable.title)) 182 183 self.control_panel.set_state(state) 183 184 except: 184 185 logging.error("prview.set_state: %s" % sys.exc_value) 185 186 186 187 187 188 def help(self, evt): 188 189 """ 189 Show a general help dialog. 190 190 Show a general help dialog. 191 191 192 :TODO: replace the text with a nice image 192 193 193 194 """ 194 195 from inversion_panel import HelpDialog … … 198 199 else: 199 200 dialog.Destroy() 200 201 201 202 def _fit_pr(self, evt): 202 203 """ … … 204 205 # Generate P(r) for sphere 205 206 radius = 60.0 206 d_max = 2*radius207 208 r = pylab.arange(0.01, d_max, d_max /51.0)207 d_max = 2 * radius 208 209 r = pylab.arange(0.01, d_max, d_max / 51.0) 209 210 M = len(r) 210 211 y = numpy.zeros(M) 211 212 pr_err = numpy.zeros(M) 212 213 sum= 0.0213 214 total = 0.0 214 215 for j in range(M): 215 216 value = self.pr_theory(r[j], radius) 216 sum+= value217 total += value 217 218 y[j] = value 218 219 pr_err[j] = math.sqrt(y[j]) 219 220 220 y = y /sum*d_max/len(r)221 y = y / total * d_max / len(r) 221 222 222 223 # Perform fit … … 230 231 for i in range(len(out)): 231 232 print "%g +- %g" % (out[i], math.sqrt(cov[i][i])) 232 233 233 234 # Show input P(r) 234 235 title = "Pr" … … 236 237 new_plot.name = "P_{obs}(r)" 237 238 new_plot.xaxis("\\rm{r}", 'A') 238 new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}")239 new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}") 239 240 new_plot.group_id = "P_{obs}(r)" 240 241 new_plot.id = "P_{obs}(r)" 241 242 new_plot.title = title 242 self.parent.update_theory(data_id=self.data_id, 243 self.parent.update_theory(data_id=self.data_id, theory=new_plot) 243 244 wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=title)) 244 245 245 246 # Show P(r) fit 246 247 self.show_pr(out, pr) 247 248 248 249 # Show I(q) fit 249 q = pylab.arange(0.001, 0.1, 0.01 /51.0)250 q = pylab.arange(0.001, 0.1, 0.01 / 51.0) 250 251 self.show_iq(out, pr, q) 251 252 252 253 def show_shpere(self, x, radius=70.0, x_range=70.0): 253 254 """ … … 258 259 sum_true = 0.0 259 260 for i in range(len(x)): 260 y_true[i] = self.pr_theory(x[i], radius) 261 y_true[i] = self.pr_theory(x[i], radius) 261 262 sum_true += y_true[i] 262 263 y_true = y_true /sum_true*x_range/len(x)264 263 264 y_true = y_true / sum_true * x_range / len(x) 265 265 266 # Show the theory P(r) 266 267 new_plot = Data1D(x, y_true) … … 268 269 new_plot.name = "P_{true}(r)" 269 270 new_plot.xaxis("\\rm{r}", 'A') 270 new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}")271 new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}") 271 272 new_plot.id = "P_{true}(r)" 272 273 new_plot.group_id = "P_{true}(r)" 273 274 self.parent.update_theory(data_id=self.data_id, theory=new_plot) 274 #Put this call in plottables/guitools 275 #Put this call in plottables/guitools 275 276 wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, 276 title="Sphere P(r)")) 277 278 277 title="Sphere P(r)")) 278 279 279 def get_npts(self): 280 280 """ … … 285 285 except: 286 286 return 0 287 287 288 288 def show_iq(self, out, pr, q=None): 289 289 """ 290 """ 290 Display computed I(q) 291 """ 291 292 qtemp = pr.x 292 293 if not q == None: … … 296 297 maxq = -1 297 298 for q_i in qtemp: 298 if q_i >maxq:299 maxq =q_i300 299 if q_i > maxq: 300 maxq = q_i 301 301 302 minq = 0.001 302 303 303 304 # Check for user min/max 304 305 if not pr.q_min == None: … … 306 307 if not pr.q_max == None: 307 308 maxq = pr.q_max 308 309 x = pylab.arange(minq, maxq, maxq /301.0)309 310 x = pylab.arange(minq, maxq, maxq / 301.0) 310 311 y = numpy.zeros(len(x)) 311 312 err = numpy.zeros(len(x)) … … 318 319 err[i] = 1.0 319 320 print "Error getting error", value, x[i] 320 321 321 322 new_plot = Data1D(x, y) 322 323 new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM 323 324 new_plot.name = IQ_FIT_LABEL 324 325 new_plot.xaxis("\\rm{Q}", 'A^{-1}') 325 new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")326 new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") 326 327 title = "I(q)" 327 328 new_plot.title = title 328 329 329 330 # If we have a group ID, use it 330 331 if pr.info.has_key("plot_group_id"): … … 332 333 new_plot.id = IQ_FIT_LABEL 333 334 self.parent.update_theory(data_id=self.data_id, theory=new_plot) 334 335 335 336 wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=title)) 336 337 337 338 # If we have used slit smearing, plot the smeared I(q) too 338 339 if pr.slit_width > 0 or pr.slit_height > 0: 339 x = pylab.arange(minq, maxq, maxq /301.0)340 x = pylab.arange(minq, maxq, maxq / 301.0) 340 341 y = numpy.zeros(len(x)) 341 342 err = numpy.zeros(len(x)) … … 348 349 err[i] = 1.0 349 350 print "Error getting error", value, x[i] 350 351 351 352 new_plot = Data1D(x, y) 352 353 new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM 353 354 new_plot.name = IQ_SMEARED_LABEL 354 355 new_plot.xaxis("\\rm{Q}", 'A^{-1}') 355 new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")356 new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") 356 357 # If we have a group ID, use it 357 358 if pr.info.has_key("plot_group_id"): 358 new_plot.group_id = pr.info["plot_group_id"]359 new_plot.group_id = pr.info["plot_group_id"] 359 360 new_plot.id = IQ_SMEARED_LABEL 360 361 new_plot.title = title 361 362 self.parent.update_theory(data_id=self.data_id, theory=new_plot) 362 363 wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=title)) 363 364 364 365 def _on_pr_npts(self, evt): 365 366 """ 366 367 Redisplay P(r) with a different number of points 367 """ 368 """ 368 369 from inversion_panel import PrDistDialog 369 370 dialog = PrDistDialog(None, -1) 370 371 dialog.set_content(self._pr_npts) 371 372 if dialog.ShowModal() == wx.ID_OK: 372 self._pr_npts = dialog.get_content()373 self._pr_npts = dialog.get_content() 373 374 dialog.Destroy() 374 375 self.show_pr(self._last_out, self._last_pr, self._last_cov) 375 376 else: 376 377 dialog.Destroy() 377 378 378 379 379 380 def show_pr(self, out, pr, cov=None): 380 381 """ 381 """ 382 """ 382 383 # Show P(r) 383 x = pylab.arange(0.0, pr.d_max, pr.d_max /self._pr_npts)384 384 x = pylab.arange(0.0, pr.d_max, pr.d_max / self._pr_npts) 385 385 386 y = numpy.zeros(len(x)) 386 387 dy = numpy.zeros(len(x)) 387 388 y_true = numpy.zeros(len(x)) 388 389 389 sum= 0.0390 total = 0.0 390 391 pmax = 0.0 391 392 cov2 = numpy.ascontiguousarray(cov) 392 393 393 394 for i in range(len(x)): 394 if cov2 ==None:395 if cov2 == None: 395 396 value = pr.pr(out, x[i]) 396 397 else: 397 398 (value, dy[i]) = pr.pr_err(out, cov2, x[i]) 398 sum += value*pr.d_max/len(x)399 399 total += value * pr.d_max / len(x) 400 400 401 # keep track of the maximum P(r) value 401 if value >pmax:402 if value > pmax: 402 403 pmax = value 403 404 404 405 y[i] = value 405 406 if self._normalize_output ==True:407 y = y /sum408 dy = dy /sum409 elif self._scale_output_unity ==True:410 y = y /pmax411 dy = dy /pmax412 413 if cov2 ==None:406 407 if self._normalize_output == True: 408 y = y / total 409 dy = dy / total 410 elif self._scale_output_unity == True: 411 y = y / pmax 412 dy = dy / pmax 413 414 if cov2 == None: 414 415 new_plot = Data1D(x, y) 415 416 new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM … … 418 419 new_plot.name = PR_FIT_LABEL 419 420 new_plot.xaxis("\\rm{r}", 'A') 420 new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}")421 new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}") 421 422 new_plot.title = "P(r) fit" 422 423 new_plot.id = PR_FIT_LABEL 423 424 # Make sure that the plot is linear 424 425 new_plot.xtransform = "x" 425 new_plot.ytransform = "y" 426 new_plot.ytransform = "y" 426 427 new_plot.group_id = GROUP_ID_PR_FIT 427 self.parent.update_theory(data_id=self.data_id, theory=new_plot) 428 self.parent.update_theory(data_id=self.data_id, theory=new_plot) 428 429 wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title="P(r) fit")) 429 430 return x, pr.d_max 430 431 431 432 def load(self, data): 432 433 """ … … 434 435 by our standard DataLoader class. 435 436 """ 436 class FileData :437 class FileData(object): 437 438 x = None 438 439 y = None 439 440 err = None 440 441 path = None 441 442 442 443 def __init__(self, path): 443 444 self.path = path 444 445 445 446 self._current_file_data = FileData(data.path) 446 447 447 448 # Use data loader to load file 448 #dataread = Loader().load(path)449 449 dataread = data 450 450 # Notify the user if we could not read the file 451 451 if dataread is None: 452 452 raise RuntimeError, "Invalid data" 453 453 454 454 x = None 455 455 y = None … … 460 460 err = dataread.dy 461 461 else: 462 if isinstance(dataread, list) and len(dataread) >0:462 if isinstance(dataread, list) and len(dataread) > 0: 463 463 x = dataread[0].x 464 464 y = dataread[0].y 465 465 err = dataread[0].dy 466 466 msg = "PrView only allows a single data set at a time. " 467 msg += "Only the first data set was loaded." 467 msg += "Only the first data set was loaded." 468 468 wx.PostEvent(self.parent, StatusEvent(status=msg)) 469 469 else: … … 471 471 return x, y, err 472 472 raise RuntimeError, "This tool can only read 1D data" 473 473 474 474 self._current_file_data.x = x 475 475 self._current_file_data.y = y 476 476 self._current_file_data.err = err 477 477 return x, y, err 478 479 def load_columns(self, path ="sphere_60_q0_2.txt"):478 479 def load_columns(self, path="sphere_60_q0_2.txt"): 480 480 """ 481 481 Load 2- or 3- column ascii 482 482 """ 483 483 # Read the data from the data file 484 data_x 485 data_y 484 data_x = numpy.zeros(0) 485 data_y = numpy.zeros(0) 486 486 data_err = numpy.zeros(0) 487 scale 488 min_err 487 scale = None 488 min_err = 0.0 489 489 if not path == None: 490 input_f = open(path, 'r')491 buff 492 lines 490 input_f = open(path, 'r') 491 buff = input_f.read() 492 lines = buff.split('\n') 493 493 for line in lines: 494 494 try: … … 496 496 x = float(toks[0]) 497 497 y = float(toks[1]) 498 if len(toks) >2:498 if len(toks) > 2: 499 499 err = float(toks[2]) 500 500 else: 501 if scale ==None:502 scale = 0.05 *math.sqrt(y)501 if scale == None: 502 scale = 0.05 * math.sqrt(y) 503 503 #scale = 0.05/math.sqrt(y) 504 min_err = 0.01 *y505 err = scale *math.sqrt(y)+min_err504 min_err = 0.01 * y 505 err = scale * math.sqrt(y) + min_err 506 506 #err = 0 507 507 508 508 data_x = numpy.append(data_x, x) 509 509 data_y = numpy.append(data_y, y) 510 510 data_err = numpy.append(data_err, err) 511 511 except: 512 pass513 514 if not scale ==None:512 logging.error(sys.exc_value) 513 514 if not scale == None: 515 515 message = "The loaded file had no error bars, statistical errors are assumed." 516 516 wx.PostEvent(self.parent, StatusEvent(status=message)) 517 517 else: 518 518 wx.PostEvent(self.parent, StatusEvent(status='')) 519 520 return data_x, data_y, data_err 521 519 520 return data_x, data_y, data_err 521 522 522 def load_abs(self, path): 523 523 """ 524 524 Load an IGOR .ABS reduced file 525 525 526 526 :param path: file path 527 527 528 528 :return: x, y, err vectors 529 529 530 530 """ 531 531 # Read the data from the data file 532 data_x 533 data_y 532 data_x = numpy.zeros(0) 533 data_y = numpy.zeros(0) 534 534 data_err = numpy.zeros(0) 535 scale 536 min_err 537 535 scale = None 536 min_err = 0.0 537 538 538 data_started = False 539 539 if not path == None: 540 input_f = open(path, 'r')541 buff 542 lines 540 input_f = open(path, 'r') 541 buff = input_f.read() 542 lines = buff.split('\n') 543 543 for line in lines: 544 544 if data_started == True: … … 547 547 x = float(toks[0]) 548 548 y = float(toks[1]) 549 if len(toks) >2:549 if len(toks) > 2: 550 550 err = float(toks[2]) 551 551 else: 552 552 if scale == None: 553 scale = 0.05 *math.sqrt(y)553 scale = 0.05 * math.sqrt(y) 554 554 #scale = 0.05/math.sqrt(y) 555 min_err = 0.01 *y556 err = scale *math.sqrt(y)+min_err555 min_err = 0.01 * y 556 err = scale * math.sqrt(y) + min_err 557 557 #err = 0 558 558 559 559 data_x = numpy.append(data_x, x) 560 560 data_y = numpy.append(data_y, y) 561 561 data_err = numpy.append(data_err, err) 562 562 except: 563 pass564 elif line.find("The 6 columns") >=0:565 data_started = True 566 563 logging.error(sys.exc_value) 564 elif line.find("The 6 columns") >= 0: 565 data_started = True 566 567 567 if not scale == None: 568 568 message = "The loaded file had no error bars, statistical errors are assumed." … … 570 570 else: 571 571 wx.PostEvent(self.parent, StatusEvent(status='')) 572 573 return data_x, data_y, data_err 574 572 573 return data_x, data_y, data_err 574 575 575 def pr_theory(self, r, R): 576 """ 577 Return P(r) of a sphere for a given R 576 """ 577 Return P(r) of a sphere for a given R 578 578 For test purposes 579 579 """ 580 if r <= 2 *R:581 return 12.0 * ((0.5*r/R)**2) * ((1.0-0.5*r/R)**2) * ( 2.0 + 0.5*r/R)580 if r <= 2 * R: 581 return 12.0 * ((0.5 * r / R) ** 2) * ((1.0 - 0.5 * r / R) ** 2) * (2.0 + 0.5 * r / R) 582 582 else: 583 583 return 0.0 … … 586 586 """ 587 587 Get the context menu items available for P(r) 588 588 589 589 :param graph: the Graph object to which we attach the context menu 590 590 591 591 :return: a list of menu items with call-back function 592 592 593 593 """ 594 594 graph = plotpanel.graph … … 603 603 change_n_hint += " points on the P(r) output" 604 604 change_n_label = "Change number of P(r) points" 605 m_list = [[change_n_label, change_n_hint 605 m_list = [[change_n_label, change_n_hint, self._on_pr_npts]] 606 606 607 607 if self._scale_output_unity or self._normalize_output: 608 608 hint = "Let the output P(r) keep the scale of the data" 609 m_list.append(["Disable P(r) scaling", hint, 609 m_list.append(["Disable P(r) scaling", hint, 610 610 self._on_disable_scaling]) 611 611 if not self._scale_output_unity: 612 m_list.append(["Scale P_max(r) to unity", 613 "Scale P(r) so that its maximum is 1", 612 m_list.append(["Scale P_max(r) to unity", 613 "Scale P(r) so that its maximum is 1", 614 614 self._on_scale_unity]) 615 615 if not self._normalize_output: 616 m_list.append(["Normalize P(r) to unity", 617 "Normalize the integral of P(r) to 1", 616 m_list.append(["Normalize P(r) to unity", 617 "Normalize the integral of P(r) to 1", 618 618 self._on_normalize]) 619 619 620 620 return m_list 621 622 elif item.id in [PR_LOADED_LABEL, IQ_DATA_LABEL, IQ_FIT_LABEL, 623 IQ_SMEARED_LABEL]: 621 622 elif item.id in [PR_LOADED_LABEL, IQ_DATA_LABEL, IQ_FIT_LABEL, IQ_SMEARED_LABEL]: 624 623 return [] 625 624 elif item.id == graph.selected_plottable: 626 if not self.standalone and issubclass(item.__class__, Data1D): 627 return [["Compute P(r)", 628 "Compute P(r) from distribution", 629 self._on_context_inversion]] 630 625 if not self.standalone and issubclass(item.__class__, Data1D): 626 return [["Compute P(r)", 627 "Compute P(r) from distribution", 628 self._on_context_inversion]] 631 629 return [] 632 630 … … 634 632 """ 635 633 Disable P(r) scaling 636 634 637 635 :param evt: Menu event 638 636 639 637 """ 640 638 self._normalize_output = False 641 639 self._scale_output_unity = False 642 640 self.show_pr(self._last_out, self._last_pr, self._last_cov) 643 641 644 642 # Now replot the original added data 645 643 for plot in self._added_plots: 646 644 self._added_plots[plot].y = numpy.copy(self._default_Iq[plot]) 647 wx.PostEvent(self.parent, 648 NewPlotEvent(plot=self._added_plots[plot], 645 wx.PostEvent(self.parent, 646 NewPlotEvent(plot=self._added_plots[plot], 649 647 title=self._added_plots[plot].name, 650 update=True))651 648 update=True)) 649 652 650 # Need the update flag in the NewPlotEvent to protect against 653 651 # the plot no longer being there... 654 652 655 653 def _on_normalize(self, evt): 656 654 """ 657 655 Normalize the area under the P(r) curve to 1. 658 656 This operation is done for all displayed plots. 659 657 660 658 :param evt: Menu event 661 659 662 660 """ 663 661 self._normalize_output = True 664 662 self._scale_output_unity = False 665 663 666 664 self.show_pr(self._last_out, self._last_pr, self._last_cov) 667 665 668 666 # Now scale the added plots too 669 667 for plot in self._added_plots: 670 sum= numpy.sum(self._added_plots[plot].y)668 total = numpy.sum(self._added_plots[plot].y) 671 669 npts = len(self._added_plots[plot].x) 672 sum *= self._added_plots[plot].x[npts-1]/npts673 y = self._added_plots[plot].y /sum674 670 total *= self._added_plots[plot].x[npts - 1] / npts 671 y = self._added_plots[plot].y / total 672 675 673 new_plot = Data1D(self._added_plots[plot].x, y) 676 674 new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM … … 680 678 new_plot.name = self._added_plots[plot].name 681 679 new_plot.xaxis("\\rm{r}", 'A') 682 new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}")683 self.parent.update_theory(data_id=self.data_id, theory=new_plot) 684 wx.PostEvent(self.parent, 680 new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}") 681 self.parent.update_theory(data_id=self.data_id, theory=new_plot) 682 wx.PostEvent(self.parent, 685 683 NewPlotEvent(plot=new_plot, update=True, 686 687 684 title=self._added_plots[plot].name)) 685 688 686 def _on_scale_unity(self, evt): 689 687 """ 690 688 Scale the maximum P(r) value on each displayed plot to 1. 691 689 692 690 :param evt: Menu event 693 691 694 692 """ 695 693 self._scale_output_unity = True 696 694 self._normalize_output = False 697 695 698 696 self.show_pr(self._last_out, self._last_pr, self._last_cov) 699 697 700 698 # Now scale the added plots too 701 699 for plot in self._added_plots: 702 700 _max = 0 703 701 for y in self._added_plots[plot].y: 704 if y >_max:702 if y > _max: 705 703 _max = y 706 y = self._added_plots[plot].y /_max707 704 y = self._added_plots[plot].y / _max 705 708 706 new_plot = Data1D(self._added_plots[plot].x, y) 709 707 new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM 710 708 new_plot.name = self._added_plots[plot].name 711 709 new_plot.xaxis("\\rm{r}", 'A') 712 new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}")713 self.parent.update_theory(data_id=self.data_id, theory=new_plot)714 wx.PostEvent(self.parent, 710 new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}") 711 self.parent.update_theory(data_id=self.data_id, theory=new_plot) 712 wx.PostEvent(self.parent, 715 713 NewPlotEvent(plot=new_plot, update=True, 716 title=self._added_plots[plot].name))717 714 title=self._added_plots[plot].name)) 715 718 716 def start_thread(self): 719 717 """ 718 Start a calculation thread 720 719 """ 721 720 from pr_thread import CalcPr 722 721 723 722 # If a thread is already started, stop it 724 723 if self.calc_thread != None and self.calc_thread.isrunning(): 725 724 self.calc_thread.stop() 726 ## stop just raises the flag -- the thread is supposed to 725 ## stop just raises the flag -- the thread is supposed to 727 726 ## then kill itself. In August 2014 it was shown that this is 728 ## incorrectly handled by fitting.py and a fix implemented. 727 ## incorrectly handled by fitting.py and a fix implemented. 729 728 ## It is not clear whether it is properly used here, but the 730 729 ## "fix" of waiting for the previous thread to end breaks the … … 735 734 ## are being properly handled. 736 735 ## 737 ## -PDB January 25, 2015 738 736 ## -PDB January 25, 2015 737 739 738 pr = self.pr.clone() 740 739 self.calc_thread = CalcPr(pr, self.nfunc, 741 error_func=self._thread_error,742 740 error_func=self._thread_error, 741 completefn=self._completed, updatefn=None) 743 742 self.calc_thread.queue() 744 743 self.calc_thread.ready(2.5) 745 744 746 745 def _thread_error(self, error): 747 746 """ 747 Call-back method for calculation errors 748 748 """ 749 749 wx.PostEvent(self.parent, StatusEvent(status=error)) 750 750 751 751 def _estimate_completed(self, alpha, message, elapsed): 752 752 """ 753 Parameter estimation completed, 753 Parameter estimation completed, 754 754 display the results to the user 755 755 756 756 :param alpha: estimated best alpha 757 757 :param elapsed: computation time 758 758 759 759 """ 760 760 # Save useful info 761 761 self.elapsed = elapsed 762 762 self.control_panel.alpha_estimate = alpha 763 if not message ==None:763 if not message == None: 764 764 wx.PostEvent(self.parent, StatusEvent(status=str(message))) 765 765 self.perform_estimateNT() 766 766 767 767 def _estimateNT_completed(self, nterms, alpha, message, elapsed): 768 768 """ 769 Parameter estimation completed, 769 Parameter estimation completed, 770 770 display the results to the user 771 771 772 772 :param alpha: estimated best alpha 773 773 :param nterms: estimated number of terms 774 774 :param elapsed: computation time 775 775 776 776 """ 777 777 # Save useful info … … 779 779 self.control_panel.nterms_estimate = nterms 780 780 self.control_panel.alpha_estimate = alpha 781 if not message ==None:781 if not message == None: 782 782 wx.PostEvent(self.parent, StatusEvent(status=str(message))) 783 783 784 784 def _completed(self, out, cov, pr, elapsed): 785 785 """ 786 786 wxCallAfter Method called with the results when the inversion 787 787 is done 788 788 789 789 :param out: output coefficient for the base functions 790 790 :param cov: covariance matrix … … 795 795 # Without CallAfter, it will freeze with wx >= 2.9. 796 796 wx.CallAfter(self._completed_call, out, cov, pr, elapsed) 797 797 798 798 def _completed_call(self, out, cov, pr, elapsed): 799 799 """ 800 800 Method called with the results when the inversion 801 801 is done 802 802 803 803 :param out: output coefficient for the base functions 804 804 :param cov: covariance matrix 805 805 :param pr: Invertor instance 806 806 :param elapsed: time spent computing 807 807 808 808 """ 809 809 # Save useful info 810 810 self.elapsed = elapsed 811 811 # Keep a copy of the last result 812 self._last_pr 812 self._last_pr = pr.clone() 813 813 self._last_out = out 814 814 self._last_cov = cov 815 815 816 816 # Save Pr invertor 817 817 self.pr = pr 818 819 #message = "Computation completed in"820 #message += %g seconds [chi2=%g]" % (elapsed, pr.chi2)821 #wx.PostEvent(self.parent, StatusEvent(status=message))822 823 818 cov = numpy.ascontiguousarray(cov) 824 819 … … 828 823 self.control_panel.oscillation = pr.oscillations(out) 829 824 self.control_panel.positive = pr.get_positive(out) 830 self.control_panel.pos_err 825 self.control_panel.pos_err = pr.get_pos_err(out, cov) 831 826 self.control_panel.rg = pr.rg(out) 832 827 self.control_panel.iq0 = pr.iq0(out) 833 828 self.control_panel.bck = pr.background 834 829 835 830 # Show I(q) fit 836 831 self.show_iq(out, self.pr) 837 832 838 833 # Show P(r) fit 839 x_values, x_range = self.show_pr(out, self.pr, cov)840 834 self.show_pr(out, self.pr, cov) 835 841 836 def show_data(self, path=None, data=None, reset=False): 842 837 """ 843 838 Show data read from a file 844 839 845 840 :param path: file path 846 841 :param reset: if True all other plottables will be cleared 847 842 848 843 """ 849 844 #if path is not None: … … 855 850 wx.PostEvent(self.parent, StatusEvent(status=status)) 856 851 raise RuntimeError, status 857 852 858 853 # If the file contains nothing, just return 859 854 if pr is None: 860 855 raise RuntimeError, "Loaded data is invalid" 861 856 862 857 self.pr = pr 863 858 864 859 # Make a plot of I(q) data 865 860 if self.pr.err == None: … … 870 865 new_plot.name = IQ_DATA_LABEL 871 866 new_plot.xaxis("\\rm{Q}", 'A^{-1}') 872 new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")867 new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") 873 868 new_plot.interactive = True 874 869 new_plot.group_id = GROUP_ID_IQ_DATA 875 870 new_plot.id = self.data_id 876 new_plot.title = "I(q)" 877 wx.PostEvent(self.parent, 871 new_plot.title = "I(q)" 872 wx.PostEvent(self.parent, 878 873 NewPlotEvent(plot=new_plot, title="I(q)", reset=reset)) 879 874 880 875 self.current_plottable = new_plot 881 876 # Get Q range 882 877 self.control_panel.q_min = min(self.pr.x) 883 878 self.control_panel.q_max = max(self.pr.x) 884 879 885 880 def save_data(self, filepath, prstate=None): 886 881 """ 887 882 Save data in provided state object. 888 889 :TODO: move the state code away from inversion_panel and move it here. 883 884 :TODO: move the state code away from inversion_panel and move it here. 890 885 Then remove the "prstate" input and make this method private. 891 886 892 887 :param filepath: path of file to write to 893 :param prstate: P(r) inversion state 894 888 :param prstate: P(r) inversion state 889 895 890 """ 896 891 #TODO: do we need this or can we use DataLoader.loader.save directly? 897 892 898 893 # Add output data and coefficients to state 899 894 prstate.coefficients = self._last_out 900 895 prstate.covariance = self._last_cov 901 896 902 897 # Write the output to file 903 898 # First, check that the data is of the right type 904 899 if issubclass(self.current_plottable.__class__, 905 900 sas.dataloader.data_info.Data1D): 906 901 self.state_reader.write(filepath, self.current_plottable, prstate) 907 902 else: 908 903 msg = "pr.save_data: the data being saved is not a" 909 msg += " sas.data_info.Data1D object" 904 msg += " sas.data_info.Data1D object" 910 905 raise RuntimeError, msg 911 912 913 def setup_plot_inversion(self, alpha, nfunc, d_max, q_min=None, q_max=None, 906 907 def setup_plot_inversion(self, alpha, nfunc, d_max, q_min=None, q_max=None, 914 908 bck=False, height=0, width=0): 915 909 """ 910 Set up inversion from plotted data 916 911 """ 917 912 self.alpha = alpha … … 922 917 self.has_bck = bck 923 918 self.slit_height = height 924 self.slit_width 925 919 self.slit_width = width 920 926 921 try: 927 922 pr = self._create_plot_pr() 928 if not pr ==None:923 if not pr == None: 929 924 self.pr = pr 930 925 self.perform_inversion() … … 932 927 wx.PostEvent(self.parent, StatusEvent(status=sys.exc_value)) 933 928 934 def estimate_plot_inversion(self, alpha, nfunc, d_max, 935 q_min=None, q_max=None, 929 def estimate_plot_inversion(self, alpha, nfunc, d_max, 930 q_min=None, q_max=None, 936 931 bck=False, height=0, width=0): 937 932 """ 933 Estimate parameters from plotted data 938 934 """ 939 935 self.alpha = alpha … … 944 940 self.has_bck = bck 945 941 self.slit_height = height 946 self.slit_width 947 942 self.slit_width = width 943 948 944 try: 949 945 pr = self._create_plot_pr() 950 if not pr ==None:946 if not pr == None: 951 947 self.pr = pr 952 948 self.perform_estimate() 953 949 except: 954 wx.PostEvent(self.parent, StatusEvent(status=sys.exc_value)) 950 wx.PostEvent(self.parent, StatusEvent(status=sys.exc_value)) 955 951 956 952 def _create_plot_pr(self, estimate=False): … … 958 954 Create and prepare invertor instance from 959 955 a plottable data set. 960 961 :param path: path of the file to read in 962 956 957 :param path: path of the file to read in 958 963 959 """ 964 960 # Sanity check 965 961 if self.current_plottable is None: 966 962 msg = "Please load a valid data set before proceeding." 967 wx.PostEvent(self.parent, StatusEvent(status=msg)) 968 return None 969 963 wx.PostEvent(self.parent, StatusEvent(status=msg)) 964 return None 965 970 966 # Get the data from the chosen data set and perform inversion 971 967 pr = Invertor() … … 979 975 pr.slit_height = self.slit_height 980 976 pr.slit_width = self.slit_width 981 977 982 978 # Keep track of the plot window title to ensure that 983 979 # we can overlay the plots 984 980 pr.info["plot_group_id"] = self.current_plottable.group_id 985 981 986 982 # Fill in errors if none were provided 987 983 err = self.current_plottable.dy 988 984 all_zeros = True 989 985 if err == None: 990 err = numpy.zeros(len(pr.y)) 991 else: 986 err = numpy.zeros(len(pr.y)) 987 else: 992 988 for i in range(len(err)): 993 if err[i] >0:989 if err[i] > 0: 994 990 all_zeros = False 995 996 if all_zeros: 991 992 if all_zeros: 997 993 scale = None 998 994 min_err = 0.0 999 995 for i in range(len(pr.y)): 1000 996 # Scale the error so that we can fit over several decades of Q 1001 if scale ==None:1002 scale = 0.05 *math.sqrt(pr.y[i])1003 min_err = 0.01 *pr.y[i]1004 err[i] = scale *math.sqrt( math.fabs(pr.y[i])) + min_err997 if scale == None: 998 scale = 0.05 * math.sqrt(pr.y[i]) 999 min_err = 0.01 * pr.y[i] 1000 err[i] = scale * math.sqrt(math.fabs(pr.y[i])) + min_err 1005 1001 message = "The loaded file had no error bars, " 1006 1002 message += "statistical errors are assumed." … … 1008 1004 1009 1005 pr.err = err 1010 1006 1011 1007 return pr 1012 1008 1013 1014 1009 def setup_file_inversion(self, alpha, nfunc, d_max, data, 1015 path=None, q_min=None, q_max=None, 1010 path=None, q_min=None, q_max=None, 1016 1011 bck=False, height=0, width=0): 1017 1012 """ 1013 Set up inversion 1018 1014 """ 1019 1015 self.alpha = alpha … … 1024 1020 self.has_bck = bck 1025 1021 self.slit_height = height 1026 self.slit_width 1027 1022 self.slit_width = width 1023 1028 1024 try: 1029 #pr = self._create_file_pr(path)1030 1025 pr = self._create_file_pr(data) 1031 if not pr ==None:1026 if not pr == None: 1032 1027 self.pr = pr 1033 1028 self.perform_inversion() 1034 1029 except: 1035 1030 wx.PostEvent(self.parent, StatusEvent(status=sys.exc_value)) 1036 1031 1037 1032 def estimate_file_inversion(self, alpha, nfunc, d_max, data, 1038 path=None, q_min=None, q_max=None, 1033 path=None, q_min=None, q_max=None, 1039 1034 bck=False, height=0, width=0): 1040 1035 """ 1036 Estimate parameters for inversion 1041 1037 """ 1042 1038 self.alpha = alpha … … 1047 1043 self.has_bck = bck 1048 1044 self.slit_height = height 1049 self.slit_width 1050 1045 self.slit_width = width 1046 1051 1047 try: 1052 1048 pr = self._create_file_pr(data) 1053 #pr = self._create_file_pr(path)1054 1049 if not pr is None: 1055 1050 self.pr = pr … … 1057 1052 except: 1058 1053 wx.PostEvent(self.parent, StatusEvent(status=sys.exc_value)) 1059 1060 1054 1061 1055 def _create_file_pr(self, data): 1062 1056 """ 1063 1057 Create and prepare invertor instance from 1064 1058 a file data set. 1065 1066 :param path: path of the file to read in 1067 1068 """ 1069 # Load data 1070 #if os.path.isfile(path): 1071 """ 1072 if self._current_file_data is not None \ 1073 and self._current_file_data.path==path: 1074 # Protect against corrupted data from 1075 # previous failed load attempt 1076 if self._current_file_data.x is None: 1077 return None 1078 x = self._current_file_data.x 1079 y = self._current_file_data.y 1080 err = self._current_file_data.err 1081 1082 message = "The data from this file has already been loaded." 1083 wx.PostEvent(self.parent, StatusEvent(status=message)) 1084 else: 1059 1060 :param path: path of the file to read in 1061 1085 1062 """ 1086 1063 # Reset the status bar so that we don't get mixed up 1087 # with old messages. 1064 # with old messages. 1088 1065 #TODO: refactor this into a proper status handling 1089 1066 wx.PostEvent(self.parent, StatusEvent(status='')) 1090 1067 try: 1091 class FileData :1068 class FileData(object): 1092 1069 x = None 1093 1070 y = None … … 1096 1073 def __init__(self, path): 1097 1074 self.path = path 1098 1075 1099 1076 self._current_file_data = FileData(data.path) 1100 1077 self._current_file_data.x = data.x … … 1105 1082 load_error(sys.exc_value) 1106 1083 return None 1107 1084 1108 1085 # If the file contains no data, just return 1109 1086 if x is None or len(x) == 0: … … 1126 1103 message += "statistical errors are assumed." 1127 1104 wx.PostEvent(self.parent, StatusEvent(status=message)) 1128 1105 1129 1106 try: 1130 1107 # Get the data from the chosen data set and perform inversion … … 1144 1121 load_error(sys.exc_value) 1145 1122 return None 1146 1123 1147 1124 def perform_estimate(self): 1148 1125 """ 1126 Perform parameter estimation 1149 1127 """ 1150 1128 from pr_thread import EstimatePr 1151 from copy import deepcopy 1152 1129 1153 1130 # If a thread is already started, stop it 1154 1131 if self.estimation_thread != None and \ 1155 1132 self.estimation_thread.isrunning(): 1156 1133 self.estimation_thread.stop() 1157 ## stop just raises the flag -- the thread is supposed to 1134 ## stop just raises the flag -- the thread is supposed to 1158 1135 ## then kill itself. In August 2014 it was shown that this is 1159 ## incorrectly handled by fitting.py and a fix implemented. 1136 ## incorrectly handled by fitting.py and a fix implemented. 1160 1137 ## It is not clear whether it is properly used here, but the 1161 1138 ## "fix" of waiting for the previous thread to end breaks the … … 1166 1143 ## are being properly handled. 1167 1144 ## 1168 ## -PDB January 25, 2015 1169 1170 1145 ## -PDB January 25, 2015 1171 1146 pr = self.pr.clone() 1172 1147 self.estimation_thread = EstimatePr(pr, self.nfunc, 1173 error_func=self._thread_error,1174 completefn = self._estimate_completed,1175 updatefn =None)1148 error_func=self._thread_error, 1149 completefn=self._estimate_completed, 1150 updatefn=None) 1176 1151 self.estimation_thread.queue() 1177 1152 self.estimation_thread.ready(2.5) 1178 1153 1179 1154 def perform_estimateNT(self): 1180 1155 """ 1156 Perform parameter estimation 1181 1157 """ 1182 1158 from pr_thread import EstimateNT 1183 from copy import deepcopy 1184 1159 1185 1160 # If a thread is already started, stop it 1186 1161 if self.estimation_thread != None and self.estimation_thread.isrunning(): 1187 1162 self.estimation_thread.stop() 1188 ## stop just raises the flag -- the thread is supposed to 1163 ## stop just raises the flag -- the thread is supposed to 1189 1164 ## then kill itself. In August 2014 it was shown that this is 1190 ## incorrectly handled by fitting.py and a fix implemented. 1165 ## incorrectly handled by fitting.py and a fix implemented. 1191 1166 ## It is not clear whether it is properly used here, but the 1192 1167 ## "fix" of waiting for the previous thread to end breaks the … … 1197 1172 ## are being properly handled. 1198 1173 ## 1199 ## -PDB January 25, 2015 1200 1174 ## -PDB January 25, 2015 1201 1175 pr = self.pr.clone() 1202 1176 # Skip the slit settings for the estimation 1203 1177 # It slows down the application and it doesn't change the estimates 1204 1178 pr.slit_height = 0.0 1205 pr.slit_width 1206 self.estimation_thread = EstimateNT(pr, self.nfunc, 1207 error_func=self._thread_error, 1208 completefn = self._estimateNT_completed,1209 updatefn =None)1179 pr.slit_width = 0.0 1180 self.estimation_thread = EstimateNT(pr, self.nfunc, 1181 error_func=self._thread_error, 1182 completefn=self._estimateNT_completed, 1183 updatefn=None) 1210 1184 self.estimation_thread.queue() 1211 1185 self.estimation_thread.ready(2.5) 1212 1186 1213 1187 def perform_inversion(self): 1214 1188 """ 1215 """ 1216 # Time estimate 1217 #estimated = self.elapsed*self.nfunc**2 1218 #message = "Computation time may take up to %g seconds" % self.elapsed 1219 #wx.PostEvent(self.parent, StatusEvent(status=message)) 1220 1221 # Start inversion thread 1189 Perform inversion 1190 """ 1222 1191 self.start_thread() 1223 return 1224 1225 out, cov = self.pr.lstsq(self.nfunc) 1226 1227 # Save useful info 1228 self.elapsed = self.pr.elapsed 1229 1230 for i in range(len(out)): 1231 try: 1232 print "%d: %g +- %g" % (i, out[i], 1233 math.sqrt(math.fabs(cov[i][i]))) 1234 except: 1235 print "%d: %g +- ?" % (i, out[i]) 1236 1237 # Make a plot of I(q) data 1238 new_plot = Data1D(self.pr.x, self.pr.y, dy=self.pr.err) 1239 new_plot.name = "I_{obs}(q)" 1240 new_plot.xaxis("\\rm{Q}", 'A^{-1}') 1241 new_plot.yaxis("\\rm{Intensity} ","cm^{-1}") 1242 wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title="Iq")) 1243 # Show I(q) fit 1244 self.show_iq(out, self.pr) 1245 # Show P(r) fit 1246 x_values, x_range = self.show_pr(out, self.pr, cov=cov) 1247 1192 1248 1193 def _on_context_inversion(self, event): 1249 1194 """ 1195 Call-back method for plot context menu 1250 1196 """ 1251 1197 panel = event.GetEventObject() … … 1259 1205 logging.info("Prview Error: No data is available") 1260 1206 return 1261 1207 1262 1208 # Store a reference to the current plottable 1263 1209 # If we have a suggested value, use it. … … 1268 1214 self.control_panel.alpha = self.alpha 1269 1215 logging.info("Prview :Alpha Not estimate yet") 1270 pass1271 1216 try: 1272 1217 estimate = int(self.control_panel.nterms_estimate) … … 1275 1220 self.control_panel.nfunc = self.nfunc 1276 1221 logging.info("Prview : ntemrs Not estimate yet") 1277 pass 1278 1222 1279 1223 self.current_plottable = panel.plots[panel.graph.selected_plottable] 1280 1224 self.set_data([self.current_plottable]) … … 1284 1228 #self.parent.set_perspective(self.perspective) 1285 1229 self.control_panel._on_invert(None) 1286 1230 1287 1231 def get_panels(self, parent): 1288 1232 """ … … 1290 1234 """ 1291 1235 from inversion_panel import InversionControl 1292 1236 1293 1237 self.parent = parent 1294 self.frame = MDIFrame(self.parent, None, 'None', (100, 200)) 1295 self.control_panel = InversionControl(self.frame, -1, 1238 self.frame = MDIFrame(self.parent, None, 'None', (100, 200)) 1239 self.control_panel = InversionControl(self.frame, -1, 1296 1240 style=wx.RAISED_BORDER, 1297 1241 standalone=self.standalone) … … 1304 1248 self.perspective = [] 1305 1249 self.perspective.append(self.control_panel.window_name) 1306 1250 1307 1251 return [self.control_panel] 1308 1252 1309 1253 def set_data(self, data_list=None): 1310 1254 """ … … 1326 1270 data_1d_list.append(data) 1327 1271 else: 1328 error_msg += " %s 1329 str(data.__class__.__name__))1272 error_msg += " %s type %s \n" % (str(data.name), 1273 str(data.__class__.__name__)) 1330 1274 data_2d_list.append(data) 1331 1275 if len(data_2d_list) > 0: … … 1333 1277 msg += error_msg 1334 1278 if len(data_1d_list) == 0: 1335 wx.PostEvent(self.parent, 1336 StatusEvent(status=msg, info='error')) 1279 wx.PostEvent(self.parent, StatusEvent(status=msg, info='error')) 1337 1280 return 1338 1281 msg += "Prview does not allow multiple data!\n" … … 1348 1291 if data is None: 1349 1292 msg += "PrView receives no data. \n" 1350 wx.PostEvent(self.parent, 1351 StatusEvent(status=msg, info='error')) 1293 wx.PostEvent(self.parent, StatusEvent(status=msg, info='error')) 1352 1294 return 1353 1295 if issubclass(data.__class__, Data1D): 1354 1296 try: 1355 wx.PostEvent(self.parent, NewPlotEvent(action='remove',1356 group_id=GROUP_ID_IQ_DATA,1357 id=self.data_id))1358 1297 wx.PostEvent(self.parent, 1298 NewPlotEvent(action='remove', 1299 group_id=GROUP_ID_IQ_DATA, 1300 id=self.data_id)) 1359 1301 self.data_id = data.id 1360 1302 self.control_panel._change_file(evt=None, data=data) 1361 1303 except: 1362 1304 msg = "Prview Set_data: " + str(sys.exc_value) 1363 wx.PostEvent(self.parent, StatusEvent(status=msg, 1364 info="error")) 1365 else: 1305 wx.PostEvent(self.parent, StatusEvent(status=msg, info="error")) 1306 else: 1366 1307 msg = "Pr cannot be computed for data of " 1367 1308 msg += "type %s" % (data_list[0].__class__.__name__) 1368 wx.PostEvent(self.parent, 1369 StatusEvent(status=msg, info='error')) 1309 wx.PostEvent(self.parent, StatusEvent(status=msg, info='error')) 1370 1310 else: 1371 1311 msg = "Pr contain no data" 1372 1312 wx.PostEvent(self.parent, StatusEvent(status=msg, info='warning')) 1373 1313 1374 1314 def post_init(self): 1375 1315 """ … … 1379 1319 if self.standalone: 1380 1320 self.parent.set_perspective(self.perspective) 1381 1382 if __name__ == "__main__":1383 i = Plugin()1384 print i.perform_estimateNT()1385 1386 1387 1388
Note: See TracChangeset
for help on using the changeset viewer.