Changes in / [0eff615:6da3e3d] in sasview


Ignore:
Location:
src/sas/qtgui
Files:
22 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/Calculators/SldPanel.py

    raed0532 r5c0e717  
    66 
    77from periodictable import formula as Formula 
    8 from periodictable.xsf import xray_energy, xray_sld_from_atoms 
     8from periodictable.xsf import xray_energy, xray_sld 
    99from periodictable.nsf import neutron_scattering 
    1010 
     
    2121    'MOLECULAR_FORMULA', 
    2222    'MASS_DENSITY', 
    23     'WAVELENGTH', 
     23    'NEUTRON_WAVELENGTH', 
    2424    'NEUTRON_SLD_REAL', 
    2525    'NEUTRON_SLD_IMAG', 
    26     'CU_KA_SLD_REAL', 
    27     'CU_KA_SLD_IMAG', 
    28     'MO_KA_SLD_REAL', 
    29     'MO_KA_SLD_IMAG', 
     26    'XRAY_WAVELENGTH', 
     27    'XRAY_SLD_REAL', 
     28    'XRAY_SLD_IMAG', 
    3029    'NEUTRON_INC_XS', 
    3130    'NEUTRON_ABS_XS', 
     
    3433 
    3534class SldResult(object): 
    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, 
     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, 
    4038        neutron_inc_xs, neutron_abs_xs, neutron_length): 
    4139 
    4240        self.molecular_formula = molecular_formula 
    4341        self.mass_density = mass_density 
    44         self.wavelength = wavelength 
     42        self.neutron_wavelength = neutron_wavelength 
    4543        self.neutron_sld_real = neutron_sld_real 
    4644        self.neutron_sld_imag = neutron_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 
     45        self.xray_wavelength = xray_wavelength 
     46        self.xray_sld_real = xray_sld_real 
     47        self.xray_sld_imag = xray_sld_imag 
    5148        self.neutron_inc_xs = neutron_inc_xs 
    5249        self.neutron_abs_xs = neutron_abs_xs 
    5350        self.neutron_length = neutron_length 
    5451 
    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, 
     52def sldAlgorithm(molecular_formula, mass_density, neutron_wavelength, xray_wavelength): 
     53 
     54    xray_sld_real, xray_sld_imag = xray_sld( 
     55            compound=molecular_formula, 
    6556            density=mass_density, 
    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 = \ 
     57            wavelength=xray_wavelength) 
     58 
     59    (neutron_sld_real, neutron_sld_imag, _), (_, neutron_abs_xs, neutron_inc_xs), neutron_length = \ 
    7260        neutron_scattering( 
    7361            compound=molecular_formula, 
    7462            density=mass_density, 
    75             wavelength=wavelength) 
     63            wavelength=neutron_wavelength) 
    7664 
    7765    SCALE = 1e-6 
    7866 
    7967    # neutron sld 
    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) 
     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 
    9075 
    9176    return SldResult( 
    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, 
     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, 
    9680        neutron_inc_xs, neutron_abs_xs, neutron_length) 
    9781 
     
    11296            MODEL.NEUTRON_SLD_REAL: self.ui.editNeutronSldReal, 
    11397            MODEL.NEUTRON_SLD_IMAG: self.ui.editNeutronSldImag, 
    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, 
     98            MODEL.XRAY_SLD_REAL: self.ui.editXraySldReal, 
     99            MODEL.XRAY_SLD_IMAG: self.ui.editXraySldImag, 
    118100            MODEL.NEUTRON_INC_XS: self.ui.editNeutronIncXs, 
    119101            MODEL.NEUTRON_ABS_XS: self.ui.editNeutronAbsXs, 
     
    131113        rx = QtCore.QRegExp("[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?") 
    132114        self.ui.editMassDensity.setValidator(QtGui.QRegExpValidator(rx, self.ui.editMassDensity)) 
    133         self.ui.editWavelength.setValidator(QtGui.QRegExpValidator(rx, self.ui.editWavelength)) 
     115        self.ui.editNeutronWavelength.setValidator(QtGui.QRegExpValidator(rx, self.ui.editNeutronWavelength)) 
     116        self.ui.editXrayWavelength.setValidator(QtGui.QRegExpValidator(rx, self.ui.editXrayWavelength)) 
    134117 
    135118        # signals 
    136         self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Reset).clicked.connect(self.modelReset) 
    137         self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self.displayHelp) 
     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() 
    138125 
    139126    def setupModel(self): 
    140127        self.model = QtGui.QStandardItemModel(self) 
    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()) 
     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()) 
    144132 
    145133        for key in list(self._getOutputs().keys()): 
     
    147135 
    148136        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) 
    149142 
    150143        self.modelReset() 
     
    154147        self.mapper.setModel(self.model) 
    155148        self.mapper.setOrientation(QtCore.Qt.Vertical) 
    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) 
     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) 
    159153 
    160154        for key, edit in self._getOutputs().items(): 
     
    166160        update = False 
    167161        for index in range(top.row(), bottom.row() + 1): 
    168             if (index == MODEL.MOLECULAR_FORMULA) or (index == MODEL.MASS_DENSITY) or (index == MODEL.WAVELENGTH): 
     162            if (index == MODEL.MOLECULAR_FORMULA) or (index == MODEL.MASS_DENSITY) or (index == MODEL.NEUTRON_WAVELENGTH) or (index == MODEL.XRAY_WAVELENGTH): 
    169163                update = True 
    170164 
    171         # calcualtion 
     165        # calculation 
    172166        if update: 
    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("") 
     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("") 
    203199 
    204200    def modelReset(self): 
    205201        #self.model.beginResetModel() 
    206202        try: 
    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") 
     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() 
    210208        finally: 
    211209            pass 
     
    217215 
    218216 
     217    def closePanel(self): 
     218        """ 
     219        close the window containing this panel 
     220        """ 
     221        self.close() 
     222 
  • src/sas/qtgui/Calculators/UI/SldPanel.ui

    rcd2cc745 r5c0e717  
    77    <x>0</x> 
    88    <y>0</y> 
    9     <width>447</width> 
    10     <height>403</height> 
     9    <width>490</width> 
     10    <height>490</height> 
    1111   </rect> 
    1212  </property> 
     
    2525  </property> 
    2626  <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> 
    2789   <item row="0" column="0"> 
    2890    <widget class="QGroupBox" name="groupBoxInput"> 
     
    58120       <widget class="QLineEdit" name="editMassDensity"/> 
    59121      </item> 
     122      <item row="2" column="2"> 
     123       <widget class="QLabel" name="label_12"> 
     124        <property name="text"> 
     125         <string>à
     126</string> 
     127        </property> 
     128       </widget> 
     129      </item> 
     130      <item row="0" column="0"> 
     131       <widget class="QLabel" name="label_9"> 
     132        <property name="text"> 
     133         <string>Molecular Formula</string> 
     134        </property> 
     135       </widget> 
     136      </item> 
     137      <item row="2" column="0"> 
     138       <widget class="QLabel" name="label_11"> 
     139        <property name="text"> 
     140         <string>Neutron Wavelength</string> 
     141        </property> 
     142       </widget> 
     143      </item> 
    60144      <item row="2" column="1"> 
    61        <widget class="QLineEdit" name="editWavelength"> 
     145       <widget class="QLineEdit" name="editNeutronWavelength"> 
    62146        <property name="styleSheet"> 
    63147         <string notr="true"/> 
     
    68152       </widget> 
    69153      </item> 
    70       <item row="2" column="2"> 
    71        <widget class="QLabel" name="label_12"> 
     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"> 
    72166        <property name="text"> 
    73167         <string>à
    74168</string> 
    75         </property> 
    76        </widget> 
    77       </item> 
    78       <item row="0" column="0"> 
    79        <widget class="QLabel" name="label_9"> 
    80         <property name="text"> 
    81          <string>Molecular Formula</string> 
    82         </property> 
    83        </widget> 
    84       </item> 
    85       <item row="2" column="0"> 
    86        <widget class="QLabel" name="label_11"> 
    87         <property name="text"> 
    88          <string>Wavelength</string> 
    89169        </property> 
    90170       </widget> 
     
    99179     </property> 
    100180     <layout class="QGridLayout" name="gridLayoutOutput"> 
     181      <item row="0" column="1"> 
     182       <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> 
    101191      <item row="0" column="0"> 
    102192       <widget class="QLabel" name="label_17"> 
     
    106196       </widget> 
    107197      </item> 
    108       <item row="0" column="1"> 
    109        <widget class="QLineEdit" name="editNeutronSldReal"> 
    110         <property name="readOnly"> 
    111          <bool>true</bool> 
     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> 
    112219        </property> 
    113220       </widget> 
     
    120227       </widget> 
    121228      </item> 
     229      <item row="1" column="2"> 
     230       <widget class="QLabel" name="label_20"> 
     231        <property name="text"> 
     232         <string>-i</string> 
     233        </property> 
     234       </widget> 
     235      </item> 
    122236      <item row="0" column="3"> 
    123237       <widget class="QLineEdit" name="editNeutronSldImag"> 
    124         <property name="readOnly"> 
    125          <bool>true</bool> 
     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> 
     291        </property> 
     292       </widget> 
     293      </item> 
     294      <item row="1" column="4"> 
     295       <widget class="QLabel" name="label_6"> 
     296        <property name="text"> 
     297         <string>1/à
     298²</string> 
     299        </property> 
     300       </widget> 
     301      </item> 
     302      <item row="1" column="0"> 
     303       <widget class="QLabel" name="label_19"> 
     304        <property name="text"> 
     305         <string>X-Ray SLD</string> 
    126306        </property> 
    127307       </widget> 
     
    135315       </widget> 
    136316      </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> 
    154       <item row="1" column="2"> 
    155        <widget class="QLabel" name="label_20"> 
    156         <property name="text"> 
    157          <string>-i</string> 
    158         </property> 
    159        </widget> 
    160       </item> 
    161       <item row="1" column="3"> 
    162        <widget class="QLineEdit" name="editCuKaSldImag"> 
    163         <property name="readOnly"> 
    164          <bool>true</bool> 
    165         </property> 
    166        </widget> 
    167       </item> 
    168       <item row="1" column="4"> 
    169        <widget class="QLabel" name="label_6"> 
    170         <property name="text"> 
    171          <string>1/à
    172 Â²</string> 
    173         </property> 
    174        </widget> 
    175       </item> 
    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"> 
    206         <property name="text"> 
    207          <string>1/à
    208 Â²</string> 
    209         </property> 
    210        </widget> 
    211       </item> 
    212       <item row="3" column="0" colspan="5"> 
     317      <item row="2" column="0" colspan="5"> 
    213318       <widget class="QFrame" name="frame"> 
    214319        <property name="minimumSize"> 
     
    232337       </widget> 
    233338      </item> 
    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> 
     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> 
    294356        </property> 
    295357       </widget> 
    296358      </item> 
    297359     </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> 
    324360    </widget> 
    325361   </item> 
     
    329365  <tabstop>editMolecularFormula</tabstop> 
    330366  <tabstop>editMassDensity</tabstop> 
    331   <tabstop>editWavelength</tabstop> 
     367  <tabstop>editNeutronWavelength</tabstop> 
    332368  <tabstop>editNeutronSldReal</tabstop> 
    333369  <tabstop>editNeutronSldImag</tabstop> 
    334   <tabstop>editCuKaSldReal</tabstop> 
    335   <tabstop>editCuKaSldImag</tabstop> 
    336   <tabstop>editMoKaSldReal</tabstop> 
    337   <tabstop>editMoKaSldImag</tabstop> 
    338370  <tabstop>editNeutronIncXs</tabstop> 
    339371  <tabstop>editNeutronAbsXs</tabstop> 
    340372  <tabstop>editNeutronLength</tabstop> 
    341   <tabstop>buttonBox</tabstop> 
    342373 </tabstops> 
    343374 <resources/> 
    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> 
     375 <connections/> 
    378376</ui> 
  • src/sas/qtgui/MainWindow/DataExplorer.py

    r9463ca2 rfd7ef36  
    44import time 
    55import logging 
    6 import re 
    76 
    87from PyQt5 import QtCore 
     
    3736    # The controller which is responsible for managing signal slots connections 
    3837    # 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+)?(.*)$") 
    4738 
    4839    def __init__(self, parent=None, guimanager=None, manager=None): 
     
    394385        # Notify the GuiManager about the send request 
    395386        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 = -1 
     393        theories_copied = 0 
     394        orig_model_size = self.model.rowCount() 
     395        while outer_index < orig_model_size: 
     396            outer_index += 1 
     397            outer_item = self.model.item(outer_index) 
     398            if not outer_item: 
     399                continue 
     400            if not outer_item.isCheckable(): 
     401                continue 
     402            # Look for checked inner items 
     403            inner_index = -1 
     404            while inner_index < outer_item.rowCount(): 
     405               inner_item = outer_item.child(inner_index) 
     406               inner_index += 1 
     407               if not inner_item: 
     408                   continue 
     409               if not inner_item.isCheckable(): 
     410                   continue 
     411               if inner_item.checkState() != QtCore.Qt.Checked: 
     412                   continue 
     413               self.model.beginResetModel() 
     414               theories_copied += 1 
     415               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            return 
     422        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_copied 
     426        else: 
     427            freeze_msg = "Unexpected number of theories copied: %i" % theories_copied 
     428            raise AttributeError(freeze_msg) 
     429        self.communicator.statusBarUpdateSignal.emit(freeze_msg) 
    396430 
    397431    def freezeTheory(self, event): 
     
    538572            else: 
    539573                # Don't plot intermediate results, e.g. P(Q), S(Q) 
    540                 match = self.theory_plot_ID_pattern.match(plot_id) 
     574                match = GuiUtils.theory_plot_ID_pattern.match(plot_id) 
    541575                # 2nd match group contains the identifier for the intermediate result, if present (e.g. "[P(Q)]") 
    542576                if match and match.groups()[1] != None: 
     
    544578                # 'sophisticated' test to generate standalone plot for residuals 
    545579                if 'esiduals' in plot.title: 
    546                     self.plotData([(item, plot)], transform=False) 
     580                    plot.yscale='linear' 
     581                    self.plotData([(item, plot)]) 
    547582                else: 
    548583                    new_plots.append((item, plot)) 
     
    825860        return wlist 
    826861 
     862    def setItemsCheckability(self, model, dimension=None, checked=False): 
     863        """ 
     864        For a given model, check or uncheck all items of given dimension 
     865        """ 
     866        mode = QtCore.Qt.Checked if checked else QtCore.Qt.Unchecked 
     867 
     868        assert isinstance(checked, bool) 
     869 
     870        types = (None, Data1D, Data2D) 
     871        assert dimension in types 
     872 
     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                continue 
     877            if item.isCheckable() and item.checkState() != mode: 
     878                item.setCheckState(mode) 
     879            # look for all children 
     880            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 
    827885    def selectData(self, index): 
    828886        """ 
     
    835893        # Respond appropriately 
    836894        if index == 0: 
    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) 
     895            self.setItemsCheckability(self.model, checked=True) 
     896 
    842897        elif index == 1: 
    843898            # De-select All 
    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) 
     899            self.setItemsCheckability(self.model, checked=False) 
    848900 
    849901        elif index == 2: 
    850902            # Select All 1-D 
    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) 
     903            self.setItemsCheckability(self.model, dimension=Data1D, checked=True) 
    863904 
    864905        elif index == 3: 
    865906            # Unselect All 1-D 
    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) 
     907            self.setItemsCheckability(self.model, dimension=Data1D, checked=False) 
    877908 
    878909        elif index == 4: 
    879910            # Select All 2-D 
    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) 
     911            self.setItemsCheckability(self.model, dimension=Data2D, checked=True) 
    891912 
    892913        elif index == 5: 
    893914            # Unselect All 2-D 
    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) 
     915            self.setItemsCheckability(self.model, dimension=Data2D, checked=False) 
    905916 
    906917        else: 
     
    12701281        self.theory_model.appendRow(model_item) 
    12711282 
     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 the 
     1285        case of intermediate results disappearing when changing calculations (in which case you don't want them to be 
     1286        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                return 
     1293            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 plot 
     1298                    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  
    395395        self.communicate.perspectiveChangedSignal.connect(self.perspectiveChanged) 
    396396        self.communicate.updateTheoryFromPerspectiveSignal.connect(self.updateTheoryFromPerspective) 
     397        self.communicate.deleteIntermediateTheoryPlotsSignal.connect(self.deleteIntermediateTheoryPlotsByModelID) 
    397398        self.communicate.plotRequestedSignal.connect(self.showPlot) 
    398399        self.communicate.plotFromFilenameSignal.connect(self.showPlotFromFilename) 
     
    438439        self._workspace.actionImage_Viewer.triggered.connect(self.actionImage_Viewer) 
    439440        self._workspace.actionOrientation_Viewer.triggered.connect(self.actionOrientation_Viewer) 
     441        self._workspace.actionFreeze_Theory.triggered.connect(self.actionFreeze_Theory) 
    440442        # Fitting 
    441443        self._workspace.actionNew_Fit_Page.triggered.connect(self.actionNew_Fit_Page) 
     
    684686        self._workspace.addDockWidget(Qt.RightDockWidgetArea, self.ipDockWidget) 
    685687 
     688    def actionFreeze_Theory(self): 
     689        """ 
     690        Convert a child index with data into a separate top level dataset 
     691        """ 
     692        self.filesWidget.freezeCheckedData() 
     693 
    686694    def actionOrientation_Viewer(self): 
    687695        """ 
     
    879887        """ 
    880888        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) 
    881896 
    882897    def updateModelFromDataOperationPanel(self, new_item, new_datalist_item): 
  • src/sas/qtgui/MainWindow/UI/DataExplorerUI.ui

    rd1fa2b8 rf4a6f2c  
    4444           <property name="sizePolicy"> 
    4545            <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> 
    46              <horstretch>5</horstretch> 
     46             <horstretch>0</horstretch> 
    4747             <verstretch>5</verstretch> 
    4848            </sizepolicy> 
     
    5050           <property name="minimumSize"> 
    5151            <size> 
    52              <width>154</width> 
    53              <height>50</height> 
     52             <width>120</width> 
     53             <height>40</height> 
    5454            </size> 
    5555           </property> 
     
    6464           </property> 
    6565           <property name="styleSheet"> 
    66             <string notr="true">font: 13pt &quot;MS Shell Dlg 2&quot;;</string> 
     66            <string notr="true">font: 11pt &quot;MS Shell Dlg 2&quot;;</string> 
    6767           </property> 
    6868           <property name="text"> 
     
    7575           <property name="iconSize"> 
    7676            <size> 
    77              <width>48</width> 
    78              <height>48</height> 
     77             <width>32</width> 
     78             <height>32</height> 
    7979            </size> 
    8080           </property> 
     
    183183           <property name="sizePolicy"> 
    184184            <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> 
    185              <horstretch>5</horstretch> 
     185             <horstretch>0</horstretch> 
    186186             <verstretch>5</verstretch> 
    187187            </sizepolicy> 
     
    189189           <property name="minimumSize"> 
    190190            <size> 
    191              <width>170</width> 
    192              <height>50</height> 
     191             <width>145</width> 
     192             <height>40</height> 
    193193            </size> 
    194194           </property> 
     
    201201           <property name="font"> 
    202202            <font> 
    203              <pointsize>13</pointsize> 
     203             <family>MS Shell Dlg 2</family> 
     204             <pointsize>11</pointsize> 
     205             <weight>50</weight> 
     206             <italic>false</italic> 
     207             <bold>false</bold> 
    204208            </font> 
    205209           </property> 
     
    208212           </property> 
    209213           <property name="styleSheet"> 
    210             <string notr="true">font: 13pt &quot;MS Shell Dlg 2&quot;;</string> 
     214            <string notr="true">font: 11pt &quot;MS Shell Dlg 2&quot;;</string> 
    211215           </property> 
    212216           <property name="text"> 
     
    219223           <property name="iconSize"> 
    220224            <size> 
    221              <width>48</width> 
    222              <height>48</height> 
     225             <width>32</width> 
     226             <height>32</height> 
    223227            </size> 
    224228           </property> 
     
    235239           <property name="font"> 
    236240            <font> 
    237              <pointsize>12</pointsize> 
     241             <pointsize>11</pointsize> 
    238242            </font> 
    239243           </property> 
  • src/sas/qtgui/MainWindow/UI/MainWindowUI.ui

    raa1db44 r6b50296  
    6464    <addaction name="actionReport"/> 
    6565    <addaction name="actionReset"/> 
     66    <addaction name="separator"/> 
     67    <addaction name="actionFreeze_Theory"/> 
    6668   </widget> 
    6769   <widget class="QMenu" name="menuView"> 
     
    535537   </property> 
    536538  </action> 
     539  <action name="actionFreeze_Theory"> 
     540   <property name="text"> 
     541    <string>Freeze Theory</string> 
     542   </property> 
     543  </action> 
    537544 </widget> 
    538545 <resources/> 
  • src/sas/qtgui/MainWindow/UnitTesting/DataExplorerTest.py

    r573c383 ra24eacf  
    7171        self.assertEqual(self.form.cmdFreeze.text(), "Freeze Theory") 
    7272        self.assertEqual(self.form.cmdSendTo.text(), "Send data to") 
    73         self.assertEqual(self.form.cmdSendTo.iconSize(), QSize(48, 48)) 
     73        self.assertEqual(self.form.cmdSendTo.iconSize(), QSize(32, 32)) 
    7474        self.assertIsInstance(self.form.cmdSendTo.icon(), QIcon) 
    7575        self.assertEqual(self.form.chkBatch.text(), "Batch mode") 
     
    352352        # Test the current selection 
    353353        self.assertTrue(item1D.checkState() == Qt.Checked) 
    354         self.assertTrue(item2D.checkState() == Qt.Unchecked)         
     354        self.assertTrue(item2D.checkState() == Qt.Checked) 
    355355 
    356356        # unselect 1d data 
     
    359359        # Test the current selection 
    360360        self.assertTrue(item1D.checkState() == Qt.Unchecked) 
    361         self.assertTrue(item2D.checkState() == Qt.Unchecked)         
     361        self.assertTrue(item2D.checkState() == Qt.Checked) 
    362362 
    363363        # select 2d data 
  • src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py

    rff3b293 rb764ae5  
    430430 
    431431    theory_name = str(current_data.name.split()[0]) 
    432     residuals.name = "Residuals for " + str(theory_name) + "[" + \ 
    433                     str(reference_data.filename) + "]" 
     432    res_name = reference_data.filename if reference_data.filename else reference_data.name 
     433    residuals.name = "Residuals for " + str(theory_name) + "[" + res_name + "]" 
    434434    residuals.title = residuals.name 
    435435    residuals.ytransform = 'y' 
     
    457457    """ 
    458458    weight = None 
     459    if data is None: 
     460        return [] 
    459461    if is2d: 
     462        if not hasattr(data, 'err_data'): 
     463            return [] 
    460464        dy_data = data.err_data 
    461465        data = data.data 
    462466    else: 
     467        if not hasattr(data, 'dy'): 
     468            return [] 
    463469        dy_data = data.dy 
    464470        data = data.y 
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    r0eff615 r0eff615  
    6060 
    6161logger = logging.getLogger(__name__) 
    62  
    6362 
    6463class ToolTippedItemModel(QtGui.QStandardItemModel): 
     
    225224        self.models = {} 
    226225        # Parameters to fit 
    227         self.parameters_to_fit = None 
     226        self.main_params_to_fit = [] 
     227        self.poly_params_to_fit = [] 
     228        self.magnet_params_to_fit = [] 
     229 
    228230        # Fit options 
    229231        self.q_range_min = 0.005 
     
    263265        self.has_magnet_error_column = False 
    264266 
     267        # If the widget generated theory item, save it 
     268        self.theory_item = None 
     269 
    265270        # signal communicator 
    266271        self.communicate = self.parent.communicate 
     
    385390        # Tag along functionality 
    386391        self.label.setText("Data loaded from: ") 
    387         self.lblFilename.setText(self.logic.data.filename) 
     392        if self.logic.data.filename: 
     393            self.lblFilename.setText(self.logic.data.filename) 
     394        else: 
     395            self.lblFilename.setText(self.logic.data.name) 
    388396        self.updateQRange() 
    389397        # Switch off Data2D control 
     
    517525 
    518526        # Signals from separate tabs asking for replot 
    519         self.options_widget.plot_signal.connect(self.onOptionsUpdate) 
    520527        self.options_widget.plot_signal.connect(self.onOptionsUpdate) 
    521528 
     
    948955        model = self.cbModel.currentText() 
    949956 
    950         # empty combobox forced to be read 
     957        # Assure the control is active 
     958        if not self.cbModel.isEnabled(): 
     959            return 
     960        # Empty combobox forced to be read 
    951961        if not model: 
    952962            return 
    953         # Reset structure factor 
    954         self.cbStructureFactor.setCurrentIndex(0) 
    955963 
    956964        # Reset parameters to fit 
    957         self.parameters_to_fit = None 
     965        self.resetParametersToFit() 
    958966        self.has_error_column = False 
    959967        self.has_poly_error_column = False 
    960968 
    961         self.respondToModelStructure(model=model, structure_factor=None) 
     969        structure = None 
     970        if self.cbStructureFactor.isEnabled(): 
     971            structure = str(self.cbStructureFactor.currentText()) 
     972        self.respondToModelStructure(model=model, structure_factor=structure) 
    962973 
    963974    def onSelectBatchFilename(self, data_index): 
     
    979990 
    980991        # Reset parameters to fit 
    981         self.parameters_to_fit = None 
     992        self.resetParametersToFit() 
    982993        self.has_error_column = False 
    983994        self.has_poly_error_column = False 
    984995 
    985996        self.respondToModelStructure(model=model, structure_factor=structure) 
     997 
     998    def resetParametersToFit(self): 
     999        """ 
     1000        Clears the list of parameters to be fitted 
     1001        """ 
     1002        self.main_params_to_fit = [] 
     1003        self.poly_params_to_fit = [] 
     1004        self.magnet_params_to_fit = [] 
    9861005 
    9871006    def onCustomModelChange(self): 
     
    10941113            self.disableModelCombo() 
    10951114            self.enableStructureCombo() 
     1115            # set the index to 0 
     1116            self.cbStructureFactor.setCurrentIndex(0) 
     1117            self.model_parameters = None 
    10961118            self._model_model.clear() 
    10971119            return 
     
    11181140        model_row = item.row() 
    11191141        name_index = self._poly_model.index(model_row, 0) 
    1120         parameter_name = str(name_index.data()).lower() # "distribution of sld" etc. 
    1121         if "distribution of" in parameter_name: 
     1142        parameter_name = str(name_index.data()) # "distribution of sld" etc. 
     1143        if "istribution of" in parameter_name: 
    11221144            # just the last word 
    11231145            parameter_name = parameter_name.rsplit()[-1] 
     
    11311153            parameter_name = parameter_name + '.width' 
    11321154            if value == QtCore.Qt.Checked: 
    1133                 self.parameters_to_fit.append(parameter_name) 
     1155                self.poly_params_to_fit.append(parameter_name) 
    11341156            else: 
    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) 
     1157                if parameter_name in self.poly_params_to_fit: 
     1158                    self.poly_params_to_fit.remove(parameter_name) 
     1159            self.cmdFit.setEnabled(self.haveParamsToFit()) 
    11381160 
    11391161        elif model_column in [delegate.poly_min, delegate.poly_max]: 
     
    11871209            value = item.checkState() 
    11881210            if value == QtCore.Qt.Checked: 
    1189                 self.parameters_to_fit.append(parameter_name) 
     1211                self.magnet_params_to_fit.append(parameter_name) 
    11901212            else: 
    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) 
     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()) 
    11941216            # Update state stack 
    11951217            self.updateUndo() 
     
    14761498        qmin = self.q_range_min 
    14771499        qmax = self.q_range_max 
    1478         params_to_fit = self.parameters_to_fit 
     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 
    14791506        if not params_to_fit: 
    14801507            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) 
    14861508 
    14871509        # Get the constraints. 
     
    15011523            data = GuiUtils.dataFromItem(fit_index) 
    15021524            # Potential weights added directly to data 
    1503             self.addWeightingToData(data) 
     1525            weighted_data = self.addWeightingToData(data) 
    15041526            try: 
    1505                 fitter_single.set_model(model, fit_id, params_to_fit, data=data, 
     1527                fitter_single.set_model(model, fit_id, params_to_fit, data=weighted_data, 
    15061528                             constraints=constraints) 
    15071529            except ValueError as ex: 
    15081530                raise ValueError("Setting model parameters failed with: %s" % ex) 
    15091531 
    1510             qmin, qmax, _ = self.logic.computeRangeFromData(data) 
    1511             fitter_single.set_data(data=data, id=fit_id, smearer=smearer, qmin=qmin, 
     1532            qmin, qmax, _ = self.logic.computeRangeFromData(weighted_data) 
     1533            fitter_single.set_data(data=weighted_data, id=fit_id, smearer=smearer, qmin=qmin, 
    15121534                            qmax=qmax) 
    15131535            fitter_single.select_problem_for_fit(id=fit_id, value=1) 
     
    19001922        Adds weighting contribution to fitting data 
    19011923        """ 
     1924        new_data = copy.deepcopy(data) 
    19021925        # Send original data for weighting 
    19031926        weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 
    19041927        if self.is2D: 
    1905             data.err_data = weight 
     1928            new_data.err_data = weight 
    19061929        else: 
    1907             data.dy = weight 
    1908         pass 
     1930            new_data.dy = weight 
     1931 
     1932        return new_data 
    19091933 
    19101934    def updateQRange(self): 
     
    19401964            # Allow the SF combobox visibility for the given sasmodel 
    19411965            self.enableStructureFactorControl(structure_factor) 
     1966            if self.cbStructureFactor.isEnabled(): 
     1967                structure_factor = self.cbStructureFactor.currentText() 
     1968                self.fromStructureFactorToQModel(structure_factor) 
    19421969 
    19431970        # Then, add multishells 
     
    19742001        """ 
    19752002        name = model_name 
     2003        kernel_module = None 
    19762004        if self.cbCategory.currentText() == CATEGORY_CUSTOM: 
    19772005            # custom kernel load requires full path 
     
    19792007        try: 
    19802008            kernel_module = generate.load_kernel_module(name) 
    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) 
     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 
    19862021 
    19872022        if hasattr(kernel_module, 'parameters'): 
     
    20262061        Setting model parameters into QStandardItemModel based on selected _structure factor_ 
    20272062        """ 
     2063        if structure_factor is None or structure_factor=="None": 
     2064            return 
    20282065        structure_module = generate.load_kernel_module(structure_factor) 
    20292066        structure_parameters = modelinfo.make_parameter_table(getattr(structure_module, 'parameters', [])) 
     
    20452082        self._last_model_row = self._model_model.rowCount() 
    20462083 
     2084    def haveParamsToFit(self): 
     2085        """ 
     2086        Finds out if there are any parameters ready to be fitted 
     2087        """ 
     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_loaded 
     2092 
    20472093    def onMainParamsChange(self, item): 
    20482094        """ 
     
    20532099        if model_column == 0: 
    20542100            self.checkboxSelected(item) 
    2055             self.cmdFit.setEnabled(self.parameters_to_fit != [] and self.logic.data_is_loaded) 
     2101            self.cmdFit.setEnabled(self.haveParamsToFit()) 
    20562102            # Update state stack 
    20572103            self.updateUndo() 
     
    21122158        # Convert to proper indices and set requested enablement 
    21132159        self.setParameterSelection(status) 
    2114         #[self._model_model.item(row, 0).setCheckState(status) for row in self.selectedParameters()] 
    21152160        self._model_model.blockSignals(False) 
    21162161 
    21172162        # update the list of parameters to fit 
    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 
     2163        self.main_params_to_fit = self.checkedListFromModel(self._model_model) 
    21262164 
    21272165    def checkedListFromModel(self, model): 
     
    21752213        name = self.nameFromData(fitted_data) 
    21762214        # Notify the GUI manager so it can create the theory model in DataExplorer 
    2177         new_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name) 
    2178         self.communicate.updateTheoryFromPerspectiveSignal.emit(new_item) 
     2215        self.theory_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name) 
     2216        self.communicate.updateTheoryFromPerspectiveSignal.emit(self.theory_item) 
    21792217 
    21802218    def nameFromData(self, fitted_data): 
     
    22102248            completefn = self.methodCompleteForData() 
    22112249        smearer = self.smearing_widget.smearer() 
     2250        weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 
     2251 
    22122252        # Awful API to a backend method. 
    22132253        calc_thread = self.methodCalculateForData()(data=data, 
     
    22182258                                               smearer=smearer, 
    22192259                                               state=None, 
    2220                                                weight=None, 
     2260                                               weight=weight, 
    22212261                                               fid=None, 
    22222262                                               toggle_mode_on=False, 
     
    22662306        residuals = self.calculateResiduals(fitted_data) 
    22672307        self.model_data = fitted_data 
    2268  
    2269         new_plots = [fitted_data, residuals] 
     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) 
    22702317 
    22712318        # Create plots for intermediate product data 
     
    22822329            new_plots.append(sq_data) 
    22832330 
    2284         if self.data_is_loaded: 
    2285             GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_plots) 
    2286  
     2331        # Update/generate plots 
    22872332        for plot in new_plots: 
    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]) 
     2333            self.communicate.plotUpdateSignal.emit([plot]) 
    22932334 
    22942335    def complete2D(self, return_data): 
     
    23082349 
    23092350        # Modify fitted_data with weighting 
    2310         self.addWeightingToData(fitted_data) 
    2311  
    2312         self.createNewIndex(fitted_data) 
     2351        weighted_data = self.addWeightingToData(fitted_data) 
     2352 
     2353        self.createNewIndex(weighted_data) 
    23132354        # Calculate difference between return_data and logic.data 
    2314         self.chi2 = FittingUtilities.calculateChi2(fitted_data, self.logic.data) 
     2355        self.chi2 = FittingUtilities.calculateChi2(weighted_data, self.logic.data) 
    23152356        # Update the control 
    23162357        chi2_repr = "---" if self.chi2 is None else GuiUtils.formatNumber(self.chi2, high=True) 
    23172358        self.lblChi2Value.setText(chi2_repr) 
    23182359 
    2319         # self.communicate.plotUpdateSignal.emit([fitted_data]) 
    2320  
    23212360        # Plot residuals if actual data 
    23222361        if not self.data_is_loaded: 
    23232362            return 
    23242363 
    2325         residuals_plot = FittingUtilities.plotResiduals(self.data, fitted_data) 
     2364        residuals_plot = FittingUtilities.plotResiduals(self.data, weighted_data) 
    23262365        residuals_plot.id = "Residual " + residuals_plot.id 
    23272366        self.createNewIndex(residuals_plot) 
     
    23922431        self._poly_model.clear() 
    23932432 
     2433        parameters = self.model_parameters.form_volume_parameters 
     2434        if self.is2D: 
     2435            parameters += self.model_parameters.orientation_parameters 
     2436 
    23942437        [self.setPolyModelParameters(i, param) for i, param in \ 
    2395             enumerate(self.model_parameters.form_volume_parameters) if param.polydisperse] 
     2438            enumerate(parameters) if param.polydisperse] 
     2439 
    23962440        FittingUtilities.addPolyHeadersToModel(self._poly_model) 
    23972441 
     
    27512795 
    27522796        fp.chi2 = self.chi2 
    2753         fp.parameters_to_fit = self.parameters_to_fit 
     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 
    27542800        fp.kernel_module = self.kernel_module 
    27552801 
     
    28112857        if self.all_data: 
    28122858            index = self.all_data[self.data_index] 
     2859        else: 
     2860            index = self.theory_item 
    28132861        report_logic = ReportPageLogic(self, 
    28142862                                       kernel_module=self.kernel_module, 
  • src/sas/qtgui/Perspectives/Fitting/ModelThread.py

    r3ae9179 r2df558e  
    117117                    self.source) 
    118118        else: 
    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, 
     119            self.completefn((output, 
     120                           self.data, 
     121                           self.page_id, 
     122                           self.model, 
     123                           self.state, 
     124                           self.toggle_mode_on, 
     125                           elapsed, 
     126                           index_model, 
     127                           self.fid, 
     128                           self.qmin, 
     129                           self.qmax, 
     130                           self.weight, 
    131131                           #qstep=self.qstep, 
    132                            update_chisqr=self.update_chisqr, 
    133                            source=self.source) 
     132                           self.update_chisqr, 
     133                           self.source)) 
    134134 
    135135 
     
    250250                    pq_values, sq_values) 
    251251        else: 
    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) 
     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)) 
    267264 
    268265    def results(self): 
  • src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py

    re20870bc rb764ae5  
    7979        self.weightingGroup.buttonClicked.connect(self.onWeightingChoice) 
    8080 
     81        self.qmin = QMIN_DEFAULT 
     82        self.qmax = QMAX_DEFAULT 
     83        self.npts = NPTS_DEFAULT 
     84        if self.logic.data_is_loaded: 
     85            self.qmin, self.qmax, self.npts = self.logic.computeDataRange() 
    8186        self.initModel() 
    8287        self.initMapper() 
    8388        self.model.blockSignals(True) 
    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)) 
     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)) 
    8994        self.model.blockSignals(False) 
    9095 
     
    127132        Callback for running the mask editor 
    128133        """ 
    129         self.parent.communicate.maskEditorSignal.emit(self.logic.data) 
    130         pass 
     134        if isinstance(self.logic.data, Data2D): 
     135            self.parent.communicate.maskEditorSignal.emit(self.logic.data) 
    131136 
    132137    def onRangeReset(self): 
     
    134139        Callback for resetting qmin/qmax 
    135140        """ 
    136         self.updateQRange(QMIN_DEFAULT, QMAX_DEFAULT, NPTS_DEFAULT) 
     141        self.updateQRange(self.qmin, self.qmax, self.npts) 
    137142 
    138143    def onWeightingChoice(self, button): 
     
    157162        Enable/disable various UI elements based on data loaded 
    158163        """ 
     164        is2Ddata = isinstance(self.logic.data, Data2D) 
    159165        self.boxWeighting.setEnabled(True) 
    160         self.cmdMaskEdit.setEnabled(True) 
     166        self.cmdMaskEdit.setEnabled(is2Ddata) 
    161167        # Switch off txtNpts related controls 
    162168        self.txtNpts.setEnabled(False) 
     
    178184        self.model.item(MODEL.index('MAX_RANGE')).setText(str(q_range_max)) 
    179185        self.model.item(MODEL.index('NPTS')).setText(str(npts)) 
     186        self.qmin, self.qmax, self.npts = q_range_min, q_range_max, npts 
    180187 
    181188    def state(self): 
  • src/sas/qtgui/Perspectives/Fitting/UI/FittingWidgetUI.ui

    rc1cfa80 rd686ff1  
    77    <x>0</x> 
    88    <y>0</y> 
    9     <width>680</width> 
    10     <height>605</height> 
     9    <width>566</width> 
     10    <height>646</height> 
    1111   </rect> 
    1212  </property> 
     
    1919  <property name="minimumSize"> 
    2020   <size> 
    21     <width>434</width> 
    22     <height>466</height> 
     21    <width>445</width> 
     22    <height>540</height> 
    2323   </size> 
    2424  </property> 
  • src/sas/qtgui/Perspectives/Fitting/UI/OptionsWidgetUI.ui

    rc1e380e r79bd268  
    88    <y>0</y> 
    99    <width>522</width> 
    10     <height>667</height> 
     10    <height>455</height> 
    1111   </rect> 
    1212  </property> 
  • src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py

    r3f5b901 r605d944  
    1818from sas.qtgui.Perspectives.Fitting.FittingWidget import * 
    1919from sas.qtgui.Perspectives.Fitting.Constraint import Constraint 
    20  
     20import sas.qtgui.Utilities.LocalConfig 
    2121from sas.qtgui.UnitTesting.TestUtils import QtSignalSpy 
     22from sas.qtgui.Perspectives.Fitting.ModelThread import Calc1D 
     23from sas.qtgui.Perspectives.Fitting.ModelThread import Calc2D 
    2224 
    2325from sas.qtgui.Plotting.PlotterData import Data1D 
     
    260262        self.widget.cbModel.setCurrentIndex(0) 
    261263 
    262         # Observe factor reset to None 
    263         self.assertEqual(self.widget.cbStructureFactor.currentText(), STRUCTURE_DEFAULT) 
     264        # Observe factor doesn't reset to None 
     265        self.assertEqual(self.widget.cbStructureFactor.currentText(), 'squarewell') 
    264266 
    265267        # Switch category to structure factor 
     
    319321        Check that the fitting 1D data object is ready 
    320322        """ 
    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") 
     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) 
    331344 
    332345    def testCalculateResiduals(self): 
     
    417430        index = self.widget._poly_model.index(0,0) 
    418431 
    419         #self.widget.show() 
    420         #QtWidgets.QApplication(sys.argv).exec_() 
    421  
    422  
    423432        # Set the checbox 
    424433        self.widget._poly_model.item(0,0).setCheckState(2) 
    425434        # Assure the parameter is added 
    426         self.assertEqual(self.widget.parameters_to_fit, ['radius_bell.width']) 
     435        self.assertEqual(self.widget.poly_params_to_fit, ['radius_bell.width']) 
    427436 
    428437        # Add another parameter 
    429438        self.widget._poly_model.item(2,0).setCheckState(2) 
    430439        # Assure the parameters are added 
    431         self.assertEqual(self.widget.parameters_to_fit, ['radius_bell.width', 'length.width']) 
     440        self.assertEqual(self.widget.poly_params_to_fit, ['radius_bell.width', 'length.width']) 
    432441 
    433442        # Change the min/max values 
     
    638647        self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot') 
    639648 
    640         self.widget.show() 
    641  
    642649        # Set data 
    643650        test_data = Data1D(x=[1,2], y=[1,2]) 
    644  
     651        item = QtGui.QStandardItem() 
     652        updateModelItem(item, test_data, "test") 
    645653        # Force same data into logic 
    646         self.widget.logic.data = test_data 
    647         self.widget.data_is_loaded = True 
     654        self.widget.data = item 
    648655 
    649656        # Change the category index so we have a model available 
     
    683690 
    684691        # Test no fitting params 
    685         self.widget.parameters_to_fit = [] 
     692        self.widget.main_params_to_fit = [] 
    686693 
    687694        logging.error = MagicMock() 
     
    691698        self.widget.close() 
    692699 
     700    def testOnEmptyFit2(self): 
    693701        test_data = Data2D(image=[1.0, 2.0, 3.0], 
    694702                           err_image=[0.01, 0.02, 0.03], 
     
    701709        item = QtGui.QStandardItem() 
    702710        updateModelItem(item, test_data, "test") 
     711 
    703712        # Force same data into logic 
    704713        self.widget.data = item 
     
    709718 
    710719        # Test no fitting params 
    711         self.widget.parameters_to_fit = [] 
     720        self.widget.main_params_to_fit = [] 
    712721 
    713722        logging.error = MagicMock() 
     
    718727        self.widget.close() 
    719728 
    720  
    721     def testOnFit1D(self): 
     729    def notestOnFit1D(self): 
    722730        """ 
    723731        Test the threaded fitting call 
     
    735743 
    736744        # Assing fitting params 
    737         self.widget.parameters_to_fit = ['scale'] 
     745        self.widget.main_params_to_fit = ['scale'] 
    738746 
    739747        # Spying on status update signal 
     
    748756 
    749757            # the fit button changed caption and got disabled 
    750             self.assertEqual(self.widget.cmdFit.text(), 'Stop fit') 
    751             self.assertFalse(self.widget.cmdFit.isEnabled()) 
     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()) 
    752761 
    753762            # Signal pushed up 
     
    756765        self.widget.close() 
    757766 
    758     def testOnFit2D(self): 
     767    def notestOnFit2D(self): 
    759768        """ 
    760769        Test the threaded fitting call 
     
    779788 
    780789        # Assing fitting params 
    781         self.widget.parameters_to_fit = ['scale'] 
     790        self.widget.main_params_to_fit = ['scale'] 
    782791 
    783792        # Spying on status update signal 
     
    792801 
    793802            # the fit button changed caption and got disabled 
    794             self.assertEqual(self.widget.cmdFit.text(), 'Stop fit') 
    795             self.assertFalse(self.widget.cmdFit.isEnabled()) 
     803            #self.assertEqual(self.widget.cmdFit.text(), 'Stop fit') 
     804            #self.assertFalse(self.widget.cmdFit.isEnabled()) 
    796805 
    797806            # Signal pushed up 
     
    851860        # Set data 
    852861        test_data = Data1D(x=[1,2], y=[1,2]) 
    853  
     862        item = QtGui.QStandardItem() 
     863        updateModelItem(item, test_data, "test") 
    854864        # Force same data into logic 
    855         self.widget.logic.data = test_data 
    856         self.widget.data_is_loaded = True 
     865        self.widget.data = item 
     866 
     867        # Force same data into logic 
    857868        category_index = self.widget.cbCategory.findText('Sphere') 
    858         self.widget.cbCategory.setCurrentIndex(category_index) 
    859         self.widget.parameters_to_fit = ['scale'] 
     869 
     870        self.widget.cbCategory.setCurrentIndex(category_index) 
     871        self.widget.main_params_to_fit = ['scale'] 
    860872        # Invoke the tested method 
    861873        fp = self.widget.currentState() 
     
    905917 
    906918        # Test no fitting params 
    907         self.widget.parameters_to_fit = ['scale'] 
     919        self.widget.main_params_to_fit = ['scale'] 
    908920 
    909921        # Invoke the tested method 
     
    937949        # Set data 
    938950        test_data = Data1D(x=[1,2], y=[1,2]) 
    939  
     951        item = QtGui.QStandardItem() 
     952        updateModelItem(item, test_data, "test") 
    940953        # Force same data into logic 
    941         self.widget.logic.data = test_data 
    942         self.widget.data_is_loaded = True 
     954        self.widget.data = item 
    943955        category_index = self.widget.cbCategory.findText("Sphere") 
    944956        self.widget.cbCategory.setCurrentIndex(category_index) 
    945         self.widget.parameters_to_fit = ['scale'] 
     957        self.widget.main_params_to_fit = ['scale'] 
    946958 
    947959        # Invoke the tested method 
     
    954966        self.assertEqual(fp.current_category, "Sphere") 
    955967        self.assertEqual(fp.current_model, "adsorbed_layer") 
    956         self.assertListEqual(fp.parameters_to_fit, ['scale']) 
     968        self.assertListEqual(fp.main_params_to_fit, ['scale']) 
    957969 
    958970    def testPushFitPage(self): 
     
    962974        # Set data 
    963975        test_data = Data1D(x=[1,2], y=[1,2]) 
    964  
     976        item = QtGui.QStandardItem() 
     977        updateModelItem(item, test_data, "test") 
    965978        # Force same data into logic 
    966         self.widget.logic.data = test_data 
    967         self.widget.data_is_loaded = True 
     979        self.widget.data = item 
    968980        category_index = self.widget.cbCategory.findText("Sphere") 
    969981 
     
    974986        self.widget.undo_supported = True 
    975987        self.widget.cbCategory.setCurrentIndex(category_index) 
    976         self.widget.parameters_to_fit = ['scale'] 
     988        self.widget.main_params_to_fit = ['scale'] 
    977989 
    978990        # Check that the stack is updated 
  • src/sas/qtgui/Plotting/PlotProperties.py

    r53c771e rfacf4ca  
    2424        self._color = color if color else 0 
    2525        self._legend = legend 
    26         self._markersize = marker_size if marker_size else 5 
     26        self._markersize = marker_size if marker_size else 3 
    2727        self.custom_color = False if isinstance(self._color, int) else True 
    2828 
  • src/sas/qtgui/Plotting/Plottables.py

    rcee5c78 rfacf4ca  
    438438    interactive = True 
    439439    custom_color = None 
    440     markersize = 5  # default marker size is 'size 5' 
     440    markersize = 3  # default marker size is 'size 3' 
    441441 
    442442    def __init__(self): 
     
    10461046        self.symbol = 0 
    10471047        self.custom_color = None 
    1048         self.markersize = 5 
     1048        self.markersize = 3 
    10491049        self.id = None 
    10501050        self.zorder = 1 
  • src/sas/qtgui/Plotting/Plotter.py

    r0231f93 rb764ae5  
    66import copy 
    77import matplotlib as mpl 
     8import numpy as np 
    89from matplotlib.font_manager import FontProperties 
    910from sas.qtgui.Plotting.PlotterData import Data1D 
     
    130131        markersize = self._data.markersize 
    131132 
     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 ranges 
     138        self.setRange = SetGraphRange(parent=self, 
     139            x_range=self.ax.get_xlim(), y_range=self.ax.get_ylim()) 
     140 
    132141        # Draw non-standard markers 
    133142        l_width = markersize * 0.4 
     
    151160                        linestyle='', label=self._title, picker=True) 
    152161            else: 
     162                dy = self._data.view.dy 
     163                # 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 
    153167                line = ax.errorbar(x, y, 
    154                             yerr=self._data.view.dy, xerr=None, 
     168                            yerr=dy, 
     169                            xerr=None, 
    155170                            capsize=2, linestyle='', 
    156171                            barsabove=False, 
     
    161176                            xlolims=False, xuplims=False, 
    162177                            label=self._title, 
     178                            zorder=1, 
    163179                            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() 
    168180 
    169181        # Update the list of data sets (plots) in chart 
     
    183195            ax.set_xlabel(self.x_label) 
    184196 
    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  
    193197        # refresh canvas 
    194198        self.canvas.draw_idle() 
     199        # This is an important processEvent. 
     200        # This allows charts to be properly updated in order 
     201        # of plots being applied. 
     202        QtWidgets.QApplication.processEvents() 
    195203 
    196204    def createContextMenu(self): 
  • src/sas/qtgui/Utilities/AddMultEditor.py

    raed0532 r287d356  
    1515import re 
    1616import logging 
     17import traceback 
     18 
    1719import sas.qtgui.Utilities.GuiUtils as GuiUtils 
    1820from sasmodels.sasview_model import load_standard_models 
     
    202204                                     self.cbOperator.currentText()) 
    203205 
    204         success = GuiUtils.checkModel(self.plugin_filename) 
     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 
    205221 
    206222        if not success: 
  • src/sas/qtgui/Utilities/GuiUtils.py

    r0eff615 r0eff615  
    3535        HELP_DIRECTORY_LOCATION = "docs/sphinx-docs/build/html" 
    3636IMAGES_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# or 
     41# "4 modelname". 
     42# Useful for determining whether the plot in question is for an intermediate result, such as P(Q) or S(Q) in the 
     43# case of a product model; the identifier for this is held in square brackets, as in the example above. 
     44theory_plot_ID_pattern = re.compile(r"^([0-9]+)\s+(\[(.*)\]\s+)?(.*)$") 
    3745 
    3846def get_app_dir(): 
     
    211219    # New theory data in current perspective 
    212220    updateTheoryFromPerspectiveSignal = QtCore.pyqtSignal(QtGui.QStandardItem) 
     221 
     222    # Request to delete plots (in the theory view) related to a given model ID 
     223    deleteIntermediateTheoryPlotsSignal = QtCore.pyqtSignal(str) 
    213224 
    214225    # New plot requested from the GUI manager 
  • src/sas/qtgui/Utilities/LocalConfig.py

    re4335ae rb764ae5  
    134134 
    135135# Default threading model 
    136 USING_TWISTED = True 
     136USING_TWISTED = False 
    137137 
    138138# Time out for updating sasview 
  • src/sas/qtgui/Utilities/ReportDialog.py

    rce30949 rcb90b65  
    7373        # Use a sensible filename default 
    7474        default_name = os.path.join(location, 'fit_report.pdf') 
     75 
    7576        kwargs = { 
    7677            'parent'   : self, 
    7778            'caption'  : 'Save Report', 
    78             'directory': default_name, 
     79            # don't use 'directory' in order to remember the previous user choice 
     80            #'directory': default_name, 
    7981            'filter'   : 'PDF file (*.pdf);;HTML file (*.html);;Text file (*.txt)', 
    8082            'options'  : QtWidgets.QFileDialog.DontUseNativeDialog} 
     
    99101 
    100102        # Create files with charts 
    101         pictures = self.getPictures(basename) 
     103        pictures = [] 
     104        if self.data_images is not None: 
     105            pictures = self.getPictures(basename) 
    102106 
    103107        # self.data_html contains all images at the end of the report, in base64 form; 
  • src/sas/qtgui/Utilities/UnitTesting/ReportDialogTest.py

    r144fe21 rcb90b65  
    158158 
    159159        self.assertTrue(logging.error.called) 
    160         logging.error.assert_called_with("Error creating pdf: Failed") 
     160        #logging.error.assert_called_with("Error creating pdf") 
    161161 
Note: See TracChangeset for help on using the changeset viewer.