[docs]defget_Vexp(dataset,tmin=0):# t = dataset.axes[0]t=dataset['t'].dataVexp=dataset.data# normalise vVexp/=Vexp.max()ift.max()>200:# guess this is in us not nst/=1e3# t -= t.min()t+=tminreturnt,Vexp
[docs]classDEERplot(QWidget):def__init__(self,parent=None):super().__init__(parent)# loading the ui fsile with uic moduleuic.loadUi(f"{package_directory}/quickdeer.ui",self)
[docs]defupdate_analysis_table(self):results=self.fitresultheaders=['Parameter','Value','95% CI','Unit']rows=[]# fitparams = {key : fitvalue if len(fitvalue)>1 else fitvalue[0] for key, fitvalue in zip(results.paramlist,[results.param[idx] for idx in results._param_idx])}forparaminresults.paramlist:ifparam=='P':continuerows.append({"Parameter":param,"Value":getattr(results,param),"95% CI":getattr(results,f"{param}Uncert").ci(95),"Unit":""})fill_table(self.Analysis_table,headers,rows,rowcount=len(rows))
[docs]defupdate_fit_result(self):results=self.fitresultself.MNRDoubleSpinBox.setValue(results.MNR)self.Chi2DoubleSpinBox.setValue(results.stats['chi2red'])self.conc_value.setValue(results.conc)self.conc_uncert.setText(getCIstring(results.concUncert))try:self.regparamDoubleSpinBox.setValue(results.regparam)self.regparamDoubleSpinBox.setDisabled(0)exceptAttributeError:self.regparamDoubleSpinBox.setDisabled(1)self.clearLayout(self.Pathways_Box)# Find pathways in the fit resultspathways=[]total_mod=0total_mod_uncert_covmat=Nonetotal_mod_lb=0total_mod_ub=0if'mod'inresults.paramlist:pathways=[1]reftime=getattr(results,f"reftime")lam=getattr(results,f"mod")total_mod=lamtotal_mod_uncert_covmat=np.sqrt(getattr(results,f"modUncert").covmat)total_mod_lb=getattr(results,f"modUncert")._UQResult__lbtotal_mod_ub=getattr(results,f"modUncert")._UQResult__ubi=0self.Pathways_Box.addWidget(QLabel(f"reftime"),i,0,1,1)self.Pathways_Box.addWidget(QDoubleSpinBox(value=reftime,suffix=' us',readOnly=True,buttonSymbols=QAbstractSpinBox.ButtonSymbols(2)),i,1,1,1)self.Pathways_Box.addWidget(QLabel(getCIstring(getattr(results,f"reftimeUncert"))),i,2,1,1)self.Pathways_Box.addWidget(QLabel(f"mod"),i+1,0,1,1)self.Pathways_Box.addWidget(QDoubleSpinBox(value=lam,suffix='',decimals=3,readOnly=True,buttonSymbols=QAbstractSpinBox.ButtonSymbols(2)),i+1,1,1,1)self.Pathways_Box.addWidget(QLabel(getCIstring(getattr(results,f"modUncert"))),i+1,2,1,1)else:forparaminresults.paramlist:# Search for parameters that start with 'reftime' and record the numberifparam.startswith('reftime'):pathways.append(int(param[7:]))# Add pathways to tableforiinrange(0,len(pathways)*2,2):pathway=pathways[i//2]# Creating a new lay out that is formed from a label and 2 double spin boxes and 2 more labels. in a 1x2x2 patternreftime=getattr(results,f"reftime{pathway}")lam=getattr(results,f"lam{pathway}")iftotal_mod_uncert_covmatisnotNone:total_mod_uncert_covmat+=np.sqrt(getattr(results,f"lam{pathway}Uncert").covmat)else:total_mod_uncert_covmat=np.sqrt(getattr(results,f"lam{pathway}Uncert").covmat)total_mod_lb+=getattr(results,f"lam{pathway}Uncert")._UQResult__lbtotal_mod_ub+=getattr(results,f"lam{pathway}Uncert")._UQResult__ubtotal_mod+=lamself.Pathways_Box.addWidget(QLabel(f"reftime {pathway}"),i,0,1,1)self.Pathways_Box.addWidget(QDoubleSpinBox(value=reftime,suffix=' us',readOnly=True,buttonSymbols=QAbstractSpinBox.ButtonSymbols(2)),i,1,1,1)self.Pathways_Box.addWidget(QLabel(getCIstring(getattr(results,f"reftime{pathway}Uncert"))),i,2,1,1)self.Pathways_Box.addWidget(QLabel(f"lam {pathway}"),i+1,0,1,1)self.Pathways_Box.addWidget(QDoubleSpinBox(value=lam,suffix='',decimals=3,readOnly=True,buttonSymbols=QAbstractSpinBox.ButtonSymbols(2)),i+1,1,1,1)self.Pathways_Box.addWidget(QLabel(getCIstring(getattr(results,f"lam{pathway}Uncert"))),i+1,2,1,1)total_mod_uncert_covmat=np.sqrt(np.diag(total_mod_uncert_covmat))coverage=95alpha=1-coverage/100p=1-alpha/2standardError=norm.ppf(p)*total_mod_uncert_covmat[0]minCI=np.max([total_mod-standardError,total_mod_lb[0]])maxCI=np.min([total_mod+standardError,total_mod_ub[0]])self.Total_mod_value.setValue(total_mod)self.Total_mod_uncert.setText(f"({minCI:.{2}f},{maxCI:.{2}f})")
[docs]defupdate_figure(self):ifnothasattr(self,'fit_result'):# Only update the raw dataifhasattr(self,'current_data')and'quickdeer'inself.current_data.keys():self._static_ax['Primary_time'].plot(*get_Vexp(self.current_data['quickdeer']))self.static_canvas.draw()
[docs]defclear_all(self):self._static_ax['Primary_time'].cla()self._static_ax['Primary_dist'].cla()self.static_canvas.draw()self.Last_updated.setText(f"Last updated: never")self.num_scans.setText(f"# of scans: 0")self.MNRDoubleSpinBox.setValue(0)self.Chi2DoubleSpinBox.setValue(0)self.conc_value.setValue(0)self.conc_uncert.setText('(-,-)')self.regparamDoubleSpinBox.setValue(0)self.Total_mod_value.setValue(0)self.Total_mod_uncert.setText('(-,-)')# clear all enteries in the Pathways_Boxwhileself.Pathways_Box.count()>0:self.Pathways_Box.removeWidget(self.Pathways_Box.itemAt(0).widget())self.fitresult=None
[docs]defprocess_deeranalysis(self,wait_condition=None,update_func=None):settings={'ROI':True}settings['exp_type']=self.ExperimentcomboBox.currentText()settings['tau1']=self.Tau1doubleSpinBox.value()settings['tau2']=self.Tau2doubleSpinBox.value()ifsettings['exp_type']=='5pDEER':settings['tau3']=self.Tau3doubleSpinBox.value()settings['pathways']=str_to_list_type(self.PathwayslineEdit.text(),int)settings['compactness']=self.CompactnessradioButton.isChecked()settings['pulselength']=self.PulseLengthdoubleSpinBox.value()dataset=self.current_data['quickdeer']# if dataset.axes[0].max()>500: # Axis is in ns# dataset.axes[0] /= 1e3# dataset.axes[0] -= dataset.axes[0].min()# dataset.axes[0] += self.tmindoubleSpinBox.value()ifself.DistancecomboBox.currentText()=='auto':settings['model']=Noneelifself.DistancecomboBox.currentText()=='Parametric':settings['model']=Noneelifself.DistancecomboBox.currentText()=='Gaussian':settings['model']=dl.dd_gausselifself.DistancecomboBox.currentText()=='Bi-Gaussian':settings['model']=dl.dd_gauss2elifself.DistancecomboBox.currentText()=='Tri-Gaussian':settings['model']=dl.dd_gauss3elifself.DistancecomboBox.currentText()=='Rice':settings['model']=dl.dd_riceelifself.DistancecomboBox.currentText()=='Bi-Rice':settings['model']=dl.dd_rice2elifself.DistancecomboBox.currentText()=='Tri-Rice':settings['model']=dl.dd_rice3else:settings['model']=Noneworker=Worker(deeranalysis_process,dataset,settings,self.cores)worker.signals.result.connect(partial(self.refresh_deer,wait_condition=wait_condition,update_func=update_func))print('starting worker')self.threadpool.start(worker)
[docs]defrefresh_deer(self,fitresult,wait_condition=None,update_func=None):ifisinstance(fitresult,tuple):self.fitresult=fitresult[0]self.taumax=fitresult[1]else:self.fitresult=fitresultifupdate_funcisnotNone:update_func(self.fitresult)ifisinstance(wait_condition,QtCore.QWaitCondition):wait_condition.wakeAll()self._static_ax['Primary_time'].cla()self._static_ax['Primary_dist'].cla()ad.DEERanalysis_plot(self.fitresult,background=True,ROI=self.fitresult.ROI,axs=self._static_ax,fig=self.static_canvas.figure)self.static_canvas.draw()self.update_fit_result()ifhasattr(self.fitresult,'dataset')andhasattr(self.fitresult.dataset,'time'):self.Last_updated.setText(f"Last updated: {self.fitresult.dataset.time}")self.num_scans.setText(f"# of scans: {self.fitresult.dataset.nAvgs}")else:self.Last_updated.setText(f"Last updated: never")self.num_scans.setText(f"# of scans: 0")