Changes in / [6da3e3d:0eff615] in sasview
- Location:
- src/sas/qtgui
- Files:
-
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/Calculators/SldPanel.py
r5c0e717 raed0532 6 6 7 7 from periodictable import formula as Formula 8 from periodictable.xsf import xray_energy, xray_sld 8 from periodictable.xsf import xray_energy, xray_sld_from_atoms 9 9 from periodictable.nsf import neutron_scattering 10 10 … … 21 21 'MOLECULAR_FORMULA', 22 22 'MASS_DENSITY', 23 ' NEUTRON_WAVELENGTH',23 'WAVELENGTH', 24 24 'NEUTRON_SLD_REAL', 25 25 'NEUTRON_SLD_IMAG', 26 'XRAY_WAVELENGTH', 27 'XRAY_SLD_REAL', 28 'XRAY_SLD_IMAG', 26 'CU_KA_SLD_REAL', 27 'CU_KA_SLD_IMAG', 28 'MO_KA_SLD_REAL', 29 'MO_KA_SLD_IMAG', 29 30 'NEUTRON_INC_XS', 30 31 'NEUTRON_ABS_XS', … … 33 34 34 35 class SldResult(object): 35 def __init__(self, molecular_formula, mass_density, 36 neutron_wavelength, neutron_sld_real, neutron_sld_imag, 37 xray_wavelength, xray_sld_real, xray_sld_imag, 36 def __init__(self, molecular_formula, mass_density, wavelength, 37 neutron_sld_real, neutron_sld_imag, 38 cu_ka_sld_real, cu_ka_sld_imag, 39 mo_ka_sld_real, mo_ka_sld_imag, 38 40 neutron_inc_xs, neutron_abs_xs, neutron_length): 39 41 40 42 self.molecular_formula = molecular_formula 41 43 self.mass_density = mass_density 42 self. neutron_wavelength = neutron_wavelength44 self.wavelength = wavelength 43 45 self.neutron_sld_real = neutron_sld_real 44 46 self.neutron_sld_imag = neutron_sld_imag 45 self.xray_wavelength = xray_wavelength 46 self.xray_sld_real = xray_sld_real 47 self.xray_sld_imag = xray_sld_imag 47 self.cu_ka_sld_real = cu_ka_sld_real 48 self.cu_ka_sld_imag = cu_ka_sld_imag 49 self.mo_ka_sld_real = mo_ka_sld_real 50 self.mo_ka_sld_imag = mo_ka_sld_imag 48 51 self.neutron_inc_xs = neutron_inc_xs 49 52 self.neutron_abs_xs = neutron_abs_xs 50 53 self.neutron_length = neutron_length 51 54 52 def sldAlgorithm(molecular_formula, mass_density, neutron_wavelength, xray_wavelength): 53 54 xray_sld_real, xray_sld_imag = xray_sld( 55 compound=molecular_formula, 55 def sldAlgorithm(molecular_formula, mass_density, wavelength): 56 57 sld_formula = Formula(molecular_formula, density=mass_density) 58 59 def calculate_sld(formula): 60 if len(formula.atoms) != 1: 61 raise NotImplementedError() 62 energy = xray_energy(list(formula.atoms.keys())[0].K_alpha) 63 return xray_sld_from_atoms( 64 sld_formula.atoms, 56 65 density=mass_density, 57 wavelength=xray_wavelength) 58 59 (neutron_sld_real, neutron_sld_imag, _), (_, neutron_abs_xs, neutron_inc_xs), neutron_length = \ 66 energy=energy) 67 68 cu_real, cu_imag = calculate_sld(Formula("Cu")) 69 mo_real, mo_imag = calculate_sld(Formula("Mo")) 70 71 (sld_real, sld_imag, _), (_, neutron_abs_xs, neutron_inc_xs), neutron_length = \ 60 72 neutron_scattering( 61 73 compound=molecular_formula, 62 74 density=mass_density, 63 wavelength= neutron_wavelength)75 wavelength=wavelength) 64 76 65 77 SCALE = 1e-6 66 78 67 79 # neutron sld 68 scaled_neutron_sld_real = SCALE * neutron_sld_real 69 scaled_neutron_sld_imag = SCALE * abs(neutron_sld_imag) 70 71 # xray sld 72 scaled_xray_sld_real = SCALE * xray_sld_real 73 scaled_xray_sld_imag = SCALE * abs(xray_sld_imag) 74 80 neutron_sld_real = SCALE * sld_real 81 neutron_sld_imag = SCALE * abs(sld_imag) 82 83 # Cu sld 84 cu_ka_sld_real = SCALE * cu_real 85 cu_ka_sld_imag = SCALE * abs(cu_imag) 86 87 # Mo sld 88 mo_ka_sld_real = SCALE * mo_real 89 mo_ka_sld_imag = SCALE * abs(mo_imag) 75 90 76 91 return SldResult( 77 molecular_formula, mass_density, 78 neutron_wavelength, scaled_neutron_sld_real, scaled_neutron_sld_imag, 79 xray_wavelength, scaled_xray_sld_real, scaled_xray_sld_imag, 92 molecular_formula, mass_density, wavelength, 93 neutron_sld_real, neutron_sld_imag, 94 cu_ka_sld_real, cu_ka_sld_imag, 95 mo_ka_sld_real, mo_ka_sld_imag, 80 96 neutron_inc_xs, neutron_abs_xs, neutron_length) 81 97 … … 96 112 MODEL.NEUTRON_SLD_REAL: self.ui.editNeutronSldReal, 97 113 MODEL.NEUTRON_SLD_IMAG: self.ui.editNeutronSldImag, 98 MODEL.XRAY_SLD_REAL: self.ui.editXraySldReal, 99 MODEL.XRAY_SLD_IMAG: self.ui.editXraySldImag, 114 MODEL.CU_KA_SLD_REAL: self.ui.editCuKaSldReal, 115 MODEL.CU_KA_SLD_IMAG: self.ui.editCuKaSldImag, 116 MODEL.MO_KA_SLD_REAL: self.ui.editMoKaSldReal, 117 MODEL.MO_KA_SLD_IMAG: self.ui.editMoKaSldImag, 100 118 MODEL.NEUTRON_INC_XS: self.ui.editNeutronIncXs, 101 119 MODEL.NEUTRON_ABS_XS: self.ui.editNeutronAbsXs, … … 113 131 rx = QtCore.QRegExp("[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?") 114 132 self.ui.editMassDensity.setValidator(QtGui.QRegExpValidator(rx, self.ui.editMassDensity)) 115 self.ui.editNeutronWavelength.setValidator(QtGui.QRegExpValidator(rx, self.ui.editNeutronWavelength)) 116 self.ui.editXrayWavelength.setValidator(QtGui.QRegExpValidator(rx, self.ui.editXrayWavelength)) 133 self.ui.editWavelength.setValidator(QtGui.QRegExpValidator(rx, self.ui.editWavelength)) 117 134 118 135 # signals 119 self.ui.helpButton.clicked.connect(self.displayHelp) 120 self.ui.closeButton.clicked.connect(self.closePanel) 121 self.ui.recalculateButton.clicked.connect(self.calculateSLD) 122 123 def calculateSLD(self): 124 self.recalculateSLD() 136 self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Reset).clicked.connect(self.modelReset) 137 self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self.displayHelp) 125 138 126 139 def setupModel(self): 127 140 self.model = QtGui.QStandardItemModel(self) 128 self.model.setItem(MODEL.MOLECULAR_FORMULA , QtGui.QStandardItem()) 129 self.model.setItem(MODEL.MASS_DENSITY , QtGui.QStandardItem()) 130 self.model.setItem(MODEL.NEUTRON_WAVELENGTH, QtGui.QStandardItem()) 131 self.model.setItem(MODEL.XRAY_WAVELENGTH , QtGui.QStandardItem()) 141 self.model.setItem(MODEL.MOLECULAR_FORMULA, QtGui.QStandardItem()) 142 self.model.setItem(MODEL.MASS_DENSITY , QtGui.QStandardItem()) 143 self.model.setItem(MODEL.WAVELENGTH , QtGui.QStandardItem()) 132 144 133 145 for key in list(self._getOutputs().keys()): … … 135 147 136 148 self.model.dataChanged.connect(self.dataChanged) 137 138 self.ui.editMassDensity.textEdited.connect(self.recalculateSLD)139 self.ui.editMolecularFormula.textEdited.connect(self.recalculateSLD)140 self.ui.editNeutronWavelength.textEdited.connect(self.recalculateSLD)141 self.ui.editXrayWavelength.textEdited.connect(self.recalculateSLD)142 149 143 150 self.modelReset() … … 147 154 self.mapper.setModel(self.model) 148 155 self.mapper.setOrientation(QtCore.Qt.Vertical) 149 self.mapper.addMapping(self.ui.editMolecularFormula , MODEL.MOLECULAR_FORMULA) 150 self.mapper.addMapping(self.ui.editMassDensity , MODEL.MASS_DENSITY) 151 self.mapper.addMapping(self.ui.editNeutronWavelength, MODEL.NEUTRON_WAVELENGTH) 152 self.mapper.addMapping(self.ui.editXrayWavelength , MODEL.XRAY_WAVELENGTH) 156 self.mapper.addMapping(self.ui.editMolecularFormula, MODEL.MOLECULAR_FORMULA) 157 self.mapper.addMapping(self.ui.editMassDensity , MODEL.MASS_DENSITY) 158 self.mapper.addMapping(self.ui.editWavelength , MODEL.WAVELENGTH) 153 159 154 160 for key, edit in self._getOutputs().items(): … … 160 166 update = False 161 167 for index in range(top.row(), bottom.row() + 1): 162 if (index == MODEL.MOLECULAR_FORMULA) or (index == MODEL.MASS_DENSITY) or (index == MODEL. NEUTRON_WAVELENGTH) or (index == MODEL.XRAY_WAVELENGTH):168 if (index == MODEL.MOLECULAR_FORMULA) or (index == MODEL.MASS_DENSITY) or (index == MODEL.WAVELENGTH): 163 169 update = True 164 170 165 # calcu lation171 # calcualtion 166 172 if update: 167 self.recalculateSLD() 168 169 def recalculateSLD(self): 170 formula = self.ui.editMolecularFormula.text() 171 density = self.ui.editMassDensity.text() 172 neutronWavelength = self.ui.editNeutronWavelength.text() 173 xrayWavelength = self.ui.editXrayWavelength.text() 174 175 if len(formula) > 0 and len(density) > 0 and len(neutronWavelength) > 0 and len(xrayWavelength) > 0: 176 try: 177 results = sldAlgorithm(str(formula), float(density), float(neutronWavelength), float(xrayWavelength)) 178 179 def format(value): 180 return ("%-5.3g" % value).strip() 181 182 self.model.item(MODEL.NEUTRON_SLD_REAL).setText(format(results.neutron_sld_real)) 183 self.model.item(MODEL.NEUTRON_SLD_IMAG).setText(format(results.neutron_sld_imag)) 184 185 self.model.item(MODEL.XRAY_SLD_REAL).setText(format(results.xray_sld_real)) 186 self.model.item(MODEL.XRAY_SLD_IMAG).setText(format(results.xray_sld_imag)) 187 188 self.model.item(MODEL.NEUTRON_INC_XS).setText(format(results.neutron_inc_xs)) 189 self.model.item(MODEL.NEUTRON_ABS_XS).setText(format(results.neutron_abs_xs)) 190 self.model.item(MODEL.NEUTRON_LENGTH).setText(format(results.neutron_length)) 191 192 return 193 194 except Exception as e: 195 pass 196 197 for key in list(self._getOutputs().keys()): 198 self.model.item(key).setText("") 173 formula = self.model.item(MODEL.MOLECULAR_FORMULA).text() 174 density = self.model.item(MODEL.MASS_DENSITY).text() 175 wavelength = self.model.item(MODEL.WAVELENGTH).text() 176 if len(formula) > 0 and len(density) > 0 and len(wavelength) > 0: 177 try: 178 results = sldAlgorithm(str(formula), float(density), float(wavelength)) 179 180 def format(value): 181 return ("%-5.3g" % value).strip() 182 183 self.model.item(MODEL.NEUTRON_SLD_REAL).setText(format(results.neutron_sld_real)) 184 self.model.item(MODEL.NEUTRON_SLD_IMAG).setText(format(results.neutron_sld_imag)) 185 186 self.model.item(MODEL.CU_KA_SLD_REAL).setText(format(results.cu_ka_sld_real)) 187 self.model.item(MODEL.CU_KA_SLD_IMAG).setText(format(results.cu_ka_sld_imag)) 188 189 self.model.item(MODEL.MO_KA_SLD_REAL).setText(format(results.mo_ka_sld_real)) 190 self.model.item(MODEL.MO_KA_SLD_IMAG).setText(format(results.mo_ka_sld_imag)) 191 192 self.model.item(MODEL.NEUTRON_INC_XS).setText(format(results.neutron_inc_xs)) 193 self.model.item(MODEL.NEUTRON_ABS_XS).setText(format(results.neutron_abs_xs)) 194 self.model.item(MODEL.NEUTRON_LENGTH).setText(format(results.neutron_length)) 195 196 return 197 198 except Exception as e: 199 pass 200 201 for key in list(self._getOutputs().keys()): 202 self.model.item(key).setText("") 199 203 200 204 def modelReset(self): 201 205 #self.model.beginResetModel() 202 206 try: 203 self.model.item(MODEL.MOLECULAR_FORMULA ).setText("H2O") 204 self.model.item(MODEL.MASS_DENSITY ).setText("1.0") 205 self.model.item(MODEL.NEUTRON_WAVELENGTH).setText("6.0") 206 self.model.item(MODEL.XRAY_WAVELENGTH ).setText("1.0") 207 self.recalculateSLD() 207 self.model.item(MODEL.MOLECULAR_FORMULA).setText("H2O") 208 self.model.item(MODEL.MASS_DENSITY ).setText("1") 209 self.model.item(MODEL.WAVELENGTH ).setText("6") 208 210 finally: 209 211 pass … … 215 217 216 218 217 def closePanel(self):218 """219 close the window containing this panel220 """221 self.close()222 -
src/sas/qtgui/Calculators/UI/SldPanel.ui
r5c0e717 rcd2cc745 7 7 <x>0</x> 8 8 <y>0</y> 9 <width>4 90</width>10 <height>4 90</height>9 <width>447</width> 10 <height>403</height> 11 11 </rect> 12 12 </property> … … 25 25 </property> 26 26 <layout class="QGridLayout" name="gridLayout_2"> 27 <item row="3" column="0">28 <spacer name="verticalSpacer">29 <property name="orientation">30 <enum>Qt::Vertical</enum>31 </property>32 <property name="sizeHint" stdset="0">33 <size>34 <width>20</width>35 <height>40</height>36 </size>37 </property>38 </spacer>39 </item>40 <item row="4" column="0">41 <widget class="QWidget" name="widget" native="true">42 <property name="minimumSize">43 <size>44 <width>466</width>45 <height>32</height>46 </size>47 </property>48 <widget class="QPushButton" name="recalculateButton">49 <property name="geometry">50 <rect>51 <x>0</x>52 <y>0</y>53 <width>114</width>54 <height>32</height>55 </rect>56 </property>57 <property name="text">58 <string>Recalculate</string>59 </property>60 </widget>61 <widget class="QPushButton" name="helpButton">62 <property name="geometry">63 <rect>64 <x>176</x>65 <y>0</y>66 <width>114</width>67 <height>32</height>68 </rect>69 </property>70 <property name="text">71 <string>Help</string>72 </property>73 </widget>74 <widget class="QPushButton" name="closeButton">75 <property name="geometry">76 <rect>77 <x>352</x>78 <y>0</y>79 <width>114</width>80 <height>32</height>81 </rect>82 </property>83 <property name="text">84 <string>Close</string>85 </property>86 </widget>87 </widget>88 </item>89 27 <item row="0" column="0"> 90 28 <widget class="QGroupBox" name="groupBoxInput"> … … 120 58 <widget class="QLineEdit" name="editMassDensity"/> 121 59 </item> 60 <item row="2" column="1"> 61 <widget class="QLineEdit" name="editWavelength"> 62 <property name="styleSheet"> 63 <string notr="true"/> 64 </property> 65 <property name="readOnly"> 66 <bool>false</bool> 67 </property> 68 </widget> 69 </item> 122 70 <item row="2" column="2"> 123 71 <widget class="QLabel" name="label_12"> … … 138 86 <widget class="QLabel" name="label_11"> 139 87 <property name="text"> 140 <string>Neutron Wavelength</string> 141 </property> 142 </widget> 143 </item> 144 <item row="2" column="1"> 145 <widget class="QLineEdit" name="editNeutronWavelength"> 146 <property name="styleSheet"> 147 <string notr="true"/> 148 </property> 149 <property name="readOnly"> 150 <bool>false</bool> 151 </property> 152 </widget> 153 </item> 154 <item row="3" column="1"> 155 <widget class="QLineEdit" name="editXrayWavelength"/> 156 </item> 157 <item row="3" column="0"> 158 <widget class="QLabel" name="label_13"> 159 <property name="text"> 160 <string>X-Ray Wavelength</string> 161 </property> 162 </widget> 163 </item> 164 <item row="3" column="2"> 165 <widget class="QLabel" name="label"> 166 <property name="text"> 167 <string>à 168 </string> 88 <string>Wavelength</string> 169 89 </property> 170 90 </widget> … … 179 99 </property> 180 100 <layout class="QGridLayout" name="gridLayoutOutput"> 101 <item row="0" column="0"> 102 <widget class="QLabel" name="label_17"> 103 <property name="text"> 104 <string>Neutron SLD</string> 105 </property> 106 </widget> 107 </item> 181 108 <item row="0" column="1"> 182 109 <widget class="QLineEdit" name="editNeutronSldReal"> 183 <property name="enabled"> 184 <bool>false</bool> 185 </property> 186 <property name="readOnly"> 187 <bool>true</bool> 188 </property> 189 </widget> 190 </item> 191 <item row="0" column="0"> 192 <widget class="QLabel" name="label_17"> 193 <property name="text"> 194 <string>Neutron SLD</string> 195 </property> 196 </widget> 197 </item> 198 <item row="5" column="0"> 199 <widget class="QLabel" name="label_3"> 200 <property name="text"> 201 <string>Neutron 1/e length</string> 202 </property> 203 </widget> 204 </item> 205 <item row="3" column="1"> 206 <widget class="QLineEdit" name="editNeutronIncXs"> 207 <property name="enabled"> 208 <bool>false</bool> 209 </property> 210 <property name="readOnly"> 211 <bool>true</bool> 212 </property> 213 </widget> 214 </item> 215 <item row="3" column="0"> 216 <widget class="QLabel" name="label_21"> 217 <property name="text"> 218 <string>Neutron Inc. Xs</string> 110 <property name="readOnly"> 111 <bool>true</bool> 219 112 </property> 220 113 </widget> … … 227 120 </widget> 228 121 </item> 122 <item row="0" column="3"> 123 <widget class="QLineEdit" name="editNeutronSldImag"> 124 <property name="readOnly"> 125 <bool>true</bool> 126 </property> 127 </widget> 128 </item> 129 <item row="0" column="4"> 130 <widget class="QLabel" name="label_5"> 131 <property name="text"> 132 <string>1/à 133 ²</string> 134 </property> 135 </widget> 136 </item> 137 <item row="1" column="0"> 138 <widget class="QLabel" name="label_19"> 139 <property name="text"> 140 <string>Cu Ka SLD</string> 141 </property> 142 </widget> 143 </item> 144 <item row="1" column="1"> 145 <widget class="QLineEdit" name="editCuKaSldReal"> 146 <property name="styleSheet"> 147 <string notr="true"/> 148 </property> 149 <property name="readOnly"> 150 <bool>true</bool> 151 </property> 152 </widget> 153 </item> 229 154 <item row="1" column="2"> 230 155 <widget class="QLabel" name="label_20"> … … 234 159 </widget> 235 160 </item> 236 <item row="0" column="3"> 237 <widget class="QLineEdit" name="editNeutronSldImag"> 238 <property name="enabled"> 239 <bool>false</bool> 240 </property> 241 <property name="readOnly"> 242 <bool>true</bool> 243 </property> 244 </widget> 245 </item> 246 <item row="5" column="2" colspan="2"> 247 <widget class="QLabel" name="label_4"> 248 <property name="text"> 249 <string>cm</string> 250 </property> 251 </widget> 252 </item> 253 <item row="5" column="1"> 254 <widget class="QLineEdit" name="editNeutronLength"> 255 <property name="enabled"> 256 <bool>false</bool> 257 </property> 258 <property name="readOnly"> 259 <bool>true</bool> 260 </property> 261 </widget> 262 </item> 263 <item row="4" column="2" colspan="2"> 264 <widget class="QLabel" name="label_24"> 265 <property name="text"> 266 <string>1/cm</string> 267 </property> 268 </widget> 269 </item> 270 <item row="4" column="1"> 271 <widget class="QLineEdit" name="editNeutronAbsXs"> 272 <property name="enabled"> 273 <bool>false</bool> 274 </property> 275 <property name="readOnly"> 276 <bool>true</bool> 277 </property> 278 </widget> 279 </item> 280 <item row="4" column="0"> 281 <widget class="QLabel" name="label_23"> 282 <property name="text"> 283 <string>Neutron Abs. Xs</string> 284 </property> 285 </widget> 286 </item> 287 <item row="3" column="2" colspan="2"> 288 <widget class="QLabel" name="label_22"> 289 <property name="text"> 290 <string>1/cm</string> 161 <item row="1" column="3"> 162 <widget class="QLineEdit" name="editCuKaSldImag"> 163 <property name="readOnly"> 164 <bool>true</bool> 291 165 </property> 292 166 </widget> … … 300 174 </widget> 301 175 </item> 302 <item row="1" column="0"> 303 <widget class="QLabel" name="label_19"> 304 <property name="text"> 305 <string>X-Ray SLD</string> 306 </property> 307 </widget> 308 </item> 309 <item row="0" column="4"> 310 <widget class="QLabel" name="label_5"> 176 <item row="2" column="0"> 177 <widget class="QLabel" name="label"> 178 <property name="text"> 179 <string>Mo Ka SLD</string> 180 </property> 181 </widget> 182 </item> 183 <item row="2" column="1"> 184 <widget class="QLineEdit" name="editMoKaSldReal"> 185 <property name="readOnly"> 186 <bool>true</bool> 187 </property> 188 </widget> 189 </item> 190 <item row="2" column="2"> 191 <widget class="QLabel" name="label_2"> 192 <property name="text"> 193 <string>-i</string> 194 </property> 195 </widget> 196 </item> 197 <item row="2" column="3"> 198 <widget class="QLineEdit" name="editMoKaSldImag"> 199 <property name="readOnly"> 200 <bool>true</bool> 201 </property> 202 </widget> 203 </item> 204 <item row="2" column="4"> 205 <widget class="QLabel" name="label_7"> 311 206 <property name="text"> 312 207 <string>1/à … … 315 210 </widget> 316 211 </item> 317 <item row=" 2" column="0" colspan="5">212 <item row="3" column="0" colspan="5"> 318 213 <widget class="QFrame" name="frame"> 319 214 <property name="minimumSize"> … … 337 232 </widget> 338 233 </item> 339 <item row="1" column="1"> 340 <widget class="QLineEdit" name="editXraySldReal"> 341 <property name="enabled"> 342 <bool>false</bool> 343 </property> 344 <property name="readOnly"> 345 <bool>true</bool> 346 </property> 347 </widget> 348 </item> 349 <item row="1" column="3"> 350 <widget class="QLineEdit" name="editXraySldImag"> 351 <property name="enabled"> 352 <bool>false</bool> 353 </property> 354 <property name="readOnly"> 355 <bool>true</bool> 234 <item row="4" column="0"> 235 <widget class="QLabel" name="label_21"> 236 <property name="text"> 237 <string>Neutron Inc. Xs</string> 238 </property> 239 </widget> 240 </item> 241 <item row="4" column="1"> 242 <widget class="QLineEdit" name="editNeutronIncXs"> 243 <property name="readOnly"> 244 <bool>true</bool> 245 </property> 246 </widget> 247 </item> 248 <item row="4" column="2" colspan="2"> 249 <widget class="QLabel" name="label_22"> 250 <property name="text"> 251 <string>1/cm</string> 252 </property> 253 </widget> 254 </item> 255 <item row="5" column="0"> 256 <widget class="QLabel" name="label_23"> 257 <property name="text"> 258 <string>Neutron Abs. Xs</string> 259 </property> 260 </widget> 261 </item> 262 <item row="5" column="1"> 263 <widget class="QLineEdit" name="editNeutronAbsXs"> 264 <property name="readOnly"> 265 <bool>true</bool> 266 </property> 267 </widget> 268 </item> 269 <item row="5" column="2" colspan="2"> 270 <widget class="QLabel" name="label_24"> 271 <property name="text"> 272 <string>1/cm</string> 273 </property> 274 </widget> 275 </item> 276 <item row="6" column="0"> 277 <widget class="QLabel" name="label_3"> 278 <property name="text"> 279 <string>Neutron 1/e length</string> 280 </property> 281 </widget> 282 </item> 283 <item row="6" column="1"> 284 <widget class="QLineEdit" name="editNeutronLength"> 285 <property name="readOnly"> 286 <bool>true</bool> 287 </property> 288 </widget> 289 </item> 290 <item row="6" column="2" colspan="2"> 291 <widget class="QLabel" name="label_4"> 292 <property name="text"> 293 <string>cm</string> 356 294 </property> 357 295 </widget> 358 296 </item> 359 297 </layout> 298 </widget> 299 </item> 300 <item row="2" column="0"> 301 <spacer name="verticalSpacer"> 302 <property name="orientation"> 303 <enum>Qt::Vertical</enum> 304 </property> 305 <property name="sizeHint" stdset="0"> 306 <size> 307 <width>20</width> 308 <height>40</height> 309 </size> 310 </property> 311 </spacer> 312 </item> 313 <item row="3" column="0"> 314 <widget class="QDialogButtonBox" name="buttonBox"> 315 <property name="orientation"> 316 <enum>Qt::Horizontal</enum> 317 </property> 318 <property name="standardButtons"> 319 <set>QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Reset</set> 320 </property> 321 <property name="centerButtons"> 322 <bool>true</bool> 323 </property> 360 324 </widget> 361 325 </item> … … 365 329 <tabstop>editMolecularFormula</tabstop> 366 330 <tabstop>editMassDensity</tabstop> 367 <tabstop>edit NeutronWavelength</tabstop>331 <tabstop>editWavelength</tabstop> 368 332 <tabstop>editNeutronSldReal</tabstop> 369 333 <tabstop>editNeutronSldImag</tabstop> 334 <tabstop>editCuKaSldReal</tabstop> 335 <tabstop>editCuKaSldImag</tabstop> 336 <tabstop>editMoKaSldReal</tabstop> 337 <tabstop>editMoKaSldImag</tabstop> 370 338 <tabstop>editNeutronIncXs</tabstop> 371 339 <tabstop>editNeutronAbsXs</tabstop> 372 340 <tabstop>editNeutronLength</tabstop> 341 <tabstop>buttonBox</tabstop> 373 342 </tabstops> 374 343 <resources/> 375 <connections/> 344 <connections> 345 <connection> 346 <sender>buttonBox</sender> 347 <signal>accepted()</signal> 348 <receiver>SldPanel</receiver> 349 <slot>accept()</slot> 350 <hints> 351 <hint type="sourcelabel"> 352 <x>248</x> 353 <y>254</y> 354 </hint> 355 <hint type="destinationlabel"> 356 <x>157</x> 357 <y>274</y> 358 </hint> 359 </hints> 360 </connection> 361 <connection> 362 <sender>buttonBox</sender> 363 <signal>rejected()</signal> 364 <receiver>SldPanel</receiver> 365 <slot>reject()</slot> 366 <hints> 367 <hint type="sourcelabel"> 368 <x>316</x> 369 <y>260</y> 370 </hint> 371 <hint type="destinationlabel"> 372 <x>286</x> 373 <y>274</y> 374 </hint> 375 </hints> 376 </connection> 377 </connections> 376 378 </ui> -
src/sas/qtgui/MainWindow/DataExplorer.py
rfd7ef36 r9463ca2 4 4 import time 5 5 import logging 6 import re 6 7 7 8 from PyQt5 import QtCore … … 36 37 # The controller which is responsible for managing signal slots connections 37 38 # for the gui and providing an interface to the data model. 39 40 # This matches the ID of a plot created using FittingLogic._create1DPlot, e.g. 41 # "5 [P(Q)] modelname" 42 # or 43 # "4 modelname". 44 # Useful for determining whether the plot in question is for an intermediate result, such as P(Q) or S(Q) in the 45 # case of a product model; the identifier for this is held in square brackets, as in the example above. 46 theory_plot_ID_pattern = re.compile(r"^([0-9]+)\s+(\[(.*)\]\s+)?(.*)$") 38 47 39 48 def __init__(self, parent=None, guimanager=None, manager=None): … … 385 394 # Notify the GuiManager about the send request 386 395 self._perspective().setData(data_item=selected_items, is_batch=self.chkBatch.isChecked()) 387 388 def freezeCheckedData(self):389 """390 Convert checked results (fitted model, residuals) into separate dataset.391 """392 outer_index = -1393 theories_copied = 0394 orig_model_size = self.model.rowCount()395 while outer_index < orig_model_size:396 outer_index += 1397 outer_item = self.model.item(outer_index)398 if not outer_item:399 continue400 if not outer_item.isCheckable():401 continue402 # Look for checked inner items403 inner_index = -1404 while inner_index < outer_item.rowCount():405 inner_item = outer_item.child(inner_index)406 inner_index += 1407 if not inner_item:408 continue409 if not inner_item.isCheckable():410 continue411 if inner_item.checkState() != QtCore.Qt.Checked:412 continue413 self.model.beginResetModel()414 theories_copied += 1415 new_item = self.cloneTheory(inner_item)416 self.model.appendRow(new_item)417 self.model.endResetModel()418 419 freeze_msg = ""420 if theories_copied == 0:421 return422 elif theories_copied == 1:423 freeze_msg = "1 theory copied to a separate data set"424 elif theories_copied > 1:425 freeze_msg = "%i theories copied to separate data sets" % theories_copied426 else:427 freeze_msg = "Unexpected number of theories copied: %i" % theories_copied428 raise AttributeError(freeze_msg)429 self.communicator.statusBarUpdateSignal.emit(freeze_msg)430 396 431 397 def freezeTheory(self, event): … … 572 538 else: 573 539 # Don't plot intermediate results, e.g. P(Q), S(Q) 574 match = GuiUtils.theory_plot_ID_pattern.match(plot_id)540 match = self.theory_plot_ID_pattern.match(plot_id) 575 541 # 2nd match group contains the identifier for the intermediate result, if present (e.g. "[P(Q)]") 576 542 if match and match.groups()[1] != None: … … 578 544 # 'sophisticated' test to generate standalone plot for residuals 579 545 if 'esiduals' in plot.title: 580 plot.yscale='linear' 581 self.plotData([(item, plot)]) 546 self.plotData([(item, plot)], transform=False) 582 547 else: 583 548 new_plots.append((item, plot)) … … 860 825 return wlist 861 826 862 def setItemsCheckability(self, model, dimension=None, checked=False):863 """864 For a given model, check or uncheck all items of given dimension865 """866 mode = QtCore.Qt.Checked if checked else QtCore.Qt.Unchecked867 868 assert isinstance(checked, bool)869 870 types = (None, Data1D, Data2D)871 assert dimension in types872 873 for index in range(model.rowCount()):874 item = model.item(index)875 if dimension is not None and not isinstance(GuiUtils.dataFromItem(item), dimension):876 continue877 if item.isCheckable() and item.checkState() != mode:878 item.setCheckState(mode)879 # look for all children880 for inner_index in range(item.rowCount()):881 child = item.child(inner_index)882 if child.isCheckable() and child.checkState() != mode:883 child.setCheckState(mode)884 885 827 def selectData(self, index): 886 828 """ … … 893 835 # Respond appropriately 894 836 if index == 0: 895 self.setItemsCheckability(self.model, checked=True) 896 837 # Select All 838 for index in range(self.model.rowCount()): 839 item = self.model.item(index) 840 if item.isCheckable() and item.checkState() == QtCore.Qt.Unchecked: 841 item.setCheckState(QtCore.Qt.Checked) 897 842 elif index == 1: 898 843 # De-select All 899 self.setItemsCheckability(self.model, checked=False) 844 for index in range(self.model.rowCount()): 845 item = self.model.item(index) 846 if item.isCheckable() and item.checkState() == QtCore.Qt.Checked: 847 item.setCheckState(QtCore.Qt.Unchecked) 900 848 901 849 elif index == 2: 902 850 # Select All 1-D 903 self.setItemsCheckability(self.model, dimension=Data1D, checked=True) 851 for index in range(self.model.rowCount()): 852 item = self.model.item(index) 853 item.setCheckState(QtCore.Qt.Unchecked) 854 855 try: 856 is1D = isinstance(GuiUtils.dataFromItem(item), Data1D) 857 except AttributeError: 858 msg = "Bad structure of the data model." 859 raise RuntimeError(msg) 860 861 if is1D: 862 item.setCheckState(QtCore.Qt.Checked) 904 863 905 864 elif index == 3: 906 865 # Unselect All 1-D 907 self.setItemsCheckability(self.model, dimension=Data1D, checked=False) 866 for index in range(self.model.rowCount()): 867 item = self.model.item(index) 868 869 try: 870 is1D = isinstance(GuiUtils.dataFromItem(item), Data1D) 871 except AttributeError: 872 msg = "Bad structure of the data model." 873 raise RuntimeError(msg) 874 875 if item.isCheckable() and item.checkState() == QtCore.Qt.Checked and is1D: 876 item.setCheckState(QtCore.Qt.Unchecked) 908 877 909 878 elif index == 4: 910 879 # Select All 2-D 911 self.setItemsCheckability(self.model, dimension=Data2D, checked=True) 880 for index in range(self.model.rowCount()): 881 item = self.model.item(index) 882 item.setCheckState(QtCore.Qt.Unchecked) 883 try: 884 is2D = isinstance(GuiUtils.dataFromItem(item), Data2D) 885 except AttributeError: 886 msg = "Bad structure of the data model." 887 raise RuntimeError(msg) 888 889 if is2D: 890 item.setCheckState(QtCore.Qt.Checked) 912 891 913 892 elif index == 5: 914 893 # Unselect All 2-D 915 self.setItemsCheckability(self.model, dimension=Data2D, checked=False) 894 for index in range(self.model.rowCount()): 895 item = self.model.item(index) 896 897 try: 898 is2D = isinstance(GuiUtils.dataFromItem(item), Data2D) 899 except AttributeError: 900 msg = "Bad structure of the data model." 901 raise RuntimeError(msg) 902 903 if item.isCheckable() and item.checkState() == QtCore.Qt.Checked and is2D: 904 item.setCheckState(QtCore.Qt.Unchecked) 916 905 917 906 else: … … 1281 1270 self.theory_model.appendRow(model_item) 1282 1271 1283 def deleteIntermediateTheoryPlotsByModelID(self, model_id):1284 """Given a model's ID, deletes all items in the theory item model which reference the same ID. Useful in the1285 case of intermediate results disappearing when changing calculations (in which case you don't want them to be1286 retained in the list)."""1287 items_to_delete = []1288 for r in range(self.theory_model.rowCount()):1289 item = self.theory_model.item(r, 0)1290 data = item.child(0).data()1291 if not hasattr(data, "id"):1292 return1293 match = GuiUtils.theory_plot_ID_pattern.match(data.id)1294 if match:1295 item_model_id = match.groups()[-1]1296 if item_model_id == model_id:1297 # Only delete those identified as an intermediate plot1298 if match.groups()[2] not in (None, ""):1299 items_to_delete.append(item)1300 1301 for item in items_to_delete:1302 self.theory_model.removeRow(item.row()) -
src/sas/qtgui/MainWindow/GuiManager.py
r0eff615 r0eff615 395 395 self.communicate.perspectiveChangedSignal.connect(self.perspectiveChanged) 396 396 self.communicate.updateTheoryFromPerspectiveSignal.connect(self.updateTheoryFromPerspective) 397 self.communicate.deleteIntermediateTheoryPlotsSignal.connect(self.deleteIntermediateTheoryPlotsByModelID)398 397 self.communicate.plotRequestedSignal.connect(self.showPlot) 399 398 self.communicate.plotFromFilenameSignal.connect(self.showPlotFromFilename) … … 439 438 self._workspace.actionImage_Viewer.triggered.connect(self.actionImage_Viewer) 440 439 self._workspace.actionOrientation_Viewer.triggered.connect(self.actionOrientation_Viewer) 441 self._workspace.actionFreeze_Theory.triggered.connect(self.actionFreeze_Theory)442 440 # Fitting 443 441 self._workspace.actionNew_Fit_Page.triggered.connect(self.actionNew_Fit_Page) … … 686 684 self._workspace.addDockWidget(Qt.RightDockWidgetArea, self.ipDockWidget) 687 685 688 def actionFreeze_Theory(self):689 """690 Convert a child index with data into a separate top level dataset691 """692 self.filesWidget.freezeCheckedData()693 694 686 def actionOrientation_Viewer(self): 695 687 """ … … 887 879 """ 888 880 self.filesWidget.updateTheoryFromPerspective(index) 889 890 def deleteIntermediateTheoryPlotsByModelID(self, model_id):891 """892 Catch the signal to delete items in the Theory item model which correspond to a model ID.893 Send the request to the DataExplorer for updating the theory model.894 """895 self.filesWidget.deleteIntermediateTheoryPlotsByModelID(model_id)896 881 897 882 def updateModelFromDataOperationPanel(self, new_item, new_datalist_item): -
src/sas/qtgui/MainWindow/UI/DataExplorerUI.ui
rf4a6f2c rd1fa2b8 44 44 <property name="sizePolicy"> 45 45 <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> 46 <horstretch> 0</horstretch>46 <horstretch>5</horstretch> 47 47 <verstretch>5</verstretch> 48 48 </sizepolicy> … … 50 50 <property name="minimumSize"> 51 51 <size> 52 <width>1 20</width>53 <height> 40</height>52 <width>154</width> 53 <height>50</height> 54 54 </size> 55 55 </property> … … 64 64 </property> 65 65 <property name="styleSheet"> 66 <string notr="true">font: 1 1pt "MS Shell Dlg 2";</string>66 <string notr="true">font: 13pt "MS Shell Dlg 2";</string> 67 67 </property> 68 68 <property name="text"> … … 75 75 <property name="iconSize"> 76 76 <size> 77 <width> 32</width>78 <height> 32</height>77 <width>48</width> 78 <height>48</height> 79 79 </size> 80 80 </property> … … 183 183 <property name="sizePolicy"> 184 184 <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> 185 <horstretch> 0</horstretch>185 <horstretch>5</horstretch> 186 186 <verstretch>5</verstretch> 187 187 </sizepolicy> … … 189 189 <property name="minimumSize"> 190 190 <size> 191 <width>1 45</width>192 <height> 40</height>191 <width>170</width> 192 <height>50</height> 193 193 </size> 194 194 </property> … … 201 201 <property name="font"> 202 202 <font> 203 <family>MS Shell Dlg 2</family> 204 <pointsize>11</pointsize> 205 <weight>50</weight> 206 <italic>false</italic> 207 <bold>false</bold> 203 <pointsize>13</pointsize> 208 204 </font> 209 205 </property> … … 212 208 </property> 213 209 <property name="styleSheet"> 214 <string notr="true">font: 1 1pt "MS Shell Dlg 2";</string>210 <string notr="true">font: 13pt "MS Shell Dlg 2";</string> 215 211 </property> 216 212 <property name="text"> … … 223 219 <property name="iconSize"> 224 220 <size> 225 <width> 32</width>226 <height> 32</height>221 <width>48</width> 222 <height>48</height> 227 223 </size> 228 224 </property> … … 239 235 <property name="font"> 240 236 <font> 241 <pointsize>1 1</pointsize>237 <pointsize>12</pointsize> 242 238 </font> 243 239 </property> -
src/sas/qtgui/MainWindow/UI/MainWindowUI.ui
r6b50296 raa1db44 64 64 <addaction name="actionReport"/> 65 65 <addaction name="actionReset"/> 66 <addaction name="separator"/>67 <addaction name="actionFreeze_Theory"/>68 66 </widget> 69 67 <widget class="QMenu" name="menuView"> … … 537 535 </property> 538 536 </action> 539 <action name="actionFreeze_Theory">540 <property name="text">541 <string>Freeze Theory</string>542 </property>543 </action>544 537 </widget> 545 538 <resources/> -
src/sas/qtgui/MainWindow/UnitTesting/DataExplorerTest.py
ra24eacf r573c383 71 71 self.assertEqual(self.form.cmdFreeze.text(), "Freeze Theory") 72 72 self.assertEqual(self.form.cmdSendTo.text(), "Send data to") 73 self.assertEqual(self.form.cmdSendTo.iconSize(), QSize( 32, 32))73 self.assertEqual(self.form.cmdSendTo.iconSize(), QSize(48, 48)) 74 74 self.assertIsInstance(self.form.cmdSendTo.icon(), QIcon) 75 75 self.assertEqual(self.form.chkBatch.text(), "Batch mode") … … 352 352 # Test the current selection 353 353 self.assertTrue(item1D.checkState() == Qt.Checked) 354 self.assertTrue(item2D.checkState() == Qt. Checked)354 self.assertTrue(item2D.checkState() == Qt.Unchecked) 355 355 356 356 # unselect 1d data … … 359 359 # Test the current selection 360 360 self.assertTrue(item1D.checkState() == Qt.Unchecked) 361 self.assertTrue(item2D.checkState() == Qt. Checked)361 self.assertTrue(item2D.checkState() == Qt.Unchecked) 362 362 363 363 # select 2d data -
src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
rb764ae5 rff3b293 430 430 431 431 theory_name = str(current_data.name.split()[0]) 432 res _name = reference_data.filename if reference_data.filename else reference_data.name433 residuals.name = "Residuals for " + str(theory_name) + "[" + res_name+ "]"432 residuals.name = "Residuals for " + str(theory_name) + "[" + \ 433 str(reference_data.filename) + "]" 434 434 residuals.title = residuals.name 435 435 residuals.ytransform = 'y' … … 457 457 """ 458 458 weight = None 459 if data is None:460 return []461 459 if is2d: 462 if not hasattr(data, 'err_data'):463 return []464 460 dy_data = data.err_data 465 461 data = data.data 466 462 else: 467 if not hasattr(data, 'dy'):468 return []469 463 dy_data = data.dy 470 464 data = data.y -
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
r0eff615 r0eff615 60 60 61 61 logger = logging.getLogger(__name__) 62 62 63 63 64 class ToolTippedItemModel(QtGui.QStandardItemModel): … … 224 225 self.models = {} 225 226 # Parameters to fit 226 self.main_params_to_fit = [] 227 self.poly_params_to_fit = [] 228 self.magnet_params_to_fit = [] 229 227 self.parameters_to_fit = None 230 228 # Fit options 231 229 self.q_range_min = 0.005 … … 265 263 self.has_magnet_error_column = False 266 264 267 # If the widget generated theory item, save it268 self.theory_item = None269 270 265 # signal communicator 271 266 self.communicate = self.parent.communicate … … 390 385 # Tag along functionality 391 386 self.label.setText("Data loaded from: ") 392 if self.logic.data.filename: 393 self.lblFilename.setText(self.logic.data.filename) 394 else: 395 self.lblFilename.setText(self.logic.data.name) 387 self.lblFilename.setText(self.logic.data.filename) 396 388 self.updateQRange() 397 389 # Switch off Data2D control … … 525 517 526 518 # Signals from separate tabs asking for replot 519 self.options_widget.plot_signal.connect(self.onOptionsUpdate) 527 520 self.options_widget.plot_signal.connect(self.onOptionsUpdate) 528 521 … … 955 948 model = self.cbModel.currentText() 956 949 957 # Assure the control is active 958 if not self.cbModel.isEnabled(): 959 return 960 # Empty combobox forced to be read 950 # empty combobox forced to be read 961 951 if not model: 962 952 return 953 # Reset structure factor 954 self.cbStructureFactor.setCurrentIndex(0) 963 955 964 956 # Reset parameters to fit 965 self. resetParametersToFit()957 self.parameters_to_fit = None 966 958 self.has_error_column = False 967 959 self.has_poly_error_column = False 968 960 969 structure = None 970 if self.cbStructureFactor.isEnabled(): 971 structure = str(self.cbStructureFactor.currentText()) 972 self.respondToModelStructure(model=model, structure_factor=structure) 961 self.respondToModelStructure(model=model, structure_factor=None) 973 962 974 963 def onSelectBatchFilename(self, data_index): … … 990 979 991 980 # Reset parameters to fit 992 self. resetParametersToFit()981 self.parameters_to_fit = None 993 982 self.has_error_column = False 994 983 self.has_poly_error_column = False 995 984 996 985 self.respondToModelStructure(model=model, structure_factor=structure) 997 998 def resetParametersToFit(self):999 """1000 Clears the list of parameters to be fitted1001 """1002 self.main_params_to_fit = []1003 self.poly_params_to_fit = []1004 self.magnet_params_to_fit = []1005 986 1006 987 def onCustomModelChange(self): … … 1113 1094 self.disableModelCombo() 1114 1095 self.enableStructureCombo() 1115 # set the index to 01116 self.cbStructureFactor.setCurrentIndex(0)1117 self.model_parameters = None1118 1096 self._model_model.clear() 1119 1097 return … … 1140 1118 model_row = item.row() 1141 1119 name_index = self._poly_model.index(model_row, 0) 1142 parameter_name = str(name_index.data()) # "distribution of sld" etc.1143 if " istribution of" in parameter_name:1120 parameter_name = str(name_index.data()).lower() # "distribution of sld" etc. 1121 if "distribution of" in parameter_name: 1144 1122 # just the last word 1145 1123 parameter_name = parameter_name.rsplit()[-1] … … 1153 1131 parameter_name = parameter_name + '.width' 1154 1132 if value == QtCore.Qt.Checked: 1155 self.p oly_params_to_fit.append(parameter_name)1133 self.parameters_to_fit.append(parameter_name) 1156 1134 else: 1157 if parameter_name in self.p oly_params_to_fit:1158 self.p oly_params_to_fit.remove(parameter_name)1159 self.cmdFit.setEnabled(self. haveParamsToFit())1135 if parameter_name in self.parameters_to_fit: 1136 self.parameters_to_fit.remove(parameter_name) 1137 self.cmdFit.setEnabled(self.parameters_to_fit != [] and self.logic.data_is_loaded) 1160 1138 1161 1139 elif model_column in [delegate.poly_min, delegate.poly_max]: … … 1209 1187 value = item.checkState() 1210 1188 if value == QtCore.Qt.Checked: 1211 self. magnet_params_to_fit.append(parameter_name)1189 self.parameters_to_fit.append(parameter_name) 1212 1190 else: 1213 if parameter_name in self. magnet_params_to_fit:1214 self. magnet_params_to_fit.remove(parameter_name)1215 self.cmdFit.setEnabled(self. haveParamsToFit())1191 if parameter_name in self.parameters_to_fit: 1192 self.parameters_to_fit.remove(parameter_name) 1193 self.cmdFit.setEnabled(self.parameters_to_fit != [] and self.logic.data_is_loaded) 1216 1194 # Update state stack 1217 1195 self.updateUndo() … … 1498 1476 qmin = self.q_range_min 1499 1477 qmax = self.q_range_max 1500 1501 params_to_fit = self.main_params_to_fit 1502 if self.chkPolydispersity.isChecked(): 1503 params_to_fit += self.poly_params_to_fit 1504 if self.chkMagnetism.isChecked(): 1505 params_to_fit += self.magnet_params_to_fit 1478 params_to_fit = self.parameters_to_fit 1506 1479 if not params_to_fit: 1507 1480 raise ValueError('Fitting requires at least one parameter to optimize.') 1481 1482 # Potential smearing added 1483 # Remember that smearing_min/max can be None -> 1484 # deal with it until Python gets discriminated unions 1485 self.addWeightingToData(data) 1508 1486 1509 1487 # Get the constraints. … … 1523 1501 data = GuiUtils.dataFromItem(fit_index) 1524 1502 # Potential weights added directly to data 1525 weighted_data =self.addWeightingToData(data)1503 self.addWeightingToData(data) 1526 1504 try: 1527 fitter_single.set_model(model, fit_id, params_to_fit, data= weighted_data,1505 fitter_single.set_model(model, fit_id, params_to_fit, data=data, 1528 1506 constraints=constraints) 1529 1507 except ValueError as ex: 1530 1508 raise ValueError("Setting model parameters failed with: %s" % ex) 1531 1509 1532 qmin, qmax, _ = self.logic.computeRangeFromData( weighted_data)1533 fitter_single.set_data(data= weighted_data, id=fit_id, smearer=smearer, qmin=qmin,1510 qmin, qmax, _ = self.logic.computeRangeFromData(data) 1511 fitter_single.set_data(data=data, id=fit_id, smearer=smearer, qmin=qmin, 1534 1512 qmax=qmax) 1535 1513 fitter_single.select_problem_for_fit(id=fit_id, value=1) … … 1922 1900 Adds weighting contribution to fitting data 1923 1901 """ 1924 new_data = copy.deepcopy(data)1925 1902 # Send original data for weighting 1926 1903 weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 1927 1904 if self.is2D: 1928 new_data.err_data = weight1905 data.err_data = weight 1929 1906 else: 1930 new_data.dy = weight 1931 1932 return new_data 1907 data.dy = weight 1908 pass 1933 1909 1934 1910 def updateQRange(self): … … 1964 1940 # Allow the SF combobox visibility for the given sasmodel 1965 1941 self.enableStructureFactorControl(structure_factor) 1966 if self.cbStructureFactor.isEnabled():1967 structure_factor = self.cbStructureFactor.currentText()1968 self.fromStructureFactorToQModel(structure_factor)1969 1942 1970 1943 # Then, add multishells … … 2001 1974 """ 2002 1975 name = model_name 2003 kernel_module = None2004 1976 if self.cbCategory.currentText() == CATEGORY_CUSTOM: 2005 1977 # custom kernel load requires full path … … 2007 1979 try: 2008 1980 kernel_module = generate.load_kernel_module(name) 2009 except ModuleNotFoundError as ex: 2010 pass 2011 2012 if kernel_module is None: 2013 # mismatch between "name" attribute and actual filename. 2014 curr_model = self.models[model_name] 2015 name, _ = os.path.splitext(os.path.basename(curr_model.filename)) 2016 try: 2017 kernel_module = generate.load_kernel_module(name) 2018 except ModuleNotFoundError as ex: 2019 logging.error("Can't find the model "+ str(ex)) 2020 return 1981 except ModuleNotFoundError: 1982 # maybe it's a recategorised custom model? 1983 name = os.path.join(ModelUtilities.find_plugins_dir(), model_name+".py") 1984 # If this rises, it's a valid problem. 1985 kernel_module = generate.load_kernel_module(name) 2021 1986 2022 1987 if hasattr(kernel_module, 'parameters'): … … 2061 2026 Setting model parameters into QStandardItemModel based on selected _structure factor_ 2062 2027 """ 2063 if structure_factor is None or structure_factor=="None":2064 return2065 2028 structure_module = generate.load_kernel_module(structure_factor) 2066 2029 structure_parameters = modelinfo.make_parameter_table(getattr(structure_module, 'parameters', [])) … … 2082 2045 self._last_model_row = self._model_model.rowCount() 2083 2046 2084 def haveParamsToFit(self):2085 """2086 Finds out if there are any parameters ready to be fitted2087 """2088 return (self.main_params_to_fit!=[]2089 or self.poly_params_to_fit!=[]2090 or self.magnet_params_to_fit != []) and \2091 self.logic.data_is_loaded2092 2093 2047 def onMainParamsChange(self, item): 2094 2048 """ … … 2099 2053 if model_column == 0: 2100 2054 self.checkboxSelected(item) 2101 self.cmdFit.setEnabled(self. haveParamsToFit())2055 self.cmdFit.setEnabled(self.parameters_to_fit != [] and self.logic.data_is_loaded) 2102 2056 # Update state stack 2103 2057 self.updateUndo() … … 2158 2112 # Convert to proper indices and set requested enablement 2159 2113 self.setParameterSelection(status) 2114 #[self._model_model.item(row, 0).setCheckState(status) for row in self.selectedParameters()] 2160 2115 self._model_model.blockSignals(False) 2161 2116 2162 2117 # update the list of parameters to fit 2163 self.main_params_to_fit = self.checkedListFromModel(self._model_model) 2118 main_params = self.checkedListFromModel(self._model_model) 2119 poly_params = self.checkedListFromModel(self._poly_model) 2120 magnet_params = self.checkedListFromModel(self._magnet_model) 2121 2122 # Retrieve poly params names 2123 poly_params = [param.rsplit()[-1] + '.width' for param in poly_params] 2124 2125 self.parameters_to_fit = main_params + poly_params + magnet_params 2164 2126 2165 2127 def checkedListFromModel(self, model): … … 2213 2175 name = self.nameFromData(fitted_data) 2214 2176 # Notify the GUI manager so it can create the theory model in DataExplorer 2215 self.theory_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name)2216 self.communicate.updateTheoryFromPerspectiveSignal.emit( self.theory_item)2177 new_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name) 2178 self.communicate.updateTheoryFromPerspectiveSignal.emit(new_item) 2217 2179 2218 2180 def nameFromData(self, fitted_data): … … 2248 2210 completefn = self.methodCompleteForData() 2249 2211 smearer = self.smearing_widget.smearer() 2250 weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting)2251 2252 2212 # Awful API to a backend method. 2253 2213 calc_thread = self.methodCalculateForData()(data=data, … … 2258 2218 smearer=smearer, 2259 2219 state=None, 2260 weight= weight,2220 weight=None, 2261 2221 fid=None, 2262 2222 toggle_mode_on=False, … … 2306 2266 residuals = self.calculateResiduals(fitted_data) 2307 2267 self.model_data = fitted_data 2308 new_plots = [fitted_data] 2309 if residuals is not None: 2310 new_plots.append(residuals) 2311 2312 if self.data_is_loaded: 2313 GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_plots) 2314 else: 2315 # delete theory items for the model, in order to get rid of any redundant items, e.g. beta(Q), S_eff(Q) 2316 self.communicate.deleteIntermediateTheoryPlotsSignal.emit(self.kernel_module.id) 2268 2269 new_plots = [fitted_data, residuals] 2317 2270 2318 2271 # Create plots for intermediate product data … … 2329 2282 new_plots.append(sq_data) 2330 2283 2331 # Update/generate plots 2284 if self.data_is_loaded: 2285 GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_plots) 2286 2332 2287 for plot in new_plots: 2333 self.communicate.plotUpdateSignal.emit([plot]) 2288 if hasattr(plot, "id") and "esidual" in plot.id: 2289 # TODO: fix updates to residuals plot 2290 pass 2291 elif plot is not None: 2292 self.communicate.plotUpdateSignal.emit([plot]) 2334 2293 2335 2294 def complete2D(self, return_data): … … 2349 2308 2350 2309 # Modify fitted_data with weighting 2351 weighted_data =self.addWeightingToData(fitted_data)2352 2353 self.createNewIndex( weighted_data)2310 self.addWeightingToData(fitted_data) 2311 2312 self.createNewIndex(fitted_data) 2354 2313 # Calculate difference between return_data and logic.data 2355 self.chi2 = FittingUtilities.calculateChi2( weighted_data, self.logic.data)2314 self.chi2 = FittingUtilities.calculateChi2(fitted_data, self.logic.data) 2356 2315 # Update the control 2357 2316 chi2_repr = "---" if self.chi2 is None else GuiUtils.formatNumber(self.chi2, high=True) 2358 2317 self.lblChi2Value.setText(chi2_repr) 2359 2318 2319 # self.communicate.plotUpdateSignal.emit([fitted_data]) 2320 2360 2321 # Plot residuals if actual data 2361 2322 if not self.data_is_loaded: 2362 2323 return 2363 2324 2364 residuals_plot = FittingUtilities.plotResiduals(self.data, weighted_data)2325 residuals_plot = FittingUtilities.plotResiduals(self.data, fitted_data) 2365 2326 residuals_plot.id = "Residual " + residuals_plot.id 2366 2327 self.createNewIndex(residuals_plot) … … 2431 2392 self._poly_model.clear() 2432 2393 2433 parameters = self.model_parameters.form_volume_parameters2434 if self.is2D:2435 parameters += self.model_parameters.orientation_parameters2436 2437 2394 [self.setPolyModelParameters(i, param) for i, param in \ 2438 enumerate(parameters) if param.polydisperse] 2439 2395 enumerate(self.model_parameters.form_volume_parameters) if param.polydisperse] 2440 2396 FittingUtilities.addPolyHeadersToModel(self._poly_model) 2441 2397 … … 2795 2751 2796 2752 fp.chi2 = self.chi2 2797 fp.main_params_to_fit = self.main_params_to_fit 2798 fp.poly_params_to_fit = self.poly_params_to_fit 2799 fp.magnet_params_to_fit = self.magnet_params_to_fit 2753 fp.parameters_to_fit = self.parameters_to_fit 2800 2754 fp.kernel_module = self.kernel_module 2801 2755 … … 2857 2811 if self.all_data: 2858 2812 index = self.all_data[self.data_index] 2859 else:2860 index = self.theory_item2861 2813 report_logic = ReportPageLogic(self, 2862 2814 kernel_module=self.kernel_module, -
src/sas/qtgui/Perspectives/Fitting/ModelThread.py
r2df558e r3ae9179 117 117 self.source) 118 118 else: 119 self.complete fn((output,120 self.data,121 self.page_id,122 self.model,123 s elf.state,124 self.toggle_mode_on,125 elapsed ,126 index _model,127 self.fid,128 self.qmin,129 self.qmax,130 self.weight,119 self.complete(image=output, 120 data=self.data, 121 page_id=self.page_id, 122 model=self.model, 123 state=self.state, 124 toggle_mode_on=self.toggle_mode_on, 125 elapsed=elapsed, 126 index=index_model, 127 fid=self.fid, 128 qmin=self.qmin, 129 qmax=self.qmax, 130 weight=self.weight, 131 131 #qstep=self.qstep, 132 self.update_chisqr,133 s elf.source))132 update_chisqr=self.update_chisqr, 133 source=self.source) 134 134 135 135 … … 250 250 pq_values, sq_values) 251 251 else: 252 self.completefn((self.data.x[index], output[index], 253 self.page_id, 254 self.state, 255 self.weight, 256 self.fid, 257 self.toggle_mode_on, 258 elapsed, index, self.model, 259 self.data, 260 self.update_chisqr, 261 self.source, 262 unsmeared_output, unsmeared_data, unsmeared_error, 263 pq_values, sq_values)) 252 self.complete(x=self.data.x[index], y=output[index], 253 page_id=self.page_id, 254 state=self.state, 255 weight=self.weight, 256 fid=self.fid, 257 toggle_mode_on=self.toggle_mode_on, 258 elapsed=elapsed, index=index, model=self.model, 259 data=self.data, 260 update_chisqr=self.update_chisqr, 261 source=self.source, 262 unsmeared_model=unsmeared_output, 263 unsmeared_data=unsmeared_data, 264 unsmeared_error=unsmeared_error, 265 pq_model=pq_values, 266 sq_model=sq_values) 264 267 265 268 def results(self): -
src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py
rb764ae5 re20870bc 79 79 self.weightingGroup.buttonClicked.connect(self.onWeightingChoice) 80 80 81 self.qmin = QMIN_DEFAULT82 self.qmax = QMAX_DEFAULT83 self.npts = NPTS_DEFAULT84 if self.logic.data_is_loaded:85 self.qmin, self.qmax, self.npts = self.logic.computeDataRange()86 81 self.initModel() 87 82 self.initMapper() 88 83 self.model.blockSignals(True) 89 self.updateQRange( self.qmin, self.qmax, self.npts)90 self.txtMaxRange.setText(str( self.qmax))91 self.txtMinRange.setText(str( self.qmin))92 self.txtNpts.setText(str( self.npts))93 self.txtNptsFit.setText(str( self.npts))84 self.updateQRange(QMIN_DEFAULT, QMAX_DEFAULT, NPTS_DEFAULT) 85 self.txtMaxRange.setText(str(QMAX_DEFAULT)) 86 self.txtMinRange.setText(str(QMIN_DEFAULT)) 87 self.txtNpts.setText(str(NPTS_DEFAULT)) 88 self.txtNptsFit.setText(str(NPTS_DEFAULT)) 94 89 self.model.blockSignals(False) 95 90 … … 132 127 Callback for running the mask editor 133 128 """ 134 if isinstance(self.logic.data, Data2D):135 self.parent.communicate.maskEditorSignal.emit(self.logic.data)129 self.parent.communicate.maskEditorSignal.emit(self.logic.data) 130 pass 136 131 137 132 def onRangeReset(self): … … 139 134 Callback for resetting qmin/qmax 140 135 """ 141 self.updateQRange( self.qmin, self.qmax, self.npts)136 self.updateQRange(QMIN_DEFAULT, QMAX_DEFAULT, NPTS_DEFAULT) 142 137 143 138 def onWeightingChoice(self, button): … … 162 157 Enable/disable various UI elements based on data loaded 163 158 """ 164 is2Ddata = isinstance(self.logic.data, Data2D)165 159 self.boxWeighting.setEnabled(True) 166 self.cmdMaskEdit.setEnabled( is2Ddata)160 self.cmdMaskEdit.setEnabled(True) 167 161 # Switch off txtNpts related controls 168 162 self.txtNpts.setEnabled(False) … … 184 178 self.model.item(MODEL.index('MAX_RANGE')).setText(str(q_range_max)) 185 179 self.model.item(MODEL.index('NPTS')).setText(str(npts)) 186 self.qmin, self.qmax, self.npts = q_range_min, q_range_max, npts187 180 188 181 def state(self): -
src/sas/qtgui/Perspectives/Fitting/UI/FittingWidgetUI.ui
rd686ff1 rc1cfa80 7 7 <x>0</x> 8 8 <y>0</y> 9 <width> 566</width>10 <height>6 46</height>9 <width>680</width> 10 <height>605</height> 11 11 </rect> 12 12 </property> … … 19 19 <property name="minimumSize"> 20 20 <size> 21 <width>4 45</width>22 <height> 540</height>21 <width>434</width> 22 <height>466</height> 23 23 </size> 24 24 </property> -
src/sas/qtgui/Perspectives/Fitting/UI/OptionsWidgetUI.ui
r79bd268 rc1e380e 8 8 <y>0</y> 9 9 <width>522</width> 10 <height> 455</height>10 <height>667</height> 11 11 </rect> 12 12 </property> -
src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py
r605d944 r3f5b901 18 18 from sas.qtgui.Perspectives.Fitting.FittingWidget import * 19 19 from sas.qtgui.Perspectives.Fitting.Constraint import Constraint 20 import sas.qtgui.Utilities.LocalConfig 20 21 21 from sas.qtgui.UnitTesting.TestUtils import QtSignalSpy 22 from sas.qtgui.Perspectives.Fitting.ModelThread import Calc1D23 from sas.qtgui.Perspectives.Fitting.ModelThread import Calc2D24 22 25 23 from sas.qtgui.Plotting.PlotterData import Data1D … … 262 260 self.widget.cbModel.setCurrentIndex(0) 263 261 264 # Observe factor doesn'treset to None265 self.assertEqual(self.widget.cbStructureFactor.currentText(), 'squarewell')262 # Observe factor reset to None 263 self.assertEqual(self.widget.cbStructureFactor.currentText(), STRUCTURE_DEFAULT) 266 264 267 265 # Switch category to structure factor … … 321 319 Check that the fitting 1D data object is ready 322 320 """ 323 324 if LocalConfig.USING_TWISTED: 325 # Mock the thread creation 326 threads.deferToThread = MagicMock() 327 # Model for theory 328 self.widget.SASModelToQModel("cylinder") 329 # Call the tested method 330 self.widget.calculateQGridForModel() 331 time.sleep(1) 332 # Test the mock 333 self.assertTrue(threads.deferToThread.called) 334 self.assertEqual(threads.deferToThread.call_args_list[0][0][0].__name__, "compute") 335 else: 336 Calc2D.queue = MagicMock() 337 # Model for theory 338 self.widget.SASModelToQModel("cylinder") 339 # Call the tested method 340 self.widget.calculateQGridForModel() 341 time.sleep(1) 342 # Test the mock 343 self.assertTrue(Calc2D.queue.called) 321 # Mock the thread creation 322 threads.deferToThread = MagicMock() 323 # Model for theory 324 self.widget.SASModelToQModel("cylinder") 325 # Call the tested method 326 self.widget.calculateQGridForModel() 327 time.sleep(1) 328 # Test the mock 329 self.assertTrue(threads.deferToThread.called) 330 self.assertEqual(threads.deferToThread.call_args_list[0][0][0].__name__, "compute") 344 331 345 332 def testCalculateResiduals(self): … … 430 417 index = self.widget._poly_model.index(0,0) 431 418 419 #self.widget.show() 420 #QtWidgets.QApplication(sys.argv).exec_() 421 422 432 423 # Set the checbox 433 424 self.widget._poly_model.item(0,0).setCheckState(2) 434 425 # Assure the parameter is added 435 self.assertEqual(self.widget.p oly_params_to_fit, ['radius_bell.width'])426 self.assertEqual(self.widget.parameters_to_fit, ['radius_bell.width']) 436 427 437 428 # Add another parameter 438 429 self.widget._poly_model.item(2,0).setCheckState(2) 439 430 # Assure the parameters are added 440 self.assertEqual(self.widget.p oly_params_to_fit, ['radius_bell.width', 'length.width'])431 self.assertEqual(self.widget.parameters_to_fit, ['radius_bell.width', 'length.width']) 441 432 442 433 # Change the min/max values … … 647 638 self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot') 648 639 640 self.widget.show() 641 649 642 # Set data 650 643 test_data = Data1D(x=[1,2], y=[1,2]) 651 item = QtGui.QStandardItem() 652 updateModelItem(item, test_data, "test") 644 653 645 # Force same data into logic 654 self.widget.data = item 646 self.widget.logic.data = test_data 647 self.widget.data_is_loaded = True 655 648 656 649 # Change the category index so we have a model available … … 690 683 691 684 # Test no fitting params 692 self.widget. main_params_to_fit = []685 self.widget.parameters_to_fit = [] 693 686 694 687 logging.error = MagicMock() … … 698 691 self.widget.close() 699 692 700 def testOnEmptyFit2(self):701 693 test_data = Data2D(image=[1.0, 2.0, 3.0], 702 694 err_image=[0.01, 0.02, 0.03], … … 709 701 item = QtGui.QStandardItem() 710 702 updateModelItem(item, test_data, "test") 711 712 703 # Force same data into logic 713 704 self.widget.data = item … … 718 709 719 710 # Test no fitting params 720 self.widget. main_params_to_fit = []711 self.widget.parameters_to_fit = [] 721 712 722 713 logging.error = MagicMock() … … 727 718 self.widget.close() 728 719 729 def notestOnFit1D(self): 720 721 def testOnFit1D(self): 730 722 """ 731 723 Test the threaded fitting call … … 743 735 744 736 # Assing fitting params 745 self.widget. main_params_to_fit = ['scale']737 self.widget.parameters_to_fit = ['scale'] 746 738 747 739 # Spying on status update signal … … 756 748 757 749 # the fit button changed caption and got disabled 758 # could fail if machine fast enough to finish 759 #self.assertEqual(self.widget.cmdFit.text(), 'Stop fit') 760 #self.assertFalse(self.widget.cmdFit.isEnabled()) 750 self.assertEqual(self.widget.cmdFit.text(), 'Stop fit') 751 self.assertFalse(self.widget.cmdFit.isEnabled()) 761 752 762 753 # Signal pushed up … … 765 756 self.widget.close() 766 757 767 def notestOnFit2D(self):758 def testOnFit2D(self): 768 759 """ 769 760 Test the threaded fitting call … … 788 779 789 780 # Assing fitting params 790 self.widget. main_params_to_fit = ['scale']781 self.widget.parameters_to_fit = ['scale'] 791 782 792 783 # Spying on status update signal … … 801 792 802 793 # the fit button changed caption and got disabled 803 #self.assertEqual(self.widget.cmdFit.text(), 'Stop fit')804 #self.assertFalse(self.widget.cmdFit.isEnabled())794 self.assertEqual(self.widget.cmdFit.text(), 'Stop fit') 795 self.assertFalse(self.widget.cmdFit.isEnabled()) 805 796 806 797 # Signal pushed up … … 860 851 # Set data 861 852 test_data = Data1D(x=[1,2], y=[1,2]) 862 item = QtGui.QStandardItem() 863 updateModelItem(item, test_data, "test") 853 864 854 # Force same data into logic 865 self.widget.data = item 866 867 # Force same data into logic 855 self.widget.logic.data = test_data 856 self.widget.data_is_loaded = True 868 857 category_index = self.widget.cbCategory.findText('Sphere') 869 870 self.widget.cbCategory.setCurrentIndex(category_index) 871 self.widget.main_params_to_fit = ['scale'] 858 self.widget.cbCategory.setCurrentIndex(category_index) 859 self.widget.parameters_to_fit = ['scale'] 872 860 # Invoke the tested method 873 861 fp = self.widget.currentState() … … 917 905 918 906 # Test no fitting params 919 self.widget. main_params_to_fit = ['scale']907 self.widget.parameters_to_fit = ['scale'] 920 908 921 909 # Invoke the tested method … … 949 937 # Set data 950 938 test_data = Data1D(x=[1,2], y=[1,2]) 951 item = QtGui.QStandardItem() 952 updateModelItem(item, test_data, "test") 939 953 940 # Force same data into logic 954 self.widget.data = item 941 self.widget.logic.data = test_data 942 self.widget.data_is_loaded = True 955 943 category_index = self.widget.cbCategory.findText("Sphere") 956 944 self.widget.cbCategory.setCurrentIndex(category_index) 957 self.widget. main_params_to_fit = ['scale']945 self.widget.parameters_to_fit = ['scale'] 958 946 959 947 # Invoke the tested method … … 966 954 self.assertEqual(fp.current_category, "Sphere") 967 955 self.assertEqual(fp.current_model, "adsorbed_layer") 968 self.assertListEqual(fp. main_params_to_fit, ['scale'])956 self.assertListEqual(fp.parameters_to_fit, ['scale']) 969 957 970 958 def testPushFitPage(self): … … 974 962 # Set data 975 963 test_data = Data1D(x=[1,2], y=[1,2]) 976 item = QtGui.QStandardItem() 977 updateModelItem(item, test_data, "test") 964 978 965 # Force same data into logic 979 self.widget.data = item 966 self.widget.logic.data = test_data 967 self.widget.data_is_loaded = True 980 968 category_index = self.widget.cbCategory.findText("Sphere") 981 969 … … 986 974 self.widget.undo_supported = True 987 975 self.widget.cbCategory.setCurrentIndex(category_index) 988 self.widget. main_params_to_fit = ['scale']976 self.widget.parameters_to_fit = ['scale'] 989 977 990 978 # Check that the stack is updated -
src/sas/qtgui/Plotting/PlotProperties.py
rfacf4ca r53c771e 24 24 self._color = color if color else 0 25 25 self._legend = legend 26 self._markersize = marker_size if marker_size else 326 self._markersize = marker_size if marker_size else 5 27 27 self.custom_color = False if isinstance(self._color, int) else True 28 28 -
src/sas/qtgui/Plotting/Plottables.py
rfacf4ca rcee5c78 438 438 interactive = True 439 439 custom_color = None 440 markersize = 3 # default marker size is 'size 3'440 markersize = 5 # default marker size is 'size 5' 441 441 442 442 def __init__(self): … … 1046 1046 self.symbol = 0 1047 1047 self.custom_color = None 1048 self.markersize = 31048 self.markersize = 5 1049 1049 self.id = None 1050 1050 self.zorder = 1 -
src/sas/qtgui/Plotting/Plotter.py
rb764ae5 r0231f93 6 6 import copy 7 7 import matplotlib as mpl 8 import numpy as np9 8 from matplotlib.font_manager import FontProperties 10 9 from sas.qtgui.Plotting.PlotterData import Data1D … … 131 130 markersize = self._data.markersize 132 131 133 # Include scaling (log vs. linear)134 ax.set_xscale(self.xscale, nonposx='clip')135 ax.set_yscale(self.yscale, nonposy='clip')136 137 # define the ranges138 self.setRange = SetGraphRange(parent=self,139 x_range=self.ax.get_xlim(), y_range=self.ax.get_ylim())140 141 132 # Draw non-standard markers 142 133 l_width = markersize * 0.4 … … 160 151 linestyle='', label=self._title, picker=True) 161 152 else: 162 dy = self._data.view.dy163 # Convert tuple (lo,hi) to array [(x-lo),(hi-x)]164 if dy is not None and type(dy) == type(()):165 dy = np.vstack((y - dy[0], dy[1] - y)).transpose()166 167 153 line = ax.errorbar(x, y, 168 yerr=dy, 169 xerr=None, 154 yerr=self._data.view.dy, xerr=None, 170 155 capsize=2, linestyle='', 171 156 barsabove=False, … … 176 161 xlolims=False, xuplims=False, 177 162 label=self._title, 178 zorder=1,179 163 picker=True) 164 165 # Now we know what the potential new color is, let's save it 166 if isinstance(line, mpl.lines.Line2D): 167 self.data.custom_color = line.get_color() 180 168 181 169 # Update the list of data sets (plots) in chart … … 195 183 ax.set_xlabel(self.x_label) 196 184 185 # Include scaling (log vs. linear) 186 ax.set_xscale(self.xscale) 187 ax.set_yscale(self.yscale) 188 189 # define the ranges 190 self.setRange = SetGraphRange(parent=self, 191 x_range=self.ax.get_xlim(), y_range=self.ax.get_ylim()) 192 197 193 # refresh canvas 198 194 self.canvas.draw_idle() 199 # This is an important processEvent.200 # This allows charts to be properly updated in order201 # of plots being applied.202 QtWidgets.QApplication.processEvents()203 195 204 196 def createContextMenu(self): -
src/sas/qtgui/Utilities/AddMultEditor.py
r287d356 raed0532 15 15 import re 16 16 import logging 17 import traceback18 19 17 import sas.qtgui.Utilities.GuiUtils as GuiUtils 20 18 from sasmodels.sasview_model import load_standard_models … … 204 202 self.cbOperator.currentText()) 205 203 206 try: 207 success = GuiUtils.checkModel(self.plugin_filename) 208 except Exception as ex: 209 # broad exception from sasmodels 210 msg = "Error building model: "+ str(ex) 211 logging.error(msg) 212 #print three last lines of the stack trace 213 # this will point out the exact line failing 214 last_lines = traceback.format_exc().split('\n')[-4:] 215 traceback_to_show = '\n'.join(last_lines) 216 logging.error(traceback_to_show) 217 218 # Set the status bar message 219 self.parent.communicate.statusBarUpdateSignal.emit("Model check failed") 220 return 204 success = GuiUtils.checkModel(self.plugin_filename) 221 205 222 206 if not success: -
src/sas/qtgui/Utilities/GuiUtils.py
r0eff615 r0eff615 35 35 HELP_DIRECTORY_LOCATION = "docs/sphinx-docs/build/html" 36 36 IMAGES_DIRECTORY_LOCATION = HELP_DIRECTORY_LOCATION + "/_images" 37 38 # This matches the ID of a plot created using FittingLogic._create1DPlot, e.g.39 # "5 [P(Q)] modelname"40 # or41 # "4 modelname".42 # Useful for determining whether the plot in question is for an intermediate result, such as P(Q) or S(Q) in the43 # case of a product model; the identifier for this is held in square brackets, as in the example above.44 theory_plot_ID_pattern = re.compile(r"^([0-9]+)\s+(\[(.*)\]\s+)?(.*)$")45 37 46 38 def get_app_dir(): … … 219 211 # New theory data in current perspective 220 212 updateTheoryFromPerspectiveSignal = QtCore.pyqtSignal(QtGui.QStandardItem) 221 222 # Request to delete plots (in the theory view) related to a given model ID223 deleteIntermediateTheoryPlotsSignal = QtCore.pyqtSignal(str)224 213 225 214 # New plot requested from the GUI manager -
src/sas/qtgui/Utilities/LocalConfig.py
rb764ae5 re4335ae 134 134 135 135 # Default threading model 136 USING_TWISTED = False136 USING_TWISTED = True 137 137 138 138 # Time out for updating sasview -
src/sas/qtgui/Utilities/ReportDialog.py
rcb90b65 rce30949 73 73 # Use a sensible filename default 74 74 default_name = os.path.join(location, 'fit_report.pdf') 75 76 75 kwargs = { 77 76 'parent' : self, 78 77 'caption' : 'Save Report', 79 # don't use 'directory' in order to remember the previous user choice 80 #'directory': default_name, 78 'directory': default_name, 81 79 'filter' : 'PDF file (*.pdf);;HTML file (*.html);;Text file (*.txt)', 82 80 'options' : QtWidgets.QFileDialog.DontUseNativeDialog} … … 101 99 102 100 # Create files with charts 103 pictures = [] 104 if self.data_images is not None: 105 pictures = self.getPictures(basename) 101 pictures = self.getPictures(basename) 106 102 107 103 # self.data_html contains all images at the end of the report, in base64 form; -
src/sas/qtgui/Utilities/UnitTesting/ReportDialogTest.py
rcb90b65 r144fe21 158 158 159 159 self.assertTrue(logging.error.called) 160 #logging.error.assert_called_with("Error creating pdf")160 logging.error.assert_called_with("Error creating pdf: Failed") 161 161
Note: See TracChangeset
for help on using the changeset viewer.