Changeset 57ad773 in sasview for src/sas/qtgui/Perspectives/Inversion
- Timestamp:
- Oct 28, 2017 10:02:15 AM (7 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:
- d132f33
- Parents:
- e7651ff
- Location:
- src/sas/qtgui/Perspectives/Inversion
- Files:
-
- 2 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/Perspectives/Inversion/InversionLogic.py
re7651ff r57ad773 1 import math 2 import pylab 1 3 import numpy as np 2 4 3 5 from sas.qtgui.Plotting.PlotterData import Data1D 6 7 PR_FIT_LABEL = r"$P_{fit}(r)$" 8 PR_LOADED_LABEL = r"$P_{loaded}(r)$" 9 IQ_DATA_LABEL = r"$I_{obs}(q)$" 10 IQ_FIT_LABEL = r"$I_{fit}(q)$" 11 IQ_SMEARED_LABEL = r"$I_{smeared}(q)$" 12 GROUP_ID_IQ_DATA = r"$I_{obs}(q)$" 13 GROUP_ID_PR_FIT = r"$P_{fit}(r)$" 4 14 5 15 … … 9 19 No QStandardModelIndex here. 10 20 """ 21 22 # TODO: Add way to change this value 23 _pr_n_pts = 51 11 24 12 25 def __init__(self, data=None): … … 30 43 return self.data_is_loaded 31 44 32 def new1DPlot(self, return_data):45 def new1DPlot(self, out, pr, q=None): 33 46 """ 34 47 Create a new 1D data instance based on fitting results 35 48 """ 36 # Unpack return data from Calc1D37 x, y, page_id, state, weight,\38 fid, toggle_mode_on, \39 elapsed, index, model,\40 data, update_chisqr, source = return_data41 49 42 # Create the new plot 43 new_plot = Data1D(x=x, y=y) 44 new_plot.is_data = False 45 new_plot.dy = np.zeros(len(y)) 46 _yaxis, _yunit = data.get_yaxis() 47 _xaxis, _xunit = data.get_xaxis() 50 qtemp = pr.x 51 if q is not None: 52 qtemp = q 48 53 49 new_plot.group_id = data.group_id 50 new_plot.id = data.name 51 new_plot.name = model.name + " [" + data.name + "]" 52 new_plot.title = new_plot.name 53 new_plot.xaxis(_xaxis, _xunit) 54 new_plot.yaxis(_yaxis, _yunit) 54 # Make a plot 55 maxq = max(qtemp) 56 57 minq = min(qtemp) 58 59 # Check for user min/max 60 if pr.q_min is not None and maxq >= pr.q_min >= minq: 61 minq = pr.q_min 62 if pr.q_max is not None and maxq >= pr.q_max >= minq: 63 maxq = pr.q_max 64 65 x = pylab.arange(minq, maxq, maxq / 301.0) 66 y = np.zeros(len(x)) 67 err = np.zeros(len(x)) 68 for i in range(len(x)): 69 value = pr.iq(out, x[i]) 70 y[i] = value 71 try: 72 err[i] = math.sqrt(math.fabs(value)) 73 except: 74 err[i] = 1.0 75 print("Error getting error", value, x[i]) 76 77 new_plot = Data1D(x, y) 78 new_plot.name = IQ_FIT_LABEL 79 new_plot.xaxis("\\rm{Q}", 'A^{-1}') 80 new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") 81 title = "I(q)" 82 new_plot.title = title 83 84 # If we have a group ID, use it 85 if 'plot_group_id' in pr.info: 86 new_plot.group_id = pr.info["plot_group_id"] 87 new_plot.id = IQ_FIT_LABEL 88 89 # If we have used slit smearing, plot the smeared I(q) too 90 if pr.slit_width > 0 or pr.slit_height > 0: 91 x = pylab.arange(minq, maxq, maxq / 301.0) 92 y = np.zeros(len(x)) 93 err = np.zeros(len(x)) 94 for i in range(len(x)): 95 value = pr.iq_smeared(pr.out, x[i]) 96 y[i] = value 97 try: 98 err[i] = math.sqrt(math.fabs(value)) 99 except: 100 err[i] = 1.0 101 print("Error getting error", value, x[i]) 102 103 new_plot = Data1D(x, y) 104 new_plot.name = IQ_SMEARED_LABEL 105 new_plot.xaxis("\\rm{Q}", 'A^{-1}') 106 new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") 107 # If we have a group ID, use it 108 if 'plot_group_id' in pr.info: 109 new_plot.group_id = pr.info["plot_group_id"] 110 new_plot.id = IQ_SMEARED_LABEL 111 new_plot.title = title 112 113 return new_plot 114 115 def newPRPlot(self, out, pr, cov=None): 116 """ 117 """ 118 # Show P(r) 119 x = pylab.arange(0.0, pr.d_max, pr.d_max / self._pr_n_pts) 120 121 y = np.zeros(len(x)) 122 dy = np.zeros(len(x)) 123 y_true = np.zeros(len(x)) 124 125 total = 0.0 126 pmax = 0.0 127 cov2 = np.ascontiguousarray(cov) 128 129 for i in range(len(x)): 130 if cov2 is None: 131 value = pr.pr(out, x[i]) 132 else: 133 (value, dy[i]) = pr.pr_err(out, cov2, x[i]) 134 total += value * pr.d_max / len(x) 135 136 # keep track of the maximum P(r) value 137 if value > pmax: 138 pmax = value 139 140 y[i] = value 141 142 # if self._normalize_output == True: 143 # y = y / total 144 # dy = dy / total 145 # elif self._scale_output_unity == True: 146 # y = y / pmax 147 # dy = dy / pmax 148 149 if cov2 is None: 150 new_plot = Data1D(x, y) 151 else: 152 new_plot = Data1D(x, y, dy=dy) 153 new_plot.name = PR_FIT_LABEL 154 new_plot.xaxis("\\rm{r}", 'A') 155 new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}") 156 new_plot.title = "P(r) fit" 157 new_plot.id = PR_FIT_LABEL 158 # Make sure that the plot is linear 159 new_plot.xtransform = "x" 160 new_plot.ytransform = "y" 161 new_plot.group_id = GROUP_ID_PR_FIT 55 162 56 163 return new_plot … … 67 174 return the npts contains in data 68 175 """ 69 qmin, qmax , npts = None,None, None176 qmin, qmax = None, None 70 177 if isinstance(data, Data1D): 71 178 try: 72 179 qmin = min(data.x) 73 180 qmax = max(data.x) 74 npts = len(data.x)75 181 except (ValueError, TypeError): 76 182 msg = "Unable to find min/max/length of \n data named %s" % \ … … 88 194 raise ValueError, msg 89 195 qmax = np.sqrt(x * x + y * y) 90 npts = len(data.data) 91 return qmin, qmax, npts 196 return qmin, qmax -
src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py
re7651ff r57ad773 12 12 # pr inversion GUI elements 13 13 from InversionUtils import WIDGETS 14 import UI.Tabbed PrInversionUI15 from UI.Tabbed PrInversionUI import Ui_PrInversion14 import UI.TabbedInversionUI 15 from UI.TabbedInversionUI import Ui_PrInversion 16 16 from InversionLogic import InversionLogic 17 17 … … 118 118 """Connect the use controls to their appropriate methods""" 119 119 self.enableButtons() 120 self.checkBgdClicked(False)121 120 # TODO: enable the drop down box once batch is working 122 121 self.dataList.setEnabled(False) … … 130 129 self.noOfTermsSuggestionButton.clicked.connect(self.acceptNoTerms) 131 130 self.explorerButton.clicked.connect(self.openExplorerWindow) 131 self.backgroundInput.textChanged.connect( 132 lambda: self._calculator.set_est_bck(int(is_float( 133 str(self.backgroundInput.text()))))) 134 self.minQInput.textChanged.connect( 135 lambda: self._calculator.set_qmin(is_float( 136 str(self.minQInput.text())))) 137 self.regularizationConstantInput.textChanged.connect( 138 lambda: self._calculator.set_alpha(is_float( 139 str(self.regularizationConstantInput.text())))) 140 self.maxDistanceInput.textChanged.connect( 141 lambda: self._calculator.set_dmax(is_float( 142 str(self.maxDistanceInput.text())))) 143 self.maxQInput.textChanged.connect( 144 lambda: self._calculator.set_qmax(is_float( 145 str(self.maxQInput.text())))) 146 self.slitHeightInput.textChanged.connect( 147 lambda: self._calculator.set_slit_height(is_float( 148 str(self.slitHeightInput.text())))) 149 self.slitWidthInput.textChanged.connect( 150 lambda: self._calculator.set_slit_width(is_float( 151 str(self.slitHeightInput.text())))) 132 152 self.model.itemChanged.connect(self.model_changed) 153 self.estimateBgd.setChecked(True) 133 154 134 155 def setupMapper(self): … … 255 276 256 277 def update_calculator(self): 257 """Update all p(r) params . Take all GUI values as an override"""278 """Update all p(r) params""" 258 279 self._calculator.set_x(self._data_set.x) 259 280 self._calculator.set_y(self._data_set.y) 260 281 self._calculator.set_err(self._data_set.dy) 261 self._calculator.set_qmin(is_float(UI.TabbedPrInversionUI._fromUtf8(262 self.minQInput.text())))263 self._calculator.set_qmax(is_float(UI.TabbedPrInversionUI._fromUtf8(264 self.maxQInput.text())))265 self._calculator.set_alpha(is_float(UI.TabbedPrInversionUI._fromUtf8(266 self.regularizationConstantInput.text())))267 self._calculator.set_dmax(is_float(UI.TabbedPrInversionUI._fromUtf8(268 self.maxDistanceInput.text())))269 self._calculator.set_est_bck(int(is_float(270 UI.TabbedPrInversionUI._fromUtf8(self.backgroundInput.text()))))271 self._calculator.set_slit_height(is_float(272 UI.TabbedPrInversionUI._fromUtf8(self.slitHeightInput.text())))273 self._calculator.set_slit_width(is_float(274 UI.TabbedPrInversionUI._fromUtf8(self.slitWidthInput.text())))275 282 276 283 def _calculation(self): … … 278 285 Calculate the P(r) for every data set in the data list 279 286 """ 280 # Pull in any GUI changesbefore running the calculations287 # Set data before running the calculations 281 288 self.update_calculator() 282 289 # Run … … 287 294 if not self.mapper: 288 295 return 289 # TODO: Update plots 296 if self.pr_plot is not None: 297 title = self.pr_plot.name 298 GuiUtils.updateModelItemWithPlot( 299 self._data, QtCore.QVariant(self.pr_plot), title) 300 if self.data_plot is not None: 301 title = self.data_plot.name 302 GuiUtils.updateModelItemWithPlot( 303 self._data, QtCore.QVariant(self.data_plot), title) 290 304 self.mapper.toFirst() 291 305 … … 303 317 self._helpView.show() 304 318 305 def checkBgdClicked(self, boolean=None): 306 if boolean or self.manualBgd.isChecked(): 307 self.manualBgd.setChecked(True) 308 self.toggleBgd(self.manualBgd) 309 else: 310 self.estimateBgd.setChecked(True) 311 self.toggleBgd(self.estimateBgd) 312 313 def toggleBgd(self, item=None): 319 def toggleBgd(self): 314 320 """ 315 321 Toggle the background between manual and estimated 316 322 :param item: gui item that was triggered 317 323 """ 318 if not item: 319 self.checkBgdClicked() 320 elif isinstance(item, QtGui.QRadioButton): 321 if item is self.estimateBgd: 322 self.backgroundInput.setEnabled(False) 323 else: 324 self.backgroundInput.setEnabled(True) 324 sender = self.sender() 325 if sender is self.estimateBgd: 326 self.backgroundInput.setEnabled(False) 327 else: 328 self.backgroundInput.setEnabled(True) 325 329 326 330 def openExplorerWindow(self): … … 353 357 self._data = data 354 358 self._data_set = GuiUtils.dataFromItem(data) 355 self.enableButtons()356 359 self.populateDataComboBox(self._data_set.filename) 357 360 358 361 # Estimate initial values from data 359 362 self.performEstimate() 360 self.logic.data(self._calculator) 361 362 self._manager.createGuiData(None) 363 364 # TODO: Finish plotting 365 if self.pr_plot is None: 366 self.pr_plot = None 367 #self.pr_plot = self.logic.new1DPlot(self._calculator) 368 if self.data_plot is None: 369 self.data_plot = None 370 371 qmin, qmax, _ = self.logic.computeDataRange() 372 title = self._data.filename 363 self.logic = InversionLogic(self._data_set) 364 365 qmin, qmax = self.logic.computeDataRange() 373 366 374 367 self.model.setItem(WIDGETS.W_QMIN, QtGui.QStandardItem( … … 376 369 self.model.setItem(WIDGETS.W_QMAX, QtGui.QStandardItem( 377 370 "{:.4g}".format(qmax))) 378 #reactor.callFromThread(GuiUtils.updateModelItemWithPlot, 379 # self._model_item, self._communicator, title)371 372 self.enableButtons() 380 373 381 374 # TODO: Only load 1st data until batch mode working. Thus, break … … 395 388 self.calc_thread.stop() 396 389 pr = self._calculator.clone() 397 nfunc = int(UI.Tabbed PrInversionUI._fromUtf8(390 nfunc = int(UI.TabbedInversionUI._fromUtf8( 398 391 self.noOfTermsInput.text())) 399 392 self.calc_thread = CalcPr(pr, nfunc, … … 418 411 pr.slit_height = 0.0 419 412 pr.slit_width = 0.0 420 nfunc = int(UI.Tabbed PrInversionUI._fromUtf8(413 nfunc = int(UI.TabbedInversionUI._fromUtf8( 421 414 self.noOfTermsInput.text())) 422 415 self.estimation_thread = EstimateNT(pr, nfunc, … … 440 433 self.estimation_thread.stop() 441 434 pr = self._calculator.clone() 442 nfunc = int(UI.Tabbed PrInversionUI._fromUtf8(435 nfunc = int(UI.TabbedInversionUI._fromUtf8( 443 436 self.noOfTermsInput.text())) 444 437 self.estimation_thread = EstimatePr(pr, nfunc, … … 503 496 """ 504 497 # Save useful info 505 # Keep a copy of the last result506 self._last_calculator = pr.clone()507 508 # Save Pr invertor509 self._calculator = pr510 498 cov = np.ascontiguousarray(cov) 499 pr.cov = cov 500 pr.out = out 501 pr.elapsed = elapsed 511 502 512 503 # Show result on control panel … … 533 524 # Display results tab 534 525 self.PrTabWidget.setCurrentIndex(1) 526 # Save Pr invertor 527 self._calculator = pr 528 # Append data to data list 535 529 self._data_list.append({self._data: pr}) 536 530 537 # TODO: Show plots - Really, this should be linked to the inputs, etc, 538 # TODO: so it should happen automagically 539 # Show I(q) fit 540 # self.show_iq(out, self._calculator) 541 # Show P(r) fit 542 # self.show_pr(out, self._calculator, cov) 531 if self.pr_plot is None: 532 self.pr_plot = self.logic.newPRPlot(out, self._calculator, cov) 533 if self.data_plot is None: 534 self.data_plot = self.logic.new1DPlot(out, self._calculator) 543 535 544 536 def _threadError(self, error):
Note: See TracChangeset
for help on using the changeset viewer.