- Timestamp:
- Oct 18, 2018 5:43:11 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:
- 2eeda93
- Parents:
- b95d748 (diff), 9a42ea1 (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:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/MainWindow/GuiManager.py
refaf022 r6040cd7 444 444 """ 445 445 # disable not yet fully implemented actions 446 self._workspace.actionOpen_Analysis.setVisible(False)446 #self._workspace.actionOpen_Analysis.setVisible(False) 447 447 self._workspace.actionUndo.setVisible(False) 448 448 self._workspace.actionRedo.setVisible(False) -
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
rdd545d1 r9a42ea1 567 567 self.communicate.customModelDirectoryChanged.connect(self.onCustomModelChange) 568 568 self.communicate.saveAnalysisSignal.connect(self.savePageState) 569 #self.communicate.loadAnalysisSignal.connect(self.loadPageState) 569 570 self.smearing_widget.smearingChangedSignal.connect(self.onSmearingOptionsUpdate) 570 571 … … 3369 3370 Create and serialize local PageState 3370 3371 """ 3371 from sas.sascalc.fit.pagestate import Reader3372 model = self.kernel_module3373 3374 # Old style PageState object3375 state = PageState(model=model, data=self.data)3376 3377 # Add parameter data to the state3378 self.getCurrentFitState(state)3379 3380 # Create the filewriter, aptly named 'Reader'3381 state_reader = Reader(self.loadPageStateCallback)3382 3372 filepath = self.saveAsAnalysisFile() 3383 3373 if filepath is None or filepath == "": 3384 3374 return 3385 state_reader.write(filename=filepath, fitstate=state) 3386 pass 3375 3376 fitpage_state = self.getFitPage() 3377 fitpage_state += self.getFitModel() 3378 3379 with open(filepath, 'w') as statefile: 3380 for line in fitpage_state: 3381 statefile.write(str(line)) 3382 3383 self.communicate.statusBarUpdateSignal.emit('Analysis saved.') 3387 3384 3388 3385 def saveAsAnalysisFile(self): … … 3417 3414 Load the PageState object and update the current widget 3418 3415 """ 3416 filepath = self.loadAnalysisFile() 3417 if filepath is None or filepath == "": 3418 return 3419 3420 with open(filepath, 'r') as statefile: 3421 #column_data = [line.rstrip().split() for line in statefile.readlines()] 3422 lines = statefile.readlines() 3423 3424 # convert into list of lists 3419 3425 pass 3420 3426 3421 def getCurrentFitState(self, state=None): 3422 """ 3423 Store current state for fit_page 3424 """ 3425 # save model option 3426 #if self.model is not None: 3427 # self.disp_list = self.getDispParamList() 3428 # state.disp_list = copy.deepcopy(self.disp_list) 3429 # #state.model = self.model.clone() 3430 3431 # Comboboxes 3432 state.categorycombobox = self.cbCategory.currentText() 3433 state.formfactorcombobox = self.cbModel.currentText() 3434 if self.cbStructureFactor.isEnabled(): 3435 state.structurecombobox = self.cbStructureFactor.currentText() 3436 state.tcChi = self.chi2 3437 3438 state.enable2D = self.is2D 3439 3440 #state.weights = copy.deepcopy(self.weights) 3441 # save data 3442 state.data = copy.deepcopy(self.data) 3443 3444 # save plotting range 3445 state.qmin = self.q_range_min 3446 state.qmax = self.q_range_max 3447 state.npts = self.npts 3448 3449 # self.state.enable_disp = self.enable_disp.GetValue() 3450 # self.state.disable_disp = self.disable_disp.GetValue() 3451 3452 # self.state.enable_smearer = \ 3453 # copy.deepcopy(self.enable_smearer.GetValue()) 3454 # self.state.disable_smearer = \ 3455 # copy.deepcopy(self.disable_smearer.GetValue()) 3456 3457 #self.state.pinhole_smearer = \ 3458 # copy.deepcopy(self.pinhole_smearer.GetValue()) 3459 #self.state.slit_smearer = copy.deepcopy(self.slit_smearer.GetValue()) 3460 #self.state.dI_noweight = copy.deepcopy(self.dI_noweight.GetValue()) 3461 #self.state.dI_didata = copy.deepcopy(self.dI_didata.GetValue()) 3462 #self.state.dI_sqrdata = copy.deepcopy(self.dI_sqrdata.GetValue()) 3463 #self.state.dI_idata = copy.deepcopy(self.dI_idata.GetValue()) 3464 3465 p = self.model_parameters 3466 # save checkbutton state and txtcrtl values 3467 state.parameters = FittingUtilities.getStandardParam(self._model_model) 3468 state.orientation_params_disp = FittingUtilities.getOrientationParam(self.kernel_module) 3469 3470 #self._copy_parameters_state(self.orientation_params_disp, self.state.orientation_params_disp) 3471 #self._copy_parameters_state(self.parameters, self.state.parameters) 3472 #self._copy_parameters_state(self.fittable_param, self.state.fittable_param) 3473 #self._copy_parameters_state(self.fixed_param, self.state.fixed_param) 3427 def loadAnalysisFile(self): 3428 """ 3429 Called when the "Open Project" menu item chosen. 3430 """ 3431 default_name = "FitPage"+str(self.tab_id)+".fitv" 3432 wildcard = "fitv files (*.fitv)" 3433 kwargs = { 3434 'caption' : 'Open Analysis', 3435 'directory' : default_name, 3436 'filter' : wildcard, 3437 'parent' : self, 3438 } 3439 filename = QtWidgets.QFileDialog.getOpenFileName(**kwargs)[0] 3440 return filename 3474 3441 3475 3442 def onCopyToClipboard(self, format=None): … … 3481 3448 param_list = self.getFitParameters() 3482 3449 if format=="": 3450 param_list = self.getFitPage() 3451 param_list += self.getFitModel() 3483 3452 formatted_output = FittingUtilities.formatParameters(param_list) 3484 3453 elif format == "Excel": … … 3493 3462 cb.setText(formatted_output) 3494 3463 3495 def getFitParameters(self, format=None): 3496 """ 3497 Copy current parameters into the clipboard 3464 def getFitModel(self): 3465 """ 3466 serializes combobox state 3467 """ 3468 param_list = [] 3469 model = str(self.cbModel.currentText()) 3470 category = str(self.cbCategory.currentText()) 3471 structure = str(self.cbStructureFactor.currentText()) 3472 param_list.append(['fitpage_category', category]) 3473 param_list.append(['fitpage_model', model]) 3474 param_list.append(['fitpage_structure', structure]) 3475 3476 return param_list 3477 3478 def getFitPage(self): 3479 """ 3480 serializes full state of this fit page 3498 3481 """ 3499 3482 # run a loop over all parameters and pull out 3500 3483 # first - regular params 3484 param_list = self.getFitParameters() 3485 3486 param_list.append(['is_data', str(self.data_is_loaded)]) 3487 if self.data_is_loaded: 3488 param_list.append(['data_id', str(self.logic.data.id)]) 3489 param_list.append(['data_name', str(self.logic.data.filename)]) 3490 3491 # option tab 3492 param_list.append(['q_range_min', str(self.q_range_min)]) 3493 param_list.append(['q_range_max', str(self.q_range_max)]) 3494 param_list.append(['q_weighting', str(self.weighting)]) 3495 param_list.append(['weighting', str(self.options_widget.weighting)]) 3496 3497 # resolution 3498 smearing, accuracy, smearing_min, smearing_max = self.smearing_widget.state() 3499 index = self.smearing_widget.cbSmearing.currentIndex() 3500 param_list.append(['smearing', str(index)]) 3501 param_list.append(['smearing_min', str(smearing_min)]) 3502 param_list.append(['smearing_max', str(smearing_max)]) 3503 3504 # checkboxes, if required 3505 has_polydisp = self.chkPolydispersity.isChecked() 3506 has_magnetism = self.chkMagnetism.isChecked() 3507 has_chain = self.chkChainFit.isChecked() 3508 has_2D = self.chk2DView.isChecked() 3509 param_list.append(['polydisperse_params', str(has_polydisp)]) 3510 param_list.append(['magnetic_params', str(has_magnetism)]) 3511 param_list.append(['chainfit_params', str(has_chain)]) 3512 param_list.append(['2D_params', str(has_2D)]) 3513 3514 return param_list 3515 3516 def getFitParameters(self): 3517 """ 3518 serializes current parameters 3519 """ 3501 3520 param_list = [] 3502 3521 param_list.append(['model_name', str(self.cbModel.currentText())]) … … 3533 3552 if self.has_error_column: 3534 3553 column_offset = 1 3554 param_error = str(self._model_model.item(row, 1+column_offset).text()) 3535 3555 try: 3536 3556 param_min = str(self._model_model.item(row, 2+column_offset).text()) … … 3539 3559 pass 3540 3560 3541 param_list.append([param_name, param_checked, param_value, param_ min, param_max])3561 param_list.append([param_name, param_checked, param_value, param_error, param_min, param_max]) 3542 3562 3543 3563 def gatherPolyParams(row): … … 3552 3572 if self.has_poly_error_column: 3553 3573 column_offset = 1 3574 param_error = str(self._poly_model.item(row, 1+column_offset).text()) 3554 3575 param_min = str(self._poly_model.item(row, 2+column_offset).text()) 3555 3576 param_max = str(self._poly_model.item(row, 3+column_offset).text()) … … 3563 3584 # width 3564 3585 name = param_name+".width" 3565 param_list.append([name, param_checked, param_value, param_ min, param_max,3566 param_npts, param_nsigs, param_fun])3586 param_list.append([name, param_checked, param_value, param_error, 3587 param_min, param_max, param_npts, param_nsigs, param_fun]) 3567 3588 3568 3589 def gatherMagnetParams(row): … … 3577 3598 if self.has_magnet_error_column: 3578 3599 column_offset = 1 3600 param_error = str(self._magnet_model.item(row, 1+column_offset).text()) 3579 3601 param_min = str(self._magnet_model.item(row, 2+column_offset).text()) 3580 3602 param_max = str(self._magnet_model.item(row, 3+column_offset).text()) 3581 param_list.append([param_name, param_checked, param_value, param_min, param_max]) 3603 param_list.append([param_name, param_checked, param_value, 3604 param_error, param_min, param_max]) 3582 3605 3583 3606 self.iterateOverModel(gatherParams) … … 3589 3612 if self.kernel_module.is_multiplicity_model: 3590 3613 param_list.append(['multiplicity', str(self.kernel_module.multiplicity)]) 3591 3592 # option tab3593 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 # resolution3598 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 required3605 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 3614 3615 return param_list … … 3697 3698 pass 3698 3699 self.options_widget.updateQRange(self.q_range_min, self.q_range_max, self.npts) 3700 try: 3701 button_id = int(line_dict['weighting'][0]) 3702 for button in self.options_widget.weightingGroup.buttons(): 3703 if abs(self.options_widget.weightingGroup.id(button)) == button_id+2: 3704 button.setChecked(True) 3705 break 3706 except ValueError: 3707 pass 3699 3708 3700 3709 self.updateFullModel(context) … … 3759 3768 # Potentially the error column 3760 3769 ioffset = 0 3761 if len(param_dict[param_name])>4 and self.has_error_column: 3770 joffset = 0 3771 if len(param_dict[param_name])>3: 3762 3772 # error values are not editable - no need to update 3763 3773 ioffset = 1 3774 if self.has_error_column: 3775 joffset = 1 3764 3776 # min/max 3765 3777 try: 3766 3778 param_repr = GuiUtils.formatNumber(param_dict[param_name][2+ioffset], high=True) 3767 self._model_model.item(row, 2+ ioffset).setText(param_repr)3779 self._model_model.item(row, 2+joffset).setText(param_repr) 3768 3780 param_repr = GuiUtils.formatNumber(param_dict[param_name][3+ioffset], high=True) 3769 self._model_model.item(row, 3+ ioffset).setText(param_repr)3781 self._model_model.item(row, 3+joffset).setText(param_repr) 3770 3782 except: 3771 3783 pass … … 3801 3813 # Potentially the error column 3802 3814 ioffset = 0 3803 if len(param_dict[param_name])>4 and self.has_poly_error_column: 3815 joffset = 0 3816 if len(param_dict[param_name])>3: 3804 3817 ioffset = 1 3818 if self.has_poly_error_column: 3819 joffset = 1 3805 3820 # min 3806 3821 param_repr = GuiUtils.formatNumber(param_dict[param_name][2+ioffset], high=True) 3807 self._poly_model.item(row, 2+ ioffset).setText(param_repr)3822 self._poly_model.item(row, 2+joffset).setText(param_repr) 3808 3823 # max 3809 3824 param_repr = GuiUtils.formatNumber(param_dict[param_name][3+ioffset], high=True) 3810 self._poly_model.item(row, 3+ ioffset).setText(param_repr)3825 self._poly_model.item(row, 3+joffset).setText(param_repr) 3811 3826 # Npts 3812 3827 param_repr = GuiUtils.formatNumber(param_dict[param_name][4+ioffset], high=True) 3813 self._poly_model.item(row, 4+ ioffset).setText(param_repr)3828 self._poly_model.item(row, 4+joffset).setText(param_repr) 3814 3829 # Nsigs 3815 3830 param_repr = GuiUtils.formatNumber(param_dict[param_name][5+ioffset], high=True) 3816 self._poly_model.item(row, 5+ioffset).setText(param_repr) 3817 3818 param_repr = GuiUtils.formatNumber(param_dict[param_name][5+ioffset], high=True) 3819 self._poly_model.item(row, 5+ioffset).setText(param_repr) 3831 self._poly_model.item(row, 5+joffset).setText(param_repr) 3832 3820 3833 self.setFocus() 3821 3834 … … 3848 3861 # Potentially the error column 3849 3862 ioffset = 0 3850 if len(param_dict[param_name])>4 and self.has_magnet_error_column: 3863 joffset = 0 3864 if len(param_dict[param_name])>3: 3851 3865 ioffset = 1 3866 if self.has_magnet_error_column: 3867 joffset = 1 3852 3868 # min 3853 3869 param_repr = GuiUtils.formatNumber(param_dict[param_name][2+ioffset], high=True) 3854 self._magnet_model.item(row, 2+ ioffset).setText(param_repr)3870 self._magnet_model.item(row, 2+joffset).setText(param_repr) 3855 3871 # max 3856 3872 param_repr = GuiUtils.formatNumber(param_dict[param_name][3+ioffset], high=True) 3857 self._magnet_model.item(row, 3+ ioffset).setText(param_repr)3873 self._magnet_model.item(row, 3+joffset).setText(param_repr) 3858 3874 3859 3875 self.iterateOverMagnetModel(updateFittedValues) 3876 3877 def getCurrentFitState(self, state=None): 3878 """ 3879 Store current state for fit_page 3880 """ 3881 # save model option 3882 #if self.model is not None: 3883 # self.disp_list = self.getDispParamList() 3884 # state.disp_list = copy.deepcopy(self.disp_list) 3885 # #state.model = self.model.clone() 3886 3887 # Comboboxes 3888 state.categorycombobox = self.cbCategory.currentText() 3889 state.formfactorcombobox = self.cbModel.currentText() 3890 if self.cbStructureFactor.isEnabled(): 3891 state.structurecombobox = self.cbStructureFactor.currentText() 3892 state.tcChi = self.chi2 3893 3894 state.enable2D = self.is2D 3895 3896 #state.weights = copy.deepcopy(self.weights) 3897 # save data 3898 state.data = copy.deepcopy(self.data) 3899 3900 # save plotting range 3901 state.qmin = self.q_range_min 3902 state.qmax = self.q_range_max 3903 state.npts = self.npts 3904 3905 # self.state.enable_disp = self.enable_disp.GetValue() 3906 # self.state.disable_disp = self.disable_disp.GetValue() 3907 3908 # self.state.enable_smearer = \ 3909 # copy.deepcopy(self.enable_smearer.GetValue()) 3910 # self.state.disable_smearer = \ 3911 # copy.deepcopy(self.disable_smearer.GetValue()) 3912 3913 #self.state.pinhole_smearer = \ 3914 # copy.deepcopy(self.pinhole_smearer.GetValue()) 3915 #self.state.slit_smearer = copy.deepcopy(self.slit_smearer.GetValue()) 3916 #self.state.dI_noweight = copy.deepcopy(self.dI_noweight.GetValue()) 3917 #self.state.dI_didata = copy.deepcopy(self.dI_didata.GetValue()) 3918 #self.state.dI_sqrdata = copy.deepcopy(self.dI_sqrdata.GetValue()) 3919 #self.state.dI_idata = copy.deepcopy(self.dI_idata.GetValue()) 3920 3921 p = self.model_parameters 3922 # save checkbutton state and txtcrtl values 3923 state.parameters = FittingUtilities.getStandardParam(self._model_model) 3924 state.orientation_params_disp = FittingUtilities.getOrientationParam(self.kernel_module) 3925 3926 #self._copy_parameters_state(self.orientation_params_disp, self.state.orientation_params_disp) 3927 #self._copy_parameters_state(self.parameters, self.state.parameters) 3928 #self._copy_parameters_state(self.fittable_param, self.state.fittable_param) 3929 #self._copy_parameters_state(self.fixed_param, self.state.fixed_param) 3930 -
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/Perspectives/Fitting/FittingPerspective.py
rd2007a8 rb95d748 337 337 pass 338 338 339 def getCurrentStateAsXml(self): 340 """ 341 Returns an XML version of the current state 342 """ 343 state = {} 344 for tab in self.tabs: 345 pass 346 return state 347 339 348 @property 340 349 def currentTab(self): -
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.