Changeset 21e71f1 in sasview for src/sas/qtgui/Utilities


Ignore:
Timestamp:
Nov 21, 2018 8:39:24 AM (5 years ago)
Author:
Piotr Rozyczko <piotr.rozyczko@…>
Branches:
ESS_GUI, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
Children:
f2e199e
Parents:
44c15fc (diff), fb39f28 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'ESS_GUI_project_save' into ESS_GUI

Location:
src/sas/qtgui/Utilities
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/Utilities/GuiUtils.py

    r67346f9 r133812c7  
    1111import webbrowser 
    1212import urllib.parse 
     13import json 
     14from io import BytesIO 
    1315 
    1416import numpy as np 
     
    2628from sas.qtgui.Plotting.PlotterData import Data1D 
    2729from sas.qtgui.Plotting.PlotterData import Data2D 
     30from sas.qtgui.Plotting.Plottables import Plottable 
     31from sas.sascalc.dataloader.data_info import Sample, Source, Vector 
     32from sas.qtgui.Plotting.Plottables import View 
     33from sas.qtgui.Plotting.Plottables import PlottableTheory1D 
     34from sas.qtgui.Plotting.Plottables import PlottableFit1D 
     35from sas.qtgui.Plotting.Plottables import Text 
     36from sas.qtgui.Plotting.Plottables import Chisq 
     37from sas.qtgui.MainWindow.DataState import DataState 
     38 
    2839from sas.sascalc.dataloader.loader import Loader 
    2940from sas.qtgui.Utilities import CustomDir 
     
    259270    sendDataToGridSignal = QtCore.pyqtSignal(list) 
    260271 
    261     # Action Save Analysis triggered 
    262     saveAnalysisSignal = QtCore.pyqtSignal() 
    263  
    264272    # Mask Editor requested 
    265273    maskEditorSignal = QtCore.pyqtSignal(Data2D) 
     
    292300    forcePlotDisplaySignal = QtCore.pyqtSignal(list) 
    293301 
    294 def updateModelItemWithPlot(item, update_data, name=""): 
     302def updateModelItemWithPlot(item, update_data, name="", checkbox_state=None): 
    295303    """ 
    296304    Adds a checkboxed row named "name" to QStandardItem 
     
    317325            # Force redisplay 
    318326            return 
    319  
    320327    # Create the new item 
    321328    checkbox_item = createModelItemWithPlot(update_data, name) 
    322329 
     330    if checkbox_state is not None: 
     331        checkbox_item.setCheckState(checkbox_state) 
    323332    # Append the new row to the main item 
    324333    item.appendRow(checkbox_item) 
     
    571580    if isinstance(data.process, list) and data.process: 
    572581        for process in data.process: 
     582            if process is None: 
     583                continue 
    573584            process_date = process.date 
    574585            process_date_item = QtGui.QStandardItem("Date: " + process_date) 
     
    11451156    return result 
    11461157 
     1158def saveData(fp, data): 
     1159    """ 
     1160    save content of data to fp (a .write()-supporting file-like object) 
     1161    """ 
     1162 
     1163    def add_type(dict, type): 
     1164        dict['__type__'] = type.__name__ 
     1165        return dict 
     1166 
     1167    def jdefault(o): 
     1168        """ 
     1169        objects that can't otherwise be serialized need to be converted 
     1170        """ 
     1171        # tuples and sets (TODO: default JSONEncoder converts tuples to lists, create custom Encoder that preserves tuples) 
     1172        if isinstance(o, (tuple, set)): 
     1173            content = { 'data': list(o) } 
     1174            return add_type(content, type(o)) 
     1175 
     1176        # "simple" types 
     1177        if isinstance(o, (Sample, Source, Vector)): 
     1178            return add_type(o.__dict__, type(o)) 
     1179        if isinstance(o, (Plottable, View)): 
     1180            return add_type(o.__dict__, type(o)) 
     1181 
     1182        # DataState 
     1183        if isinstance(o, (Data1D, Data2D)): 
     1184            # don't store parent 
     1185            content = o.__dict__.copy() 
     1186            #content.pop('parent') 
     1187            return add_type(content, type(o)) 
     1188 
     1189        # ndarray 
     1190        if isinstance(o, np.ndarray): 
     1191            buffer = BytesIO() 
     1192            np.save(buffer, o) 
     1193            buffer.seek(0) 
     1194            content = { 'data': buffer.read().decode('latin-1') } 
     1195            return add_type(content, type(o)) 
     1196 
     1197        # not supported 
     1198        logging.info("data cannot be serialized to json: %s" % type(o)) 
     1199        return None 
     1200 
     1201    json.dump(data, fp, indent=2, sort_keys=True, default=jdefault) 
     1202 
     1203def readDataFromFile(fp): 
     1204    ''' 
     1205    Reads in Data1D/Data2 datasets from the file. 
     1206    Datasets are stored in the JSON format. 
     1207    ''' 
     1208    supported = [ 
     1209        tuple, set, 
     1210        Sample, Source, Vector, 
     1211        Plottable, Data1D, Data2D, PlottableTheory1D, PlottableFit1D, Text, Chisq, View, 
     1212        DataState, np.ndarray] 
     1213 
     1214    lookup = dict((cls.__name__, cls) for cls in supported) 
     1215 
     1216    class TooComplexException(Exception): 
     1217        pass 
     1218 
     1219    def simple_type(cls, data, level): 
     1220        class Empty(object): 
     1221            def __init__(self): 
     1222                for key, value in data.items(): 
     1223                    setattr(self, key, generate(value, level)) 
     1224 
     1225        # create target object 
     1226        o = Empty() 
     1227        o.__class__ = cls 
     1228 
     1229        return o 
     1230 
     1231    def construct(type, data, level): 
     1232        try: 
     1233            cls = lookup[type] 
     1234        except KeyError: 
     1235            logging.info('unknown type: %s' % type) 
     1236            return None 
     1237 
     1238        # tuples and sets 
     1239        if cls in (tuple, set): 
     1240            # convert list to tuple/set 
     1241            return cls(generate(data['data'], level)) 
     1242 
     1243        # "simple" types 
     1244        if cls in (Sample, Source, Vector): 
     1245            return simple_type(cls, data, level) 
     1246        if issubclass(cls, Plottable) or (cls == View): 
     1247            return simple_type(cls, data, level) 
     1248 
     1249        # DataState 
     1250        if cls == DataState: 
     1251            o = simple_type(cls, data, level) 
     1252            o.parent = None # TODO: set to ??? 
     1253            return o 
     1254 
     1255        # ndarray 
     1256        if cls == np.ndarray: 
     1257            buffer = BytesIO() 
     1258            buffer.write(data['data'].encode('latin-1')) 
     1259            buffer.seek(0) 
     1260            return np.load(buffer) 
     1261 
     1262        logging.info('not implemented: %s, %s' % (type, cls)) 
     1263        return None 
     1264 
     1265    def generate(data, level): 
     1266        if level > 16: # recursion limit (arbitrary number) 
     1267            raise TooComplexException() 
     1268        else: 
     1269            level += 1 
     1270 
     1271        if isinstance(data, dict): 
     1272            try: 
     1273                type = data['__type__'] 
     1274            except KeyError: 
     1275                # if dictionary doesn't have __type__ then it is assumed to be just an ordinary dictionary 
     1276                o = {} 
     1277                for key, value in data.items(): 
     1278                    o[key] = generate(value, level) 
     1279                return o 
     1280 
     1281            return construct(type, data, level) 
     1282 
     1283        if isinstance(data, list): 
     1284            return [generate(item, level) for item in data] 
     1285 
     1286        return data 
     1287 
     1288    new_stored_data = {} 
     1289    for id, data in json.load(fp).items(): 
     1290        try: 
     1291            new_stored_data[id] = generate(data, 0) 
     1292        except TooComplexException: 
     1293            logging.info('unable to load %s' % id) 
     1294 
     1295    return new_stored_data 
     1296 
     1297def readProjectFromSVS(filepath): 
     1298    """ 
     1299    Read old SVS file and convert to the project dictionary 
     1300    """ 
     1301    from sas.sascalc.dataloader.readers.cansas_reader import Reader as CansasReader 
     1302    from sas.sascalc.fit.pagestate import Reader 
     1303 
     1304    loader = Loader() 
     1305    loader.associate_file_reader('.svs', Reader) 
     1306    temp = loader.load(filepath) 
     1307    state_reader = Reader() 
     1308    data_svs, state_svs = state_reader.read(filepath) 
     1309 
     1310    output = [] 
     1311    if isinstance(temp, list) and isinstance(state_svs, list): 
     1312        for item, state in zip(temp, state_svs): 
     1313            output.append([item, state]) 
     1314    else: 
     1315        output[temp, state_svs] 
     1316    return output 
     1317 
     1318def convertFromSVS(datasets): 
     1319    """ 
     1320    Read in properties from SVS and convert into a simple dict 
     1321    """ 
     1322    content = {} 
     1323    for dataset in datasets: 
     1324        # we already have data - interested only in properties 
     1325        #[[item_1, state_1], [item_2, state_2],...] 
     1326        data = dataset[0] 
     1327        params = dataset[1] 
     1328        content[params.data_id] = {} 
     1329        content[params.data_id]['fit_data'] = [data, {'checked': 2}, []] 
     1330        param_dict = {} 
     1331        param_dict['fitpage_category'] = [params.categorycombobox] 
     1332        param_dict['fitpage_model'] = [params.formfactorcombobox] 
     1333        param_dict['fitpage_structure'] = [params.structurecombobox] 
     1334        param_dict['2D_params'] = [str(params.is_2D)] 
     1335        param_dict['chainfit_params'] = ["False"] 
     1336        param_dict['data_id'] = [params.data_id] 
     1337        param_dict['data_name'] = [params.data_name] 
     1338        param_dict['is_data'] = [str(params.is_data)] 
     1339        param_dict['magnetic_params'] = [str(params.magnetic_on)] 
     1340        param_dict['model_name'] = [params.formfactorcombobox] 
     1341        param_dict['polydisperse_params'] = [str(params.enable_disp)] 
     1342        param_dict['q_range_max'] = [str(params.qmax)] 
     1343        param_dict['q_range_min'] = [str(params.qmin)] 
     1344        # Smearing is a bit trickier. 4.x has multiple keywords, 
     1345        # one for each combobox option 
     1346        if params.enable_smearer: 
     1347            if params.slit_smearer: 
     1348                w = 1 
     1349            elif params.pinhole_smearer: 
     1350                w = 2 
     1351            else: 
     1352                w = 0 
     1353            param_dict['smearing'] = [str(w)] 
     1354        # weighting is also tricky. 4.x has multiple keywords, 
     1355        # one for each radio box. 
     1356        if params.dI_noweight: 
     1357            w = 2 
     1358        elif params.dI_didata: 
     1359            w = 3 
     1360        elif params.dI_sqrdata: 
     1361            w = 4 
     1362        elif params.dI_idata: 
     1363            w = 5 
     1364        else: 
     1365            w = 2 
     1366        param_dict['weighting'] = [str(w)] 
     1367 
     1368        # 4.x multi_factor is really the multiplicity 
     1369        if params.multi_factor is not None: 
     1370            param_dict['multiplicity'] = [str(int(params.multi_factor))] 
     1371 
     1372        # playing with titles 
     1373        data.filename = params.file 
     1374        data.title = params.data_name 
     1375        data.name = params.data_name 
     1376 
     1377        # main parameters 
     1378        for p in params.parameters: 
     1379            p_name = p[1] 
     1380            param_dict[p_name] = [str(p[0]), str(p[2]), None, str(p[5][1]), str(p[6][1])] 
     1381        # orientation parameters 
     1382        if params.is_2D: 
     1383            for p in params.orientation_params: 
     1384                p_name = p[1] 
     1385                p_min = "-360.0" 
     1386                p_max = "360.0" 
     1387                if p[5][1] != "": 
     1388                    p_min = p[5][1] 
     1389                if p[6][1] != "": 
     1390                    p_max = p[6][1] 
     1391                param_dict[p_name] = [str(p[0]), str(p[2]), None, p_min, p_max] 
     1392 
     1393        # disperse parameters 
     1394        if params.enable_disp: 
     1395            for p in params.fittable_param: 
     1396                p_name = p[1] 
     1397                p_opt = str(p[0]) 
     1398                p_err = "0" 
     1399                p_width = str(p[2]) 
     1400                p_min = str(0) 
     1401                p_max = "inf" 
     1402                param_npts = p_name.replace('.width','.npts') 
     1403                param_nsigmas = p_name.replace('.width', '.nsigmas') 
     1404                if params.is_2D and p_name in params.disp_obj_dict: 
     1405                    lookup = params.orientation_params_disp 
     1406                    p_min = "-360.0" 
     1407                    p_max = "360.0" 
     1408                else: 
     1409                    lookup = params.fixed_param 
     1410                p_npts = [s[2] for s in lookup if s[1] == param_npts][0] 
     1411                p_nsigmas = [s[2] for s in lookup if s[1] == param_nsigmas][0] 
     1412                if p_name in params.disp_obj_dict: 
     1413                    p_disp = params.disp_obj_dict[p_name] 
     1414                else: 
     1415                    p_disp = "gaussian" 
     1416                param_dict[p_name] = [p_opt, p_width, p_min, p_max, p_npts, p_nsigmas, p_disp] 
     1417 
     1418        content[params.data_id]['fit_params'] = param_dict 
     1419    return content 
    11471420 
    11481421def enum(*sequential, **named): 
  • src/sas/qtgui/Utilities/GridPanel.py

    r75906a1 rc4c4957  
    126126        return 
    127127 
    128     def addTabPage(self): 
     128    def addTabPage(self, name=None): 
    129129        """ 
    130130        Add new tab page with QTableWidget 
     
    141141        # However, some models have LONG names, which doesn't look well on the tab bar. 
    142142        self.tab_number += 1 
    143         tab_name = "Tab " + str(self.tab_number) 
     143        if name is not None: 
     144            tab_name = name 
     145        else: 
     146            tab_name = "Tab " + str(self.tab_number) 
    144147        # each table needs separate slots. 
    145148        tab_widget.customContextMenuRequested.connect(self.showContextMenu) 
     
    153156        Create a new tab with batch fitting results 
    154157        """ 
     158        # pull out page name from results 
     159        page_name = None 
     160        if len(results)>=2: 
     161            if isinstance(results[-1], str): 
     162                page_name = results[-1] 
     163                _ = results.pop(-1) 
     164 
    155165        if self.has_data: 
    156             self.addTabPage() 
     166            self.addTabPage(name=page_name) 
     167        else: 
     168            self.tabWidget.setTabText(0, page_name) 
    157169        # Update the new widget 
    158170        # Fill in the table from input data in the last/newest page 
Note: See TracChangeset for help on using the changeset viewer.