- Timestamp:
- Oct 17, 2018 8:00:00 AM (6 years ago)
- Branches:
- ESS_GUI, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
- Children:
- 10d57f6
- Parents:
- 345b3b3 (diff), dd545d1 (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/qtgui
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/MainWindow/GuiManager.py
re258c53 refaf022 136 136 self.logDockWidget = QDockWidget("Log Explorer", self._workspace) 137 137 self.logDockWidget.setObjectName("LogDockWidget") 138 self.logDockWidget.visibilityChanged.connect(self.updateLogContextMenus) 139 138 140 139 141 self.listWidget = QTextBrowser() … … 178 180 logger.error("%s: could not load SasView models") 179 181 logger.error(traceback.format_exc()) 182 183 def updateLogContextMenus(self, visible=False): 184 """ 185 Modify the View/Data Explorer menu item text on widget visibility 186 """ 187 if visible: 188 self._workspace.actionHide_LogExplorer.setText("Hide Log Explorer") 189 else: 190 self._workspace.actionHide_LogExplorer.setText("Show Log Explorer") 180 191 181 192 def updateContextMenus(self, visible=False): … … 433 444 """ 434 445 # disable not yet fully implemented actions 435 self._workspace.actionOpen_Analysis.set Enabled(False)436 self._workspace.actionUndo.set Enabled(False)437 self._workspace.actionRedo.set Enabled(False)438 self._workspace.actionReset.set Enabled(False)439 self._workspace.actionStartup_Settings.set Enabled(False)440 self._workspace.actionImage_Viewer.set Enabled(False)441 self._workspace.actionCombine_Batch_Fit.set Enabled(False)442 self._workspace.actionFit_Results.set Enabled(False)446 self._workspace.actionOpen_Analysis.setVisible(False) 447 self._workspace.actionUndo.setVisible(False) 448 self._workspace.actionRedo.setVisible(False) 449 self._workspace.actionReset.setVisible(False) 450 self._workspace.actionStartup_Settings.setVisible(False) 451 self._workspace.actionImage_Viewer.setVisible(False) 452 self._workspace.actionCombine_Batch_Fit.setVisible(False) 453 self._workspace.actionFit_Results.setVisible(False) 443 454 # orientation viewer set to invisible SASVIEW-1132 444 455 self._workspace.actionOrientation_Viewer.setVisible(False) … … 467 478 self._workspace.actionCategory_Manager.triggered.connect(self.actionCategory_Manager) 468 479 self._workspace.actionHide_DataExplorer.triggered.connect(self.actionHide_DataExplorer) 480 self._workspace.actionHide_LogExplorer.triggered.connect(self.actionHide_LogExplorer) 469 481 # Tools 470 482 self._workspace.actionData_Operation.triggered.connect(self.actionData_Operation) … … 654 666 """ 655 667 if self.dockedFilesWidget.isVisible(): 656 #self._workspace.actionHide_DataExplorer.setText("Show Data Explorer")657 668 self.dockedFilesWidget.setVisible(False) 658 669 else: 659 #self._workspace.actionHide_DataExplorer.setText("Hide Data Explorer")660 670 self.dockedFilesWidget.setVisible(True) 671 pass 672 673 def actionHide_LogExplorer(self): 674 """ 675 Toggle Data Explorer vsibility 676 """ 677 if self.logDockWidget.isVisible(): 678 self.logDockWidget.setVisible(False) 679 else: 680 self.logDockWidget.setVisible(True) 661 681 pass 662 682 -
src/sas/qtgui/MainWindow/UI/MainWindowUI.ui
rfc5d2d7f refaf022 25 25 <y>0</y> 26 26 <width>915</width> 27 <height>2 6</height>27 <height>21</height> 28 28 </rect> 29 29 </property> … … 75 75 <addaction name="actionHide_Toolbar"/> 76 76 <addaction name="actionHide_DataExplorer"/> 77 <addaction name="actionHide_LogExplorer"/> 77 78 <addaction name="separator"/> 78 79 <addaction name="actionStartup_Settings"/> … … 565 566 </property> 566 567 </action> 568 <action name="actionHide_LogExplorer"> 569 <property name="text"> 570 <string>Hide Log Explorer</string> 571 </property> 572 </action> 567 573 </widget> 568 574 <resources/> -
src/sas/qtgui/Perspectives/Fitting/ConsoleUpdate.py
r7adc2a8 ra4ceeb7 147 147 model_name = str(self.result.model.name) 148 148 if m_flag and d_flag: 149 msg += "Data : %s \n" % (str(data_name))#, 150 #str(model_name)) 149 msg += "Data : %s \n" % (str(data_name)) 151 150 msg += str(self.result) 152 151 msg += "\n" 153 else:154 msg += "No result available\n"155 152 156 153 logging.info(msg) -
src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py
r345b3b3 rb95d748 102 102 103 103 def onParamCopy(self): 104 self.currentTab.on ParameterCopy("")104 self.currentTab.onCopyToClipboard("") 105 105 106 106 def onParamPaste(self): … … 108 108 109 109 def onExcelCopy(self): 110 self.currentTab.on ParameterCopy("Excel")110 self.currentTab.onCopyToClipboard("Excel") 111 111 112 112 def onLatexCopy(self): 113 self.currentTab.on ParameterCopy("Latex")113 self.currentTab.onCopyToClipboard("Latex") 114 114 115 115 def closeEvent(self, event): -
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
r3ab2105 rdd545d1 119 119 self.tab_id = tab_id 120 120 121 import sys 122 sys.excepthook = self.info 123 121 124 # Globals 122 125 self.initializeGlobals() … … 163 166 self.label_17.setStyleSheet(new_font) 164 167 self.label_19.setStyleSheet(new_font) 168 169 def info(self, type, value, tb): 170 logger.error("SasView threw exception: " + str(value)) 171 traceback.print_exception(type, value, tb) 165 172 166 173 @property … … 543 550 544 551 # Respond to change in parameters from the UI 545 self._model_model.itemChanged.connect(self.onMainParamsChange) 546 #self.constraintAddedSignal.connect(self.modifyViewOnConstraint) 547 self._poly_model.itemChanged.connect(self.onPolyModelChange) 548 self._magnet_model.itemChanged.connect(self.onMagnetModelChange) 552 self._model_model.dataChanged.connect(self.onMainParamsChange) 553 self._poly_model.dataChanged.connect(self.onPolyModelChange) 554 self._magnet_model.dataChanged.connect(self.onMagnetModelChange) 549 555 self.lstParams.selectionModel().selectionChanged.connect(self.onSelectionChanged) 550 556 … … 1207 1213 self.cbModel.addItems(sorted([model for (model, _) in model_list])) 1208 1214 1209 def onPolyModelChange(self, item):1215 def onPolyModelChange(self, top, bottom): 1210 1216 """ 1211 1217 Callback method for updating the main model and sasmodel 1212 1218 parameters with the GUI values in the polydispersity view 1213 1219 """ 1220 item = self._poly_model.itemFromIndex(top) 1214 1221 model_column = item.column() 1215 1222 model_row = item.row() … … 1278 1285 self._model_model.blockSignals(False) 1279 1286 1280 def onMagnetModelChange(self, item):1287 def onMagnetModelChange(self, top, bottom): 1281 1288 """ 1282 1289 Callback method for updating the sasmodel magnetic parameters with the GUI values 1283 1290 """ 1291 item = self._magnet_model.itemFromIndex(top) 1284 1292 model_column = item.column() 1285 1293 model_row = item.row() … … 1716 1724 # block signals temporarily, so we don't end up 1717 1725 # updating charts with every single model change on the end of fitting 1718 self._model_model. itemChanged.disconnect()1726 self._model_model.dataChanged.disconnect() 1719 1727 self.iterateOverModel(updateFittedValues) 1720 1728 self.iterateOverModel(updatePolyValues) 1721 self._model_model. itemChanged.connect(self.onMainParamsChange)1729 self._model_model.dataChanged.connect(self.onMainParamsChange) 1722 1730 1723 1731 def iterateOverPolyModel(self, func): … … 1771 1779 # block signals temporarily, so we don't end up 1772 1780 # updating charts with every single model change on the end of fitting 1773 self._poly_model. itemChanged.disconnect()1781 self._poly_model.dataChanged.disconnect() 1774 1782 self.iterateOverPolyModel(updateFittedValues) 1775 self._poly_model. itemChanged.connect(self.onPolyModelChange)1783 self._poly_model.dataChanged.connect(self.onPolyModelChange) 1776 1784 1777 1785 if self.has_poly_error_column: … … 1836 1844 # block signals temporarily, so we don't end up 1837 1845 # updating charts with every single model change on the end of fitting 1838 self._magnet_model. itemChanged.disconnect()1846 self._magnet_model.dataChanged.disconnect() 1839 1847 self.iterateOverMagnetModel(updateFittedValues) 1840 self._magnet_model. itemChanged.connect(self.onMagnetModelChange)1848 self._magnet_model.dataChanged.connect(self.onMagnetModelChange) 1841 1849 1842 1850 if self.has_magnet_error_column: … … 2272 2280 return False 2273 2281 2274 def onMainParamsChange(self, item):2282 def onMainParamsChange(self, top, bottom): 2275 2283 """ 2276 2284 Callback method for updating the sasmodel parameters with the GUI values 2277 2285 """ 2286 item = self._model_model.itemFromIndex(top) 2287 2278 2288 model_column = item.column() 2279 2289 … … 2301 2311 else: 2302 2312 parameter_name = str(self._model_model.data(name_index)) 2303 2304 # Update the parameter value - note: this supports +/-inf as well2305 self.kernel_module.params[parameter_name] = value2306 2313 2307 2314 # Update the parameter value - note: this supports +/-inf as well … … 3151 3158 # Update relevant models 3152 3159 self.setPolyModel() 3153 self.setMagneticModel() 3160 if self.canHaveMagnetism(): 3161 self.setMagneticModel() 3154 3162 3155 3163 def onShowSLDProfile(self): … … 3465 3473 #self._copy_parameters_state(self.fixed_param, self.state.fixed_param) 3466 3474 3467 def onParameterCopy(self, format=None): 3475 def onCopyToClipboard(self, format=None): 3476 """ 3477 Copy current fitting parameters into the clipboard 3478 using requested formatting: 3479 plain, excel, latex 3480 """ 3481 param_list = self.getFitParameters() 3482 if format=="": 3483 formatted_output = FittingUtilities.formatParameters(param_list) 3484 elif format == "Excel": 3485 formatted_output = FittingUtilities.formatParametersExcel(param_list[1:]) 3486 elif format == "Latex": 3487 formatted_output = FittingUtilities.formatParametersLatex(param_list[1:]) 3488 else: 3489 raise AttributeError("Bad parameter output format specifier.") 3490 3491 # Dump formatted_output to the clipboard 3492 cb = QtWidgets.QApplication.clipboard() 3493 cb.setText(formatted_output) 3494 3495 def getFitParameters(self, format=None): 3468 3496 """ 3469 3497 Copy current parameters into the clipboard … … 3472 3500 # first - regular params 3473 3501 param_list = [] 3474 3475 3502 param_list.append(['model_name', str(self.cbModel.currentText())]) 3503 3476 3504 def gatherParams(row): 3477 3505 """ … … 3479 3507 """ 3480 3508 param_name = str(self._model_model.item(row, 0).text()) 3509 3510 # Assure this is a parameter - must contain a checkbox 3511 if not self._model_model.item(row, 0).isCheckable(): 3512 # maybe it is a combobox item (multiplicity) 3513 try: 3514 index = self._model_model.index(row, 1) 3515 widget = self.lstParams.indexWidget(index) 3516 if widget is None: 3517 return 3518 if isinstance(widget, QtWidgets.QComboBox): 3519 # find the index of the combobox 3520 current_index = widget.currentIndex() 3521 param_list.append([param_name, 'None', str(current_index)]) 3522 except Exception as ex: 3523 pass 3524 return 3525 3481 3526 param_checked = str(self._model_model.item(row, 0).checkState() == QtCore.Qt.Checked) 3527 # Value of the parameter. In some cases this is the text of the combobox choice. 3482 3528 param_value = str(self._model_model.item(row, 1).text()) 3483 3529 param_error = None … … 3486 3532 column_offset = 0 3487 3533 if self.has_error_column: 3488 param_error = str(self._model_model.item(row, 2).text())3489 3534 column_offset = 1 3490 3491 3535 try: 3492 3536 param_min = str(self._model_model.item(row, 2+column_offset).text()) … … 3495 3539 pass 3496 3540 3497 param_list.append([param_name, param_checked, param_value, param_ error, param_min, param_max])3541 param_list.append([param_name, param_checked, param_value, param_min, param_max]) 3498 3542 3499 3543 def gatherPolyParams(row): … … 3507 3551 column_offset = 0 3508 3552 if self.has_poly_error_column: 3509 param_error = str(self._poly_model.item(row, 2).text())3510 3553 column_offset = 1 3511 3554 param_min = str(self._poly_model.item(row, 2+column_offset).text()) … … 3514 3557 param_nsigs = str(self._poly_model.item(row, 5+column_offset).text()) 3515 3558 param_fun = str(self._poly_model.item(row, 6+column_offset).text()).rstrip() 3559 index = self._poly_model.index(row, 6+column_offset) 3560 widget = self.lstPoly.indexWidget(index) 3561 if widget is not None and isinstance(widget, QtWidgets.QComboBox): 3562 param_fun = widget.currentText() 3516 3563 # width 3517 3564 name = param_name+".width" 3518 param_list.append([name, param_checked, param_value, param_ error,3519 param_npts, param_nsigs, param_ min, param_max, param_fun])3565 param_list.append([name, param_checked, param_value, param_min, param_max, 3566 param_npts, param_nsigs, param_fun]) 3520 3567 3521 3568 def gatherMagnetParams(row): … … 3529 3576 column_offset = 0 3530 3577 if self.has_magnet_error_column: 3531 param_error = str(self._magnet_model.item(row, 2).text())3532 3578 column_offset = 1 3533 3579 param_min = str(self._magnet_model.item(row, 2+column_offset).text()) 3534 3580 param_max = str(self._magnet_model.item(row, 3+column_offset).text()) 3535 param_list.append([param_name, param_checked, param_value, param_ error, param_min, param_max])3581 param_list.append([param_name, param_checked, param_value, param_min, param_max]) 3536 3582 3537 3583 self.iterateOverModel(gatherParams) … … 3541 3587 self.iterateOverMagnetModel(gatherMagnetParams) 3542 3588 3543 if format=="": 3544 formatted_output = FittingUtilities.formatParameters(param_list) 3545 elif format == "Excel": 3546 formatted_output = FittingUtilities.formatParametersExcel(param_list[1:]) 3547 elif format == "Latex": 3548 formatted_output = FittingUtilities.formatParametersLatex(param_list[1:]) 3549 else: 3550 raise AttributeError("Bad format specifier.") 3551 3552 # Dump formatted_output to the clipboard 3553 cb = QtWidgets.QApplication.clipboard() 3554 cb.setText(formatted_output) 3589 if self.kernel_module.is_multiplicity_model: 3590 param_list.append(['multiplicity', str(self.kernel_module.multiplicity)]) 3591 3592 # option tab 3593 param_list.append(['q_range_min', str(self.q_range_min)]) 3594 param_list.append(['q_range_max', str(self.q_range_max)]) 3595 param_list.append(['q_weighting', str(self.weighting)]) 3596 3597 # resolution 3598 smearing, accuracy, smearing_min, smearing_max = self.smearing_widget.state() 3599 index = self.smearing_widget.cbSmearing.currentIndex() 3600 param_list.append(['smearing', str(index)]) 3601 param_list.append(['smearing_min', str(smearing_min)]) 3602 param_list.append(['smearing_max', str(smearing_max)]) 3603 3604 # checkboxes, if required 3605 has_polydisp = self.chkPolydispersity.isChecked() 3606 has_magnetism = self.chkMagnetism.isChecked() 3607 has_chain = self.chkChainFit.isChecked() 3608 has_2D = self.chk2DView.isChecked() 3609 param_list.append(['polydisperse_params', str(has_polydisp)]) 3610 param_list.append(['magnetic_params', str(has_magnetism)]) 3611 param_list.append(['chainfit_params', str(has_chain)]) 3612 param_list.append(['2D_params', str(has_2D)]) 3613 3614 return param_list 3555 3615 3556 3616 def onParameterPaste(self): … … 3563 3623 3564 3624 context = {} 3565 # put the text into dictionary3566 3625 lines = cb_text.split(':') 3567 3626 if lines[0] != 'sasview_parameter_values': 3568 3627 return False 3569 3628 3570 model = lines[1].split(',') 3571 3572 if model[0] != 'model_name': 3629 # put the text into dictionary 3630 line_dict = {} 3631 for line in lines[1:]: 3632 content = line.split(',') 3633 if len(content) > 1: 3634 line_dict[content[0]] = content[1:] 3635 3636 model = line_dict['model_name'][0] 3637 3638 if 'model_name' not in line_dict.keys(): 3573 3639 return False 3574 3640 3575 context['model_name'] = [model[1]] 3576 for line in lines[2:-1]: 3577 if len(line) != 0: 3578 item = line.split(',') 3579 check = item[1] 3580 name = item[0] 3581 value = item[2] 3582 # Transfer the text to content[dictionary] 3583 context[name] = [check, value] 3584 3585 # limits 3586 try: 3587 limit_lo = item[3] 3588 context[name].append(limit_lo) 3589 limit_hi = item[4] 3590 context[name].append(limit_hi) 3591 except: 3592 pass 3593 3594 # Polydisp 3595 if len(item) > 5: 3596 value = item[5] 3597 context[name].append(value) 3598 try: 3599 value = item[6] 3600 context[name].append(value) 3601 value = item[7] 3602 context[name].append(value) 3603 except IndexError: 3604 pass 3605 3606 if str(self.cbModel.currentText()) != str(context['model_name'][0]): 3641 if 'multiplicity' in line_dict.keys(): 3642 multip = int(line_dict['multiplicity'][0], 0) 3643 # reset the model with multiplicity, so further updates are saved 3644 if self.kernel_module.is_multiplicity_model: 3645 self.kernel_module.multiplicity=multip 3646 self.updateMultiplicityCombo(multip) 3647 3648 if 'polydisperse_params' in line_dict.keys(): 3649 self.chkPolydispersity.setChecked(line_dict['polydisperse_params'][0]=='True') 3650 if 'magnetic_params' in line_dict.keys(): 3651 self.chkMagnetism.setChecked(line_dict['magnetic_params'][0]=='True') 3652 if 'chainfit_params' in line_dict.keys(): 3653 self.chkChainFit.setChecked(line_dict['chainfit_params'][0]=='True') 3654 if '2D_params' in line_dict.keys(): 3655 self.chk2DView.setChecked(line_dict['2D_params'][0]=='True') 3656 3657 # Create the context dictionary for parameters 3658 context['model_name'] = model 3659 for key, value in line_dict.items(): 3660 if len(value) > 2: 3661 context[key] = value 3662 3663 if str(self.cbModel.currentText()) != str(context['model_name']): 3607 3664 msg = QtWidgets.QMessageBox() 3608 3665 msg.setIcon(QtWidgets.QMessageBox.Information) … … 3616 3673 return 3617 3674 3675 if 'smearing' in line_dict.keys(): 3676 try: 3677 index = int(line_dict['smearing'][0]) 3678 self.smearing_widget.cbSmearing.setCurrentIndex(index) 3679 except ValueError: 3680 pass 3681 if 'smearing_min' in line_dict.keys(): 3682 try: 3683 self.smearing_widget.dq_l = float(line_dict['smearing_min'][0]) 3684 except ValueError: 3685 pass 3686 if 'smearing_max' in line_dict.keys(): 3687 try: 3688 self.smearing_widget.dq_r = float(line_dict['smearing_max'][0]) 3689 except ValueError: 3690 pass 3691 3692 if 'q_range_max' in line_dict.keys(): 3693 try: 3694 self.q_range_min = float(line_dict['q_range_min'][0]) 3695 self.q_range_max = float(line_dict['q_range_max'][0]) 3696 except ValueError: 3697 pass 3698 self.options_widget.updateQRange(self.q_range_min, self.q_range_max, self.npts) 3699 3618 3700 self.updateFullModel(context) 3619 3701 self.updateFullPolyModel(context) 3702 self.updateFullMagnetModel(context) 3703 3704 def updateMultiplicityCombo(self, multip): 3705 """ 3706 Find and update the multiplicity combobox 3707 """ 3708 index = self._model_model.index(self._n_shells_row, 1) 3709 widget = self.lstParams.indexWidget(index) 3710 if widget is not None and isinstance(widget, QtWidgets.QComboBox): 3711 widget.setCurrentIndex(widget.findText(str(multip))) 3712 self.current_shell_displayed = multip 3620 3713 3621 3714 def updateFullModel(self, param_dict): … … 3633 3726 if param_name not in list(param_dict.keys()): 3634 3727 return 3728 # Special case of combo box in the cell (multiplicity) 3729 param_line = param_dict[param_name] 3730 if len(param_line) == 1: 3731 # modify the shells value 3732 try: 3733 combo_index = int(param_line[0]) 3734 except ValueError: 3735 # quietly pass 3736 return 3737 index = self._model_model.index(row, 1) 3738 widget = self.lstParams.indexWidget(index) 3739 if widget is not None and isinstance(widget, QtWidgets.QComboBox): 3740 #widget.setCurrentIndex(combo_index) 3741 return 3635 3742 # checkbox state 3636 3743 param_checked = QtCore.Qt.Checked if param_dict[param_name][0] == "True" else QtCore.Qt.Unchecked 3637 3744 self._model_model.item(row, 0).setCheckState(param_checked) 3638 3745 3639 # modify the param value 3640 param_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) 3641 self._model_model.item(row, 1).setText(param_repr) 3746 # parameter value can be either just a value or text on the combobox 3747 param_text = param_dict[param_name][1] 3748 index = self._model_model.index(row, 1) 3749 widget = self.lstParams.indexWidget(index) 3750 if widget is not None and isinstance(widget, QtWidgets.QComboBox): 3751 # Find the right index based on text 3752 combo_index = int(param_text, 0) 3753 widget.setCurrentIndex(combo_index) 3754 else: 3755 # modify the param value 3756 param_repr = GuiUtils.formatNumber(param_text, high=True) 3757 self._model_model.item(row, 1).setText(param_repr) 3642 3758 3643 3759 # Potentially the error column … … 3645 3761 if len(param_dict[param_name])>4 and self.has_error_column: 3646 3762 # error values are not editable - no need to update 3647 #error_repr = GuiUtils.formatNumber(param_dict[param_name][2], high=True)3648 #self._model_model.item(row, 2).setText(error_repr)3649 3763 ioffset = 1 3650 3764 # min/max … … 3659 3773 self.setFocus() 3660 3774 3661 3662 3663 # block signals temporarily, so we don't end up3664 # updating charts with every single model change on the end of fitting3665 self._model_model.blockSignals(True)3666 3775 self.iterateOverModel(updateFittedValues) 3667 self._model_model.blockSignals(False)3668 3669 3776 3670 3777 def updateFullPolyModel(self, param_dict): … … 3713 3820 self.setFocus() 3714 3821 3715 # block signals temporarily, so we don't end up3716 # updating charts with every single model change on the end of fitting3717 self._poly_model.blockSignals(True)3718 3822 self.iterateOverPolyModel(updateFittedValues) 3719 self._poly_model.blockSignals(False) 3720 3721 3722 3823 3824 def updateFullMagnetModel(self, param_dict): 3825 """ 3826 Update the magnetism model with new parameters, create the errors column 3827 """ 3828 assert isinstance(param_dict, dict) 3829 if not dict: 3830 return 3831 3832 def updateFittedValues(row): 3833 # Utility function for main model update 3834 # internal so can use closure for param_dict 3835 if row >= self._magnet_model.rowCount(): 3836 return 3837 param_name = str(self._magnet_model.item(row, 0).text()).rsplit()[-1] 3838 if param_name not in list(param_dict.keys()): 3839 return 3840 # checkbox state 3841 param_checked = QtCore.Qt.Checked if param_dict[param_name][0] == "True" else QtCore.Qt.Unchecked 3842 self._magnet_model.item(row,0).setCheckState(param_checked) 3843 3844 # modify the param value 3845 param_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) 3846 self._magnet_model.item(row, 1).setText(param_repr) 3847 3848 # Potentially the error column 3849 ioffset = 0 3850 if len(param_dict[param_name])>4 and self.has_magnet_error_column: 3851 ioffset = 1 3852 # min 3853 param_repr = GuiUtils.formatNumber(param_dict[param_name][2+ioffset], high=True) 3854 self._magnet_model.item(row, 2+ioffset).setText(param_repr) 3855 # max 3856 param_repr = GuiUtils.formatNumber(param_dict[param_name][3+ioffset], high=True) 3857 self._magnet_model.item(row, 3+ioffset).setText(param_repr) 3858 3859 self.iterateOverMagnetModel(updateFittedValues) -
src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py
ra4b9b7a rd2007a8 1010 1010 1011 1011 # Change another parameter 1012 self.widget._model_model.item(2, 1).setText("3.0") 1012 self.widget._model_model.item(3, 1).setText("3.0") 1013 1013 1014 # Check that the stack is updated 1014 1015 self.assertEqual(len(self.widget.page_stack), 2) -
src/sas/qtgui/MainWindow/DataExplorer.py
r3b95b3b r345b3b3 233 233 filename = QtWidgets.QFileDialog.getOpenFileName(**kwargs)[0] 234 234 if filename: 235 load_thread = threads.deferToThread(self.readProject, filename) 236 load_thread.addCallback(self.readProjectComplete) 237 load_thread.addErrback(self.readProjectFailed) 238 239 def loadFailed(self, reason): 240 """ 241 """ 242 print("file load FAILED: ", reason) 243 pass 244 245 def readProjectFailed(self, reason): 246 """ 247 """ 248 print("readProjectFailed FAILED: ", reason) 249 pass 250 251 def readProject(self, filename): 252 self.communicator.statusBarUpdateSignal.emit("Loading Project... %s" % os.path.basename(filename)) 253 try: 254 manager = DataManager() 255 with open(filename, 'r') as infile: 256 manager.load_from_readable(infile) 257 258 self.communicator.statusBarUpdateSignal.emit("Loaded Project: %s" % os.path.basename(filename)) 259 return manager 260 261 except: 262 self.communicator.statusBarUpdateSignal.emit("Failed: %s" % os.path.basename(filename)) 263 raise 264 265 def readProjectComplete(self, manager): 266 self.model.clear() 267 268 self.manager.assign(manager) 269 self.model.beginResetModel() 270 for id, item in self.manager.get_all_data().items(): 271 self.updateModel(item.data, item.path) 272 273 self.model.endResetModel() 235 self.readProject(filename) 274 236 275 237 def saveProject(self): … … 285 247 name_tuple = QtWidgets.QFileDialog.getSaveFileName(**kwargs) 286 248 filename = name_tuple[0] 287 if filename: 288 _, extension = os.path.splitext(filename) 289 if not extension: 290 filename = '.'.join((filename, 'json')) 291 self.communicator.statusBarUpdateSignal.emit("Saving Project... %s\n" % os.path.basename(filename)) 292 with open(filename, 'w') as outfile: 293 self.manager.save_to_writable(outfile) 249 if not filename: 250 return 251 _, extension = os.path.splitext(filename) 252 if not extension: 253 filename = '.'.join((filename, 'json')) 254 self.communicator.statusBarUpdateSignal.emit("Saving Project... %s\n" % os.path.basename(filename)) 255 256 with open(filename, 'w') as outfile: 257 self.saveDataToFile(outfile) 258 259 def allDataForModel(self, model): 260 # data model 261 all_data = {} 262 for i in range(model.rowCount()): 263 properties = {} 264 item = model.item(i) 265 data = GuiUtils.dataFromItem(item) 266 if data is None: continue 267 # Now, all plots under this item 268 filename = data.filename 269 is_checked = item.checkState() 270 properties['checked'] = is_checked 271 other_datas = GuiUtils.plotsFromFilename(filename, model) 272 # skip the main plot 273 other_datas = list(other_datas.values())[1:] 274 all_data[data.id] = [data, properties, other_datas] 275 return all_data 276 277 def saveDataToFile(self, outfile): 278 """ 279 Save every dataset to a json file 280 """ 281 data = self.allDataForModel(self.model) 282 theory = self.allDataForModel(self.theory_model) 283 284 all_data = {} 285 for key, value in data.items(): 286 all_data[key] = value 287 for key, value in theory.items(): 288 if key in all_data: 289 raise ValueError("Inconsistent data in Project file.") 290 all_data[key] = value 291 292 # perspectives 293 current_perspective = self._perspective() 294 try: 295 perspective_dump = current_perspective.getCurrentStateAsXml() 296 except Exception: 297 ex = "State of " + current_perspective.windowTitle() + \ 298 " cannot be saved." 299 logging.error(ex) 300 if perspective_dump is not None: 301 assert(isinstance(perspective_dump, dict)) 302 all_data['perspective'] = perspective_dump 303 # save datas 304 GuiUtils.saveData(outfile, all_data) 305 return 306 307 def readProject(self, filename): 308 """ 309 Read out datasets and fitpages from file 310 """ 311 with open(filename, 'r') as infile: 312 all_data = GuiUtils.readDataFromFile(infile) 313 # clear the model 314 self.model.clear() 315 316 #self.model.beginResetModel() 317 for key, value in all_data.items(): 318 # key - cardinal number of dataset 319 # value - main dataset, [dependant filesets] 320 # add the main index 321 new_data = value[0] 322 assert isinstance(new_data, (Data1D, Data2D)) 323 properties = value[1] 324 is_checked = properties['checked'] 325 new_item = GuiUtils.createModelItemWithPlot(new_data, new_data.filename) 326 new_item.setCheckState(is_checked) 327 model = self.theory_model 328 if new_data.is_data: 329 model = self.model 330 model.appendRow(new_item) 331 self.manager.add_data(data_list={new_data.id:new_data}) 332 333 # Add the underlying data 334 if not value[2]: 335 continue 336 for plot in value[2]: 337 assert isinstance(plot, (Data1D, Data2D)) 338 GuiUtils.updateModelItemWithPlot(new_item, plot, plot.name) 294 339 295 340 def deleteFile(self, event): … … 1394 1439 checkbox_item.setCheckable(True) 1395 1440 checkbox_item.setCheckState(QtCore.Qt.Checked) 1396 checkbox_item.setText(os.path.basename(p_file)) 1441 if p_file is not None: 1442 checkbox_item.setText(os.path.basename(p_file)) 1397 1443 1398 1444 # Add the actual Data1D/Data2D object -
src/sas/qtgui/MainWindow/DataManager.py
re2e5f3d r345b3b3 29 29 from sas.qtgui.Plotting.PlotterData import Data1D 30 30 from sas.qtgui.Plotting.PlotterData import Data2D 31 from sas.qtgui.Plotting.Plottables import Plottable32 31 from sas.qtgui.Plotting.Plottables import PlottableTheory1D 33 32 from sas.qtgui.Plotting.Plottables import PlottableFit1D -
src/sas/qtgui/Utilities/GuiUtils.py
r63467b6 r345b3b3 11 11 import webbrowser 12 12 import urllib.parse 13 import json 14 from io import BytesIO 13 15 14 16 import numpy as np … … 26 28 from sas.qtgui.Plotting.PlotterData import Data1D 27 29 from sas.qtgui.Plotting.PlotterData import Data2D 30 from sas.qtgui.Plotting.Plottables import Plottable 31 from sas.sascalc.dataloader.data_info import Sample, Source, Vector 32 from sas.qtgui.Plotting.Plottables import View 33 from sas.qtgui.Plotting.Plottables import PlottableTheory1D 34 from sas.qtgui.Plotting.Plottables import PlottableFit1D 35 from sas.qtgui.Plotting.Plottables import Text 36 from sas.qtgui.Plotting.Plottables import Chisq 37 from sas.qtgui.MainWindow.DataState import DataState 38 28 39 from sas.sascalc.dataloader.loader import Loader 29 40 from sas.qtgui.Utilities import CustomDir … … 286 297 changeDataExplorerTabSignal = QtCore.pyqtSignal(int) 287 298 288 def updateModelItemWithPlot(item, update_data, name="" ):299 def updateModelItemWithPlot(item, update_data, name="", checkbox_state=None): 289 300 """ 290 301 Adds a checkboxed row named "name" to QStandardItem … … 311 322 # Force redisplay 312 323 return 313 314 324 # Create the new item 315 325 checkbox_item = createModelItemWithPlot(update_data, name) 316 326 327 if checkbox_state is not None: 328 checkbox_item.setCheckState(checkbox_state) 317 329 # Append the new row to the main item 318 330 item.appendRow(checkbox_item) … … 1139 1151 return result 1140 1152 1153 def saveData(fp, data): 1154 """ 1155 save content of data to fp (a .write()-supporting file-like object) 1156 """ 1157 1158 def add_type(dict, type): 1159 dict['__type__'] = type.__name__ 1160 return dict 1161 1162 def jdefault(o): 1163 """ 1164 objects that can't otherwise be serialized need to be converted 1165 """ 1166 # tuples and sets (TODO: default JSONEncoder converts tuples to lists, create custom Encoder that preserves tuples) 1167 if isinstance(o, (tuple, set)): 1168 content = { 'data': list(o) } 1169 return add_type(content, type(o)) 1170 1171 # "simple" types 1172 if isinstance(o, (Sample, Source, Vector)): 1173 return add_type(o.__dict__, type(o)) 1174 if isinstance(o, (Plottable, View)): 1175 return add_type(o.__dict__, type(o)) 1176 1177 # DataState 1178 if isinstance(o, (Data1D, Data2D)): 1179 # don't store parent 1180 content = o.__dict__.copy() 1181 #content.pop('parent') 1182 return add_type(content, type(o)) 1183 1184 # ndarray 1185 if isinstance(o, np.ndarray): 1186 buffer = BytesIO() 1187 np.save(buffer, o) 1188 buffer.seek(0) 1189 content = { 'data': buffer.read().decode('latin-1') } 1190 return add_type(content, type(o)) 1191 1192 # not supported 1193 logging.info("data cannot be serialized to json: %s" % type(o)) 1194 return None 1195 1196 json.dump(data, fp, indent=2, sort_keys=True, default=jdefault) 1197 1198 def readDataFromFile(fp): 1199 ''' 1200 ''' 1201 supported = [ 1202 tuple, set, 1203 Sample, Source, Vector, 1204 Plottable, Data1D, Data2D, PlottableTheory1D, PlottableFit1D, Text, Chisq, View, 1205 DataState, np.ndarray] 1206 1207 lookup = dict((cls.__name__, cls) for cls in supported) 1208 1209 class TooComplexException(Exception): 1210 pass 1211 1212 def simple_type(cls, data, level): 1213 class Empty(object): 1214 def __init__(self): 1215 for key, value in data.items(): 1216 setattr(self, key, generate(value, level)) 1217 1218 # create target object 1219 o = Empty() 1220 o.__class__ = cls 1221 1222 return o 1223 1224 def construct(type, data, level): 1225 try: 1226 cls = lookup[type] 1227 except KeyError: 1228 logging.info('unknown type: %s' % type) 1229 return None 1230 1231 # tuples and sets 1232 if cls in (tuple, set): 1233 # convert list to tuple/set 1234 return cls(generate(data['data'], level)) 1235 1236 # "simple" types 1237 if cls in (Sample, Source, Vector): 1238 return simple_type(cls, data, level) 1239 if issubclass(cls, Plottable) or (cls == View): 1240 return simple_type(cls, data, level) 1241 1242 # DataState 1243 if cls == DataState: 1244 o = simple_type(cls, data, level) 1245 o.parent = None # TODO: set to ??? 1246 return o 1247 1248 # ndarray 1249 if cls == np.ndarray: 1250 buffer = BytesIO() 1251 buffer.write(data['data'].encode('latin-1')) 1252 buffer.seek(0) 1253 return np.load(buffer) 1254 1255 logging.info('not implemented: %s, %s' % (type, cls)) 1256 return None 1257 1258 def generate(data, level): 1259 if level > 16: # recursion limit (arbitrary number) 1260 raise TooComplexException() 1261 else: 1262 level += 1 1263 1264 if isinstance(data, dict): 1265 try: 1266 type = data['__type__'] 1267 except KeyError: 1268 # if dictionary doesn't have __type__ then it is assumed to be just an ordinary dictionary 1269 o = {} 1270 for key, value in data.items(): 1271 o[key] = generate(value, level) 1272 return o 1273 1274 return construct(type, data, level) 1275 1276 if isinstance(data, list): 1277 return [generate(item, level) for item in data] 1278 1279 return data 1280 1281 new_stored_data = {} 1282 for id, data in json.load(fp).items(): 1283 try: 1284 new_stored_data[id] = generate(data, 0) 1285 except TooComplexException: 1286 logging.info('unable to load %s' % id) 1287 1288 return new_stored_data 1289 1141 1290 1142 1291 def enum(*sequential, **named):
Note: See TracChangeset
for help on using the changeset viewer.