- Timestamp:
- Apr 27, 2017 8:39:35 AM (8 years ago)
- Branches:
- 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
- Children:
- 0215e0a
- Parents:
- 98b13f72
- Location:
- src/sas/qtgui/Perspectives/Fitting
- Files:
-
- 2 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/Perspectives/Fitting/FittingLogic.py
r4ff5e35 r180bd54 27 27 self._data = value 28 28 self.data_is_loaded = True 29 30 def isLoadedData(self): 31 """ accessor """ 32 return self.data_is_loaded 29 33 30 34 def createDefault1dData(self, interval, tab_id=0): -
src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
r1970780 r180bd54 231 231 res = (fn - gn) / en 232 232 except ValueError: 233 print "Chi2 calculations: Unmatched lengths %s, %s, %s" % (len(fn), len(gn), len(en))233 #print "Chi2 calculations: Unmatched lengths %s, %s, %s" % (len(fn), len(gn), len(en)) 234 234 return None 235 235 … … 248 248 249 249 # 1d theory from model_thread is only in the range of index 250 if current_data.dy ==None or current_data.dy == []:250 if current_data.dy is None or current_data.dy == []: 251 251 dy = numpy.ones(len(current_data.y)) 252 252 else: 253 if weight == None: 254 dy = numpy.ones(len(current_data.y)) 255 else: 256 dy = weight 253 dy = weight if weight is not None else numpy.ones(len(current_data.y)) 257 254 dy[dy == 0] = 1 258 255 fn = current_data.y[index][0] … … 261 258 # build residuals 262 259 residuals = Data1D() 263 try:260 if len(fn) == len(gn): 264 261 y = (fn - gn)/en 265 262 residuals.y = -y 266 except: 267 msg = "ResidualPlot Error: different # of data points in theory" 268 print msg 263 else: 269 264 y = (fn - gn[index][0]) / en 270 265 residuals.y = y 266 267 #try: 268 # y = (fn - gn)/en 269 # residuals.y = -y 270 #except ValueError: 271 # msg = "ResidualPlot Error: different number of data points in theory" 272 # print msg 273 # y = (fn - gn[index][0]) / en 274 # residuals.y = y 271 275 residuals.x = current_data.x[index][0] 272 276 residuals.dy = numpy.ones(len(residuals.y)) … … 296 300 fn = current_data.data 297 301 gn = reference_data.data 298 if weight == None: 299 en = current_data.err_data 300 else: 301 en = weight 302 en = current_data.err_data if weight is None else weight 302 303 residuals.data = (fn - gn) / en 303 304 residuals.qx_data = current_data.qx_data -
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
- Property mode changed from 100755 to 100644
r98b13f72 r180bd54 2 2 import json 3 3 import os 4 import numpy 4 import numpy as np 5 5 from collections import defaultdict 6 6 from itertools import izip … … 31 31 from sas.qtgui.Perspectives.Fitting import FittingUtilities 32 32 from SmearingWidget import SmearingWidget 33 from OptionsWidget import OptionsWidget 33 34 34 35 TAB_MAGNETISM = 4 … … 37 38 CATEGORY_STRUCTURE = "Structure Factor" 38 39 STRUCTURE_DEFAULT = "None" 39 QMIN_DEFAULT = 0.000540 QMAX_DEFAULT = 0.541 NPTS_DEFAULT = 5042 40 43 41 class FittingWidget(QtGui.QWidget, Ui_FittingWidgetUI): … … 69 67 # Parameters to fit 70 68 self.parameters_to_fit = None 71 # Weight radio box group 72 self.weightingGroup = QtGui.QButtonGroup() 69 # Fit options 70 self.q_range_min = 0.005 71 self.q_range_max = 0.1 72 self.npts = 25 73 self.log_points = False 74 self.weighting = 0 73 75 74 76 # Which tab is this widget displayed in? … … 78 80 self.current_shell_displayed = 0 79 81 self.has_error_column = False 80 81 # Range parameters82 self.q_range_min = QMIN_DEFAULT83 self.q_range_max = QMAX_DEFAULT84 self.npts = NPTS_DEFAULT85 82 86 83 # Main Data[12]D holder … … 92 89 self.communicate = self.parent.communicate 93 90 91 # Options widget 92 layout = QtGui.QGridLayout() 93 self.options_widget = OptionsWidget(self, self.logic) 94 layout.addWidget(self.options_widget) 95 self.tabOptions.setLayout(layout) 96 94 97 # Smearing widget 95 98 layout = QtGui.QGridLayout() 96 99 self.smearing_widget = SmearingWidget(self) 97 100 layout.addWidget(self.smearing_widget) 98 #self.tabFitting.removeTab(2) 99 self.tabFitting.insertTab(2, self.smearing_widget, "Resolution") 101 self.tabResolution.setLayout(layout) 100 102 101 103 # Define bold font for use in various controls … … 186 188 self.updateQRange() 187 189 self.cmdFit.setEnabled(True) 188 self.boxWeighting.setEnabled(True)189 self.cmdMaskEdit.setEnabled(True)190 # Switch off txtNpts related controls191 self.txtNpts.setEnabled(False)192 self.txtNptsFit.setEnabled(False)193 self.chkLogData.setEnabled(False)194 190 # Switch off Data2D control 195 191 self.chk2DView.setEnabled(False) 196 192 self.chk2DView.setVisible(False) 197 193 self.chkMagnetism.setEnabled(True) 198 199 # Weighting controls 200 if self.is2D: 201 if self.logic.data.err_data is None or\ 202 numpy.all(err == 1 for err in self.logic.data.err_data) or \ 203 not numpy.any(self.logic.data.err_data): 204 self.rbWeighting2.setEnabled(False) 205 self.rbWeighting1.setChecked(True) 206 else: 207 self.rbWeighting2.setEnabled(True) 208 self.rbWeighting2.setChecked(True) 209 else: 210 if self.logic.data.dy is None or\ 211 numpy.all(self.logic.data.dy == 1) or\ 212 not numpy.any(self.logic.data.dy): 213 self.rbWeighting2.setEnabled(False) 214 self.rbWeighting1.setChecked(True) 215 else: 216 self.rbWeighting2.setEnabled(True) 217 self.rbWeighting2.setChecked(True) 194 # Similarly on other tabs 195 self.options_widget.setEnablementOnDataLoad() 218 196 219 197 # Smearing tab … … 260 238 self.onSelectModel() 261 239 262 def toggleLogData(self, isChecked):263 """ Toggles between log and linear data sets """264 pass265 266 240 def initializeControls(self): 267 241 """ … … 270 244 self.cmdFit.setEnabled(False) 271 245 self.cmdPlot.setEnabled(True) 272 self. cmdComputePoints.setVisible(False) # probably redundant246 self.options_widget.cmdComputePoints.setVisible(False) # probably redundant 273 247 self.chkPolydispersity.setEnabled(True) 274 248 self.chkPolydispersity.setCheckState(False) … … 281 255 self.tabFitting.setTabEnabled(TAB_MAGNETISM, False) 282 256 self.lblChi2Value.setText("---") 283 # Group boxes284 self.boxWeighting.setEnabled(False)285 self.cmdMaskEdit.setEnabled(False)286 # Button groups287 self.weightingGroup.addButton(self.rbWeighting1)288 self.weightingGroup.addButton(self.rbWeighting2)289 self.weightingGroup.addButton(self.rbWeighting3)290 self.weightingGroup.addButton(self.rbWeighting4)291 257 # Smearing tab 292 258 self.smearing_widget.updateSmearing(self.data) 259 # Line edits in the option tab 260 self.updateQRange() 293 261 294 262 def initializeSignals(self): … … 304 272 self.chkPolydispersity.toggled.connect(self.togglePoly) 305 273 self.chkMagnetism.toggled.connect(self.toggleMagnetism) 306 self.chkLogData.toggled.connect(self.toggleLogData)307 274 # Buttons 308 275 self.cmdFit.clicked.connect(self.onFit) 309 276 self.cmdPlot.clicked.connect(self.onPlot) 310 self.cmdMaskEdit.clicked.connect(self.onMaskEdit)311 self.cmdReset.clicked.connect(self.onReset)312 # Line edits313 self.txtNpts.editingFinished.connect(self.onNpts)314 self.txtMinRange.editingFinished.connect(self.onMinRange)315 self.txtMaxRange.editingFinished.connect(self.onMaxRange)316 # Button groups317 self.weightingGroup.buttonClicked.connect(self.onWeightingChoice)318 277 319 278 # Respond to change in parameters from the UI … … 322 281 # TODO after the poly_model prototype accepted 323 282 #self._magnet_model.itemChanged.connect(self.onMagneticModelChange) 283 284 # Signals from separate tabs asking for replot 285 self.options_widget.plot_signal.connect(self.onOptionsUpdate) 324 286 325 287 def onSelectModel(self): … … 391 353 # Populate the models combobox 392 354 self.cbModel.addItems(sorted([model for (model, _) in model_list])) 393 394 def onWeightingChoice(self, button):395 """396 Update weighting in the fit state397 """398 button_id = button.group().checkedId()399 button_id = abs(button_id + 2)400 #self.fitPage.weighting = button_id401 print button_id402 355 403 356 def onPolyModelChange(self, item): … … 448 401 params_to_fit = self.parameters_to_fit 449 402 450 # Potential weights added 403 # Potential weights added directly to data 451 404 self.addWeightingToData(data) 452 405 453 406 # Potential smearing added 407 # Remember that smearing_min/max can be None -> 408 # deal with it until Python gets discriminated unions 454 409 smearing, accuracy, smearing_min, smearing_max = self.smearing_widget.state() 455 410 … … 512 467 res = res_list[0] 513 468 if res.fitness is None or \ 514 not n umpy.isfinite(res.fitness) or \515 n umpy.any(res.pvec == None) or \516 not n umpy.all(numpy.isfinite(res.pvec)):469 not np.isfinite(res.fitness) or \ 470 np.any(res.pvec == None) or \ 471 not np.all(np.isfinite(res.pvec)): 517 472 msg = "Fitting did not converge!!!" 518 473 self.communicate.statusBarUpdateSignal.emit(msg) … … 607 562 Plot the current set of data 608 563 """ 609 if self.data is None:564 if not self.data_is_loaded: 610 565 self.createDefaultDataset() 611 566 self.calculateQGridForModel() 612 567 613 def onNpts(self): 614 """ 615 Callback for number of points line edit update 616 """ 617 # assumes type/value correctness achieved with QValidator 618 try: 619 self.npts = int(self.txtNpts.text()) 620 except ValueError: 621 # TODO 622 # This will return the old value to model/view and return 623 # notifying the user about format available. 624 pass 625 # Force redisplay 626 if self.model_is_loaded: 627 self.onPlot() 628 629 def onMinRange(self): 630 """ 631 Callback for minimum range of points line edit update 632 """ 633 # assumes type/value correctness achieved with QValidator 634 try: 635 self.q_range_min = float(self.txtMinRange.text()) 636 except ValueError: 637 # TODO 638 # This will return the old value to model/view and return 639 # notifying the user about format available. 640 return 641 # set Q range labels on the main tab 642 #self.lblMinRangeDef.setText(str(self.q_range_min)) 643 if self.model_is_loaded: 644 self.onPlot() 645 646 def onMaxRange(self): 647 """ 648 Callback for maximum range of points line edit update 649 """ 650 # assumes type/value correctness achieved with QValidator 651 try: 652 self.q_range_max = float(self.txtMaxRange.text()) 653 except: 654 pass 655 # set Q range labels on the main tab 656 self.lblMaxRangeDef.setText(str(self.q_range_max)) 657 if self.model_is_loaded: 658 self.onPlot() 659 660 def onMaskEdit(self): 661 """ 662 Callback for running the mask editor 663 """ 664 pass 665 666 def onReset(self): 667 """ 668 Callback for resetting qmin/qmax 669 """ 670 pass 568 def onOptionsUpdate(self): 569 """ 570 Update local option values and replot 571 """ 572 self.q_range_min, self.q_range_max, self.npts, self.log_points, self.weighting = \ 573 self.options_widget.state() 574 self.onPlot() 671 575 672 576 def setDefaultStructureCombo(self): … … 686 590 # Create default datasets if no data passed 687 591 if self.is2D: 688 qmax = self.q_range_max/n umpy.sqrt(2)592 qmax = self.q_range_max/np.sqrt(2) 689 593 qstep = self.npts 690 594 self.logic.createDefault2dData(qmax, qstep, self.tab_id) 595 return 596 elif self.log_points: 597 qmin = -10.0 if self.q_range_min < 1.e-10 else np.log10(self.q_range_min) 598 qmax = 10.0 if self.q_range_max > 1.e10 else np.log10(self.q_range_max) 599 interval = np.logspace(start=qmin, stop=qmax, num=self.npts, endpoint=True, base=10.0) 691 600 else: 692 interval = n umpy.linspace(start=self.q_range_min, stop=self.q_range_max,693 694 601 interval = np.linspace(start=self.q_range_min, stop=self.q_range_max, 602 num=self.npts, endpoint=True) 603 self.logic.createDefault1dData(interval, self.tab_id) 695 604 696 605 def readCategoryInfo(self): … … 745 654 """ 746 655 Adds weighting contribution to fitting data 747 """ 748 # Check the state of the Weighting radio buttons 749 button_id = self.weightingGroup.checkedId() 750 # Cast the id to a valid index 751 button_id = abs(button_id + 2) 752 if button_id == 0: 753 # No weight added 754 return 656 #""" 755 657 # Send original data for weighting 756 weight = get_weight(data=data, is2d=self.is2D, flag=button_id) 757 if self.is2D: 758 data.err_data = weight 759 else: 760 data.dy = weight 658 weight = get_weight(data=data, is2d=self.is2D, flag=self.weighting) 659 update_module = data.err_data if self.is2D else data.dy 660 update_module = weight 761 661 762 662 def updateQRange(self): … … 770 670 self.lblMaxRangeDef.setText(str(self.q_range_max)) 771 671 # set Q range labels on the options tab 772 self.txtMaxRange.setText(str(self.q_range_max)) 773 self.txtMinRange.setText(str(self.q_range_min)) 774 self.txtNpts.setText(str(self.npts)) 775 self.txtNptsFit.setText(str(self.npts)) 672 self.options_widget.updateQRange(self.q_range_min, self.q_range_max, self.npts) 776 673 777 674 def SASModelToQModel(self, model_name, structure_factor=None): … … 959 856 Prepare the fitting data object, based on current ModelModel 960 857 """ 858 if self.kernel_module is None: 859 return 961 860 # Awful API to a backend method. 962 861 method = self.methodCalculateForData()(data=self.data, -
src/sas/qtgui/Perspectives/Fitting/SmearingWidget.py
- Property mode changed from 100755 to 100644
r98b13f72 r180bd54 42 42 43 43 # Have we loaded data yet? If so, what kind 44 self. is_data = None44 self.have_data = None 45 45 # Local model for holding data 46 46 self.model = None … … 96 96 elif isinstance(data, Data1D): 97 97 self.cbSmearing.addItems(SMEARING_1D) 98 self. is_data = Data1D98 self.have_data = Data1D 99 99 else: 100 100 self.cbSmearing.addItems(SMEARING_2D) 101 self. is_data = Data2D101 self.have_data = Data2D 102 102 self.cbSmearing.setCurrentIndex(0) 103 103 … … 120 120 Respond to model change by updating 121 121 """ 122 print "MODEL CHANGED for property: %s. The value is now: %s" % \123 (MODEL[top.row()], str(self.model.item(top.row()).text()))122 #print "MODEL CHANGED for property: %s. The value is now: %s" % \ 123 # (MODEL[top.row()], str(self.model.item(top.row()).text())) 124 124 pass 125 125 … … 140 140 Accuracy combobox visibility 141 141 """ 142 if self. is_data == Data2D and self.cbSmearing.currentIndex() == 1:142 if self.have_data == Data2D and self.cbSmearing.currentIndex() == 1: 143 143 self.cbAccuracy.setVisible(True) 144 144 else: … … 165 165 # or model-held values 166 166 smearing = str(self.model.item(MODEL.index('SMEARING')).text()) 167 accuracy = str(self.model.item(MODEL.index('ACCURACY')).text()) 168 d_down = float(self.model.item(MODEL.index('PINHOLE_MIN')).text()) 169 d_up = float(self.model.item(MODEL.index('PINHOLE_MAX')).text()) 167 accuracy = "" 168 d_down = None 169 d_up = None 170 if smearing != "None": 171 accuracy = str(self.model.item(MODEL.index('ACCURACY')).text()) 172 try: 173 d_down = float(self.model.item(MODEL.index('PINHOLE_MIN')).text()) 174 except ValueError: 175 d_down = None 176 try: 177 d_up = float(self.model.item(MODEL.index('PINHOLE_MAX')).text()) 178 except ValueError: 179 d_up = None 170 180 171 181 return (smearing, accuracy, d_down, d_up) -
src/sas/qtgui/Perspectives/Fitting/UI/FittingWidgetUI.ui
re1e3e09 r180bd54 351 351 </layout> 352 352 </widget> 353 <widget class="QWidget" name=" QRanges">353 <widget class="QWidget" name="tabOptions"> 354 354 <attribute name="title"> 355 355 <string>Fit Options</string> 356 356 </attribute> 357 <layout class="QGridLayout" name="gridLayout_7"> 358 <item row="0" column="0"> 359 <widget class="QGroupBox" name="groupBox"> 360 <property name="title"> 361 <string>Fitting range</string> 362 </property> 363 <layout class="QGridLayout" name="gridLayout_4"> 364 <item row="0" column="0" rowspan="2"> 365 <layout class="QGridLayout" name="gridLayout_3"> 366 <item row="0" column="0"> 367 <widget class="QLabel" name="label_5"> 368 <property name="text"> 369 <string>Min range</string> 370 </property> 371 </widget> 372 </item> 373 <item row="0" column="1"> 374 <widget class="QLineEdit" name="txtMinRange"/> 375 </item> 376 <item row="0" column="2"> 377 <widget class="QLabel" name="label_7"> 378 <property name="text"> 379 <string><html><head/><body><p>Ã 380 <span style=" vertical-align:super;">-1</span></p></body></html></string> 381 </property> 382 </widget> 383 </item> 384 <item row="1" column="0"> 385 <widget class="QLabel" name="label_6"> 386 <property name="text"> 387 <string>Max range</string> 388 </property> 389 </widget> 390 </item> 391 <item row="1" column="1"> 392 <widget class="QLineEdit" name="txtMaxRange"/> 393 </item> 394 <item row="1" column="2"> 395 <widget class="QLabel" name="label_8"> 396 <property name="text"> 397 <string><html><head/><body><p>Ã 398 <span style=" vertical-align:super;">-1</span></p></body></html></string> 399 </property> 400 </widget> 401 </item> 402 </layout> 403 </item> 404 <item row="0" column="1" rowspan="2"> 405 <spacer name="horizontalSpacer_5"> 406 <property name="orientation"> 407 <enum>Qt::Horizontal</enum> 408 </property> 409 <property name="sizeHint" stdset="0"> 410 <size> 411 <width>217</width> 412 <height>20</height> 413 </size> 414 </property> 415 </spacer> 416 </item> 417 <item row="0" column="2"> 418 <widget class="QPushButton" name="cmdReset"> 419 <property name="text"> 420 <string>Reset</string> 421 </property> 422 </widget> 423 </item> 424 <item row="1" column="2"> 425 <widget class="QPushButton" name="cmdMaskEdit"> 426 <property name="text"> 427 <string>Mask Editor</string> 428 </property> 429 </widget> 430 </item> 431 </layout> 432 </widget> 433 </item> 434 <item row="1" column="0"> 435 <widget class="QGroupBox" name="groupBox_2"> 436 <property name="title"> 437 <string>Data points</string> 438 </property> 439 <layout class="QGridLayout" name="gridLayout_6"> 440 <item row="0" column="0"> 441 <layout class="QGridLayout" name="gridLayout_5"> 442 <item row="0" column="0"> 443 <widget class="QLabel" name="label_10"> 444 <property name="text"> 445 <string>Npts</string> 446 </property> 447 </widget> 448 </item> 449 <item row="0" column="1"> 450 <widget class="QLineEdit" name="txtNpts"/> 451 </item> 452 <item row="0" column="2"> 453 <widget class="QCheckBox" name="chkLogData"> 454 <property name="text"> 455 <string>Log spaced points</string> 456 </property> 457 </widget> 458 </item> 459 <item row="1" column="0"> 460 <widget class="QLabel" name="label_11"> 461 <property name="text"> 462 <string>Npts(Fit)</string> 463 </property> 464 </widget> 465 </item> 466 <item row="1" column="1"> 467 <widget class="QLineEdit" name="txtNptsFit"/> 468 </item> 469 <item row="2" column="0"> 470 <widget class="QLabel" name="label_12"> 471 <property name="text"> 472 <string><html><head/><body><p>Ï<span style=" vertical-align:super;">2</span>/Npts</p></body></html></string> 473 </property> 474 </widget> 475 </item> 476 <item row="2" column="1"> 477 <widget class="QLineEdit" name="txtChi2"/> 478 </item> 479 <item row="2" column="3"> 480 <widget class="QPushButton" name="cmdComputePoints"> 481 <property name="text"> 482 <string>Compute</string> 483 </property> 484 </widget> 485 </item> 486 <item row="1" column="2"> 487 <spacer name="horizontalSpacer_7"> 488 <property name="orientation"> 489 <enum>Qt::Horizontal</enum> 490 </property> 491 <property name="sizeHint" stdset="0"> 492 <size> 493 <width>40</width> 494 <height>20</height> 495 </size> 496 </property> 497 </spacer> 498 </item> 499 </layout> 500 </item> 501 </layout> 502 </widget> 503 </item> 504 <item row="2" column="0"> 505 <widget class="QGroupBox" name="boxWeighting"> 506 <property name="title"> 507 <string>Weighting</string> 508 </property> 509 <layout class="QGridLayout" name="gridLayout_12"> 510 <item row="0" column="0"> 511 <layout class="QVBoxLayout" name="verticalLayout"> 512 <item> 513 <widget class="QRadioButton" name="rbWeighting1"> 514 <property name="text"> 515 <string>None</string> 516 </property> 517 <property name="checked"> 518 <bool>true</bool> 519 </property> 520 </widget> 521 </item> 522 <item> 523 <widget class="QRadioButton" name="rbWeighting2"> 524 <property name="text"> 525 <string>Use dI Data</string> 526 </property> 527 </widget> 528 </item> 529 <item> 530 <widget class="QRadioButton" name="rbWeighting3"> 531 <property name="text"> 532 <string>Use |sqrt(I Data)|</string> 533 </property> 534 </widget> 535 </item> 536 <item> 537 <widget class="QRadioButton" name="rbWeighting4"> 538 <property name="text"> 539 <string>Use |I Data|</string> 540 </property> 541 </widget> 542 </item> 543 </layout> 544 </item> 545 </layout> 546 </widget> 547 </item> 548 <item row="3" column="0"> 549 <spacer name="verticalSpacer"> 550 <property name="orientation"> 551 <enum>Qt::Vertical</enum> 552 </property> 553 <property name="sizeHint" stdset="0"> 554 <size> 555 <width>20</width> 556 <height>347</height> 557 </size> 558 </property> 559 </spacer> 560 </item> 561 </layout> 357 </widget> 358 <widget class="QWidget" name="tabResolution"> 359 <attribute name="title"> 360 <string>Resolution</string> 361 </attribute> 562 362 </widget> 563 363 <widget class="QWidget" name="tab_4">
Note: See TracChangeset
for help on using the changeset viewer.