source: sasview/src/sas/qtgui/Utilities/GuiUtils.py @ b3e8629

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since b3e8629 was b3e8629, checked in by Piotr Rozyczko <rozyczko@…>, 6 years ago

Initial changes to make SasView? run with python3

  • Property mode set to 100755
File size: 27.0 KB
Line 
1"""
2Global defaults and various utility functions usable by the general GUI
3"""
4
5import os
6import re
7import sys
8import imp
9import warnings
10import webbrowser
11import urllib.parse
12
13warnings.simplefilter("ignore")
14import logging
15
16from PyQt4 import QtCore
17from PyQt4 import QtGui
18
19from periodictable import formula as Formula
20from sas.qtgui.Plotting import DataTransform
21from sas.qtgui.Plotting.ConvertUnits import convertUnit
22from sas.qtgui.Plotting.PlotterData import Data1D
23from sas.qtgui.Plotting.PlotterData import Data2D
24from sas.sascalc.dataloader.loader import Loader
25from sas.qtgui.Utilities import CustomDir
26
27## TODO: CHANGE FOR SHIPPED PATH IN RELEASE
28if os.path.splitext(sys.argv[0])[1].lower() != ".py":
29        HELP_DIRECTORY_LOCATION = "doc"
30else:
31        HELP_DIRECTORY_LOCATION = "docs/sphinx-docs/build/html"
32IMAGES_DIRECTORY_LOCATION = HELP_DIRECTORY_LOCATION + "/_images"
33
34def get_app_dir():
35    """
36        The application directory is the one where the default custom_config.py
37        file resides.
38
39        :returns: app_path - the path to the applicatin directory
40    """
41    # First, try the directory of the executable we are running
42    app_path = sys.path[0]
43    if os.path.isfile(app_path):
44        app_path = os.path.dirname(app_path)
45    if os.path.isfile(os.path.join(app_path, "custom_config.py")):
46        app_path = os.path.abspath(app_path)
47        #logging.info("Using application path: %s", app_path)
48        return app_path
49
50    # Next, try the current working directory
51    if os.path.isfile(os.path.join(os.getcwd(), "custom_config.py")):
52        #logging.info("Using application path: %s", os.getcwd())
53        return os.path.abspath(os.getcwd())
54
55    # Finally, try the directory of the sasview module
56    # TODO: gui_manager will have to know about sasview until we
57    # clean all these module variables and put them into a config class
58    # that can be passed by sasview.py.
59    #logging.info(sys.executable)
60    #logging.info(str(sys.argv))
61    from sas import sasview as sasview
62    app_path = os.path.dirname(sasview.__file__)
63    #logging.info("Using application path: %s", app_path)
64    return app_path
65
66def get_user_directory():
67    """
68        Returns the user's home directory
69    """
70    userdir = os.path.join(os.path.expanduser("~"), ".sasview")
71    if not os.path.isdir(userdir):
72        os.makedirs(userdir)
73    return userdir
74
75def _find_local_config(confg_file, path):
76    """
77        Find configuration file for the current application
78    """
79    config_module = None
80    fObj = None
81    try:
82        fObj, path_config, descr = imp.find_module(confg_file, [path])
83        config_module = imp.load_module(confg_file, fObj, path_config, descr)
84    except ImportError:
85        pass
86        #logging.error("Error loading %s/%s: %s" % (path, confg_file, sys.exc_value))
87    except ValueError:
88        print("Value error")
89        pass
90    finally:
91        if fObj is not None:
92            fObj.close()
93    #logging.info("GuiManager loaded %s/%s" % (path, confg_file))
94    return config_module
95
96
97# Get APP folder
98PATH_APP = get_app_dir()
99DATAPATH = PATH_APP
100
101# Read in the local config, which can either be with the main
102# application or in the installation directory
103config = _find_local_config('local_config', PATH_APP)
104
105if config is None:
106    config = _find_local_config('local_config', os.getcwd())
107else:
108    pass
109
110c_conf_dir = CustomDir.setup_conf_dir(PATH_APP)
111
112custom_config = _find_local_config('custom_config', c_conf_dir)
113if custom_config is None:
114    custom_config = _find_local_config('custom_config', os.getcwd())
115    if custom_config is None:
116        msgConfig = "Custom_config file was not imported"
117
118#read some constants from config
119APPLICATION_STATE_EXTENSION = config.APPLICATION_STATE_EXTENSION
120APPLICATION_NAME = config.__appname__
121SPLASH_SCREEN_PATH = config.SPLASH_SCREEN_PATH
122WELCOME_PANEL_ON = config.WELCOME_PANEL_ON
123SPLASH_SCREEN_WIDTH = config.SPLASH_SCREEN_WIDTH
124SPLASH_SCREEN_HEIGHT = config.SPLASH_SCREEN_HEIGHT
125SS_MAX_DISPLAY_TIME = config.SS_MAX_DISPLAY_TIME
126if not WELCOME_PANEL_ON:
127    WELCOME_PANEL_SHOW = False
128else:
129    WELCOME_PANEL_SHOW = True
130try:
131    DATALOADER_SHOW = custom_config.DATALOADER_SHOW
132    TOOLBAR_SHOW = custom_config.TOOLBAR_SHOW
133    FIXED_PANEL = custom_config.FIXED_PANEL
134    if WELCOME_PANEL_ON:
135        WELCOME_PANEL_SHOW = custom_config.WELCOME_PANEL_SHOW
136    PLOPANEL_WIDTH = custom_config.PLOPANEL_WIDTH
137    DATAPANEL_WIDTH = custom_config.DATAPANEL_WIDTH
138    GUIFRAME_WIDTH = custom_config.GUIFRAME_WIDTH
139    GUIFRAME_HEIGHT = custom_config.GUIFRAME_HEIGHT
140    CONTROL_WIDTH = custom_config.CONTROL_WIDTH
141    CONTROL_HEIGHT = custom_config.CONTROL_HEIGHT
142    DEFAULT_PERSPECTIVE = custom_config.DEFAULT_PERSPECTIVE
143    CLEANUP_PLOT = custom_config.CLEANUP_PLOT
144    # custom open_path
145    open_folder = custom_config.DEFAULT_OPEN_FOLDER
146    if open_folder is not None and os.path.isdir(open_folder):
147        DEFAULT_OPEN_FOLDER = os.path.abspath(open_folder)
148    else:
149        DEFAULT_OPEN_FOLDER = PATH_APP
150except AttributeError:
151    DATALOADER_SHOW = True
152    TOOLBAR_SHOW = True
153    FIXED_PANEL = True
154    WELCOME_PANEL_SHOW = False
155    PLOPANEL_WIDTH = config.PLOPANEL_WIDTH
156    DATAPANEL_WIDTH = config.DATAPANEL_WIDTH
157    GUIFRAME_WIDTH = config.GUIFRAME_WIDTH
158    GUIFRAME_HEIGHT = config.GUIFRAME_HEIGHT
159    CONTROL_WIDTH = -1
160    CONTROL_HEIGHT = -1
161    DEFAULT_PERSPECTIVE = None
162    CLEANUP_PLOT = False
163    DEFAULT_OPEN_FOLDER = PATH_APP
164
165#DEFAULT_STYLE = config.DEFAULT_STYLE
166
167PLUGIN_STATE_EXTENSIONS = config.PLUGIN_STATE_EXTENSIONS
168OPEN_SAVE_MENU = config.OPEN_SAVE_PROJECT_MENU
169VIEW_MENU = config.VIEW_MENU
170EDIT_MENU = config.EDIT_MENU
171extension_list = []
172if APPLICATION_STATE_EXTENSION is not None:
173    extension_list.append(APPLICATION_STATE_EXTENSION)
174EXTENSIONS = PLUGIN_STATE_EXTENSIONS + extension_list
175try:
176    PLUGINS_WLIST = '|'.join(config.PLUGINS_WLIST)
177except AttributeError:
178    PLUGINS_WLIST = ''
179APPLICATION_WLIST = config.APPLICATION_WLIST
180IS_WIN = True
181IS_LINUX = False
182CLOSE_SHOW = True
183TIME_FACTOR = 2
184NOT_SO_GRAPH_LIST = ["BoxSum"]
185
186
187class Communicate(QtCore.QObject):
188    """
189    Utility class for tracking of the Qt signals
190    """
191    # File got successfully read
192    fileReadSignal = QtCore.pyqtSignal(list)
193
194    # Open File returns "list" of paths
195    fileDataReceivedSignal = QtCore.pyqtSignal(dict)
196
197    # Update Main window status bar with "str"
198    # Old "StatusEvent"
199    statusBarUpdateSignal = QtCore.pyqtSignal(str)
200
201    # Send data to the current perspective
202    updatePerspectiveWithDataSignal = QtCore.pyqtSignal(list)
203
204    # New data in current perspective
205    updateModelFromPerspectiveSignal = QtCore.pyqtSignal(QtGui.QStandardItem)
206
207    # New theory data in current perspective
208    updateTheoryFromPerspectiveSignal = QtCore.pyqtSignal(QtGui.QStandardItem)
209
210    # New plot requested from the GUI manager
211    # Old "NewPlotEvent"
212    plotRequestedSignal = QtCore.pyqtSignal(list)
213
214    # Plot update requested from a perspective
215    plotUpdateSignal = QtCore.pyqtSignal(list)
216
217    # Progress bar update value
218    progressBarUpdateSignal = QtCore.pyqtSignal(int)
219
220    # Workspace charts added/removed
221    activeGraphsSignal = QtCore.pyqtSignal(list)
222
223    # Current workspace chart's name changed
224    activeGraphName = QtCore.pyqtSignal(tuple)
225
226    # Current perspective changed
227    perspectiveChangedSignal = QtCore.pyqtSignal(str)
228
229    # File/dataset got deleted
230    dataDeletedSignal = QtCore.pyqtSignal(list)
231
232    # Send data to Data Operation Utility panel
233    sendDataToPanelSignal = QtCore.pyqtSignal(dict)
234
235    # Send result of Data Operation Utility panel to Data Explorer
236    updateModelFromDataOperationPanelSignal = QtCore.pyqtSignal(QtGui.QStandardItem, dict)
237
238def updateModelItemWithPlot(item, update_data, name=""):
239    """
240    Adds a checkboxed row named "name" to QStandardItem
241    Adds QVariant 'update_data' to that row.
242    """
243    assert isinstance(item, QtGui.QStandardItem)
244    #assert isinstance(update_data, QtCore.QVariant)
245    #py_update_data = update_data.toPyObject()
246    py_update_data = update_data
247
248    # Check if data with the same ID is already present
249    for index in range(item.rowCount()):
250        plot_item = item.child(index)
251        if plot_item.isCheckable():
252            plot_data = plot_item.child(0).data() #.toPyObject()
253            if plot_data.id is not None and plot_data.id == py_update_data.id:
254                # replace data section in item
255                plot_item.child(0).setData(update_data)
256                plot_item.setText(name)
257                # Plot title
258                plot_item.child(1).child(0).setText("Title: %s"%name)
259                # Force redisplay
260                return
261
262    # Create the new item
263    checkbox_item = createModelItemWithPlot(update_data, name)
264
265    # Append the new row to the main item
266    item.appendRow(checkbox_item)
267
268def createModelItemWithPlot(update_data, name=""):
269    """
270    Creates a checkboxed QStandardItem named "name"
271    Adds QVariant 'update_data' to that row.
272    """
273    #assert isinstance(update_data, QtCore.QVariant)
274    #py_update_data = update_data.toPyObject()
275    py_update_data = update_data
276
277    checkbox_item = QtGui.QStandardItem()
278    checkbox_item.setCheckable(True)
279    checkbox_item.setCheckState(QtCore.Qt.Checked)
280    checkbox_item.setText(name)
281
282    # Add "Info" item
283    if isinstance(py_update_data, (Data1D, Data2D)):
284        # If Data1/2D added - extract Info from it
285        info_item = infoFromData(py_update_data)
286    else:
287        # otherwise just add a naked item
288        info_item = QtGui.QStandardItem("Info")
289
290    # Add the actual Data1D/Data2D object
291    object_item = QtGui.QStandardItem()
292    object_item.setData(update_data)
293
294    # Set the data object as the first child
295    checkbox_item.setChild(0, object_item)
296
297    # Set info_item as the second child
298    checkbox_item.setChild(1, info_item)
299
300    # And return the newly created item
301    return checkbox_item
302
303def updateModelItem(item, update_data, name=""):
304    """
305    Adds a simple named child to QStandardItem
306    """
307    assert isinstance(item, QtGui.QStandardItem)
308    assert isinstance(update_data, list)
309
310    # Add the actual Data1D/Data2D object
311    object_item = QtGui.QStandardItem()
312    object_item.setText(name)
313    #object_item.setData(QtCore.QVariant(update_data))
314    object_item.setData(update_data)
315
316    # Append the new row to the main item
317    item.appendRow(object_item)
318
319def itemFromFilename(filename, model_item):
320    """
321    Returns the model item text=filename in the model
322    """
323    assert isinstance(model_item, QtGui.QStandardItemModel)
324    assert isinstance(filename, str)
325
326    # Iterate over model looking for named items
327    item = list([i for i in [model_item.item(index) for index in range(model_item.rowCount())] if str(i.text()) == filename])
328    return item[0] if len(item)>0 else None
329
330def plotsFromFilename(filename, model_item):
331    """
332    Returns the list of plots for the item with text=filename in the model
333    """
334    assert isinstance(model_item, QtGui.QStandardItemModel)
335    assert isinstance(filename, str)
336
337    plot_data = []
338    # Iterate over model looking for named items
339    for index in range(model_item.rowCount()):
340        item = model_item.item(index)
341        if str(item.text()) == filename:
342            # TODO: assure item type is correct (either data1/2D or Plotter)
343            plot_data.append(item.child(0).data()) #.toPyObject())
344            # Going 1 level deeper only
345            for index_2 in range(item.rowCount()):
346                item_2 = item.child(index_2)
347                if item_2 and item_2.isCheckable():
348                    # TODO: assure item type is correct (either data1/2D or Plotter)
349                    plot_data.append(item_2.child(0).data()) #.toPyObject())
350
351    return plot_data
352
353def plotsFromCheckedItems(model_item):
354    """
355    Returns the list of plots for items in the model which are checked
356    """
357    assert isinstance(model_item, QtGui.QStandardItemModel)
358
359    plot_data = []
360    # Iterate over model looking for items with checkboxes
361    for index in range(model_item.rowCount()):
362        item = model_item.item(index)
363        if item.isCheckable() and item.checkState() == QtCore.Qt.Checked:
364            # TODO: assure item type is correct (either data1/2D or Plotter)
365            plot_data.append((item, item.child(0).data())) #.toPyObject()))
366        # Going 1 level deeper only
367        for index_2 in range(item.rowCount()):
368            item_2 = item.child(index_2)
369            if item_2 and item_2.isCheckable() and item_2.checkState() == QtCore.Qt.Checked:
370                # TODO: assure item type is correct (either data1/2D or Plotter)
371                plot_data.append((item_2, item_2.child(0).data())) #.toPyObject()))
372
373    return plot_data
374
375def infoFromData(data):
376    """
377    Given Data1D/Data2D object, extract relevant Info elements
378    and add them to a model item
379    """
380    assert isinstance(data, (Data1D, Data2D))
381
382    info_item = QtGui.QStandardItem("Info")
383
384    title_item = QtGui.QStandardItem("Title: " + data.title)
385    info_item.appendRow(title_item)
386    run_item = QtGui.QStandardItem("Run: " + str(data.run))
387    info_item.appendRow(run_item)
388    type_item = QtGui.QStandardItem("Type: " + str(data.__class__.__name__))
389    info_item.appendRow(type_item)
390
391    if data.path:
392        path_item = QtGui.QStandardItem("Path: " + data.path)
393        info_item.appendRow(path_item)
394
395    if data.instrument:
396        instr_item = QtGui.QStandardItem("Instrument: " + data.instrument)
397        info_item.appendRow(instr_item)
398
399    process_item = QtGui.QStandardItem("Process")
400    if isinstance(data.process, list) and data.process:
401        for process in data.process:
402            process_date = process.date
403            process_date_item = QtGui.QStandardItem("Date: " + process_date)
404            process_item.appendRow(process_date_item)
405
406            process_descr = process.description
407            process_descr_item = QtGui.QStandardItem("Description: " + process_descr)
408            process_item.appendRow(process_descr_item)
409
410            process_name = process.name
411            process_name_item = QtGui.QStandardItem("Name: " + process_name)
412            process_item.appendRow(process_name_item)
413
414    info_item.appendRow(process_item)
415
416    return info_item
417
418def openLink(url):
419    """
420    Open a URL in an external browser.
421    Check the URL first, though.
422    """
423    parsed_url = urllib.parse.urlparse(url)
424    if parsed_url.scheme:
425        webbrowser.open(url)
426    else:
427        msg = "Attempt at opening an invalid URL"
428        raise AttributeError(msg)
429
430def retrieveData1d(data):
431    """
432    Retrieve 1D data from file and construct its text
433    representation
434    """
435    if not isinstance(data, Data1D):
436        msg = "Incorrect type passed to retrieveData1d"
437        raise AttributeError(msg)
438    try:
439        xmin = min(data.x)
440        ymin = min(data.y)
441    except:
442        msg = "Unable to find min/max of \n data named %s" % \
443                    data.filename
444        #logging.error(msg)
445        raise ValueError(msg)
446
447    text = data.__str__()
448    text += 'Data Min Max:\n'
449    text += 'X_min = %s:  X_max = %s\n' % (xmin, max(data.x))
450    text += 'Y_min = %s:  Y_max = %s\n' % (ymin, max(data.y))
451    if data.dy is not None:
452        text += 'dY_min = %s:  dY_max = %s\n' % (min(data.dy), max(data.dy))
453    text += '\nData Points:\n'
454    x_st = "X"
455    for index in range(len(data.x)):
456        if data.dy is not None and len(data.dy) > index:
457            dy_val = data.dy[index]
458        else:
459            dy_val = 0.0
460        if data.dx is not None and len(data.dx) > index:
461            dx_val = data.dx[index]
462        else:
463            dx_val = 0.0
464        if data.dxl is not None and len(data.dxl) > index:
465            if index == 0:
466                x_st = "Xl"
467            dx_val = data.dxl[index]
468        elif data.dxw is not None and len(data.dxw) > index:
469            if index == 0:
470                x_st = "Xw"
471            dx_val = data.dxw[index]
472
473        if index == 0:
474            text += "<index> \t<X> \t<Y> \t<dY> \t<d%s>\n" % x_st
475        text += "%s \t%s \t%s \t%s \t%s\n" % (index,
476                                                data.x[index],
477                                                data.y[index],
478                                                dy_val,
479                                                dx_val)
480    return text
481
482def retrieveData2d(data):
483    """
484    Retrieve 2D data from file and construct its text
485    representation
486    """
487    if not isinstance(data, Data2D):
488        msg = "Incorrect type passed to retrieveData2d"
489        raise AttributeError(msg)
490
491    text = data.__str__()
492    text += 'Data Min Max:\n'
493    text += 'I_min = %s\n' % min(data.data)
494    text += 'I_max = %s\n\n' % max(data.data)
495    text += 'Data (First 2501) Points:\n'
496    text += 'Data columns include err(I).\n'
497    text += 'ASCII data starts here.\n'
498    text += "<index> \t<Qx> \t<Qy> \t<I> \t<dI> \t<dQparal> \t<dQperp>\n"
499    di_val = 0.0
500    dx_val = 0.0
501    dy_val = 0.0
502    len_data = len(data.qx_data)
503    for index in range(0, len_data):
504        x_val = data.qx_data[index]
505        y_val = data.qy_data[index]
506        i_val = data.data[index]
507        if data.err_data is not None:
508            di_val = data.err_data[index]
509        if data.dqx_data is not None:
510            dx_val = data.dqx_data[index]
511        if data.dqy_data is not None:
512            dy_val = data.dqy_data[index]
513
514        text += "%s \t%s \t%s \t%s \t%s \t%s \t%s\n" % (index,
515                                                        x_val,
516                                                        y_val,
517                                                        i_val,
518                                                        di_val,
519                                                        dx_val,
520                                                        dy_val)
521        # Takes too long time for typical data2d: Break here
522        if index >= 2500:
523            text += ".............\n"
524            break
525
526    return text
527
528def onTXTSave(data, path):
529    """
530    Save file as formatted txt
531    """
532    with open(path,'w') as out:
533        has_errors = True
534        if data.dy == None or data.dy == []:
535            has_errors = False
536        # Sanity check
537        if has_errors:
538            try:
539                if len(data.y) != len(data.dy):
540                    has_errors = False
541            except:
542                has_errors = False
543        if has_errors:
544            if data.dx is not None and data.dx != []:
545                out.write("<X>   <Y>   <dY>   <dX>\n")
546            else:
547                out.write("<X>   <Y>   <dY>\n")
548        else:
549            out.write("<X>   <Y>\n")
550
551        for i in range(len(data.x)):
552            if has_errors:
553                if data.dx is not None and data.dx != []:
554                    if  data.dx[i] != None:
555                        out.write("%g  %g  %g  %g\n" % (data.x[i],
556                                                        data.y[i],
557                                                        data.dy[i],
558                                                        data.dx[i]))
559                    else:
560                        out.write("%g  %g  %g\n" % (data.x[i],
561                                                    data.y[i],
562                                                    data.dy[i]))
563                else:
564                    out.write("%g  %g  %g\n" % (data.x[i],
565                                                data.y[i],
566                                                data.dy[i]))
567            else:
568                out.write("%g  %g\n" % (data.x[i],
569                                        data.y[i]))
570
571def saveData1D(data):
572    """
573    Save 1D data points
574    """
575    default_name = os.path.basename(data.filename)
576    default_name, extension = os.path.splitext(default_name)
577    if not extension:
578        extension = ".txt"
579    default_name += "_out" + extension
580
581    wildcard = "Text files (*.txt);;"\
582                "CanSAS 1D files(*.xml)"
583    kwargs = {
584        'caption'   : 'Save As',
585        'directory' : default_name,
586        'filter'    : wildcard,
587        'parent'    : None,
588    }
589    # Query user for filename.
590    filename = QtGui.QFileDialog.getSaveFileName(**kwargs)
591
592    # User cancelled.
593    if not filename:
594        return
595
596    filename = str(filename)
597
598    #Instantiate a loader
599    loader = Loader()
600    if os.path.splitext(filename)[1].lower() == ".txt":
601        onTXTSave(data, filename)
602    if os.path.splitext(filename)[1].lower() == ".xml":
603        loader.save(filename, data, ".xml")
604
605def saveData2D(data):
606    """
607    Save data2d dialog
608    """
609    default_name = os.path.basename(data.filename)
610    default_name, _ = os.path.splitext(default_name)
611    ext_format = ".dat"
612    default_name += "_out" + ext_format
613
614    wildcard = "IGOR/DAT 2D file in Q_map (*.dat)"
615    kwargs = {
616        'caption'   : 'Save As',
617        'directory' : default_name,
618        'filter'    : wildcard,
619        'parent'    : None,
620    }
621    # Query user for filename.
622    filename = QtGui.QFileDialog.getSaveFileName(**kwargs)
623
624    # User cancelled.
625    if not filename:
626        return
627    filename = str(filename)
628    #Instantiate a loader
629    loader = Loader()
630
631    if os.path.splitext(filename)[1].lower() == ext_format:
632        loader.save(filename, data, ext_format)
633
634class FormulaValidator(QtGui.QValidator):
635    def __init__(self, parent=None):
636        super(FormulaValidator, self).__init__(parent)
637 
638    def validate(self, input, pos):
639        try:
640            Formula(str(input))
641            self._setStyleSheet("")
642            return QtGui.QValidator.Acceptable, pos
643
644        except Exception as e:
645            self._setStyleSheet("background-color:pink;")
646            return QtGui.QValidator.Intermediate, pos
647
648    def _setStyleSheet(self, value):
649        try:
650            if self.parent():
651                self.parent().setStyleSheet(value)
652        except:
653            pass
654
655def xyTransform(data, xLabel="", yLabel=""):
656    """
657    Transforms x and y in View and set the scale
658    """
659    # Changing the scale might be incompatible with
660    # currently displayed data (for instance, going
661    # from ln to log when all plotted values have
662    # negative natural logs).
663    # Go linear and only change the scale at the end.
664    xscale = 'linear'
665    yscale = 'linear'
666    # Local data is either 1D or 2D
667    if data.id == 'fit':
668        return
669
670    # control axis labels from the panel itself
671    yname, yunits = data.get_yaxis()
672    xname, xunits = data.get_xaxis()
673
674    # Goes through all possible scales
675    # self.x_label is already wrapped with Latex "$", so using the argument
676
677    # X
678    if xLabel == "x":
679        data.transformX(DataTransform.toX, DataTransform.errToX)
680        xLabel = "%s(%s)" % (xname, xunits)
681    if xLabel == "x^(2)":
682        data.transformX(DataTransform.toX2, DataTransform.errToX2)
683        xunits = convertUnit(2, xunits)
684        xLabel = "%s^{2}(%s)" % (xname, xunits)
685    if xLabel == "x^(4)":
686        data.transformX(DataTransform.toX4, DataTransform.errToX4)
687        xunits = convertUnit(4, xunits)
688        xLabel = "%s^{4}(%s)" % (xname, xunits)
689    if xLabel == "ln(x)":
690        data.transformX(DataTransform.toLogX, DataTransform.errToLogX)
691        xLabel = "\ln{(%s)}(%s)" % (xname, xunits)
692    if xLabel == "log10(x)":
693        data.transformX(DataTransform.toX_pos, DataTransform.errToX_pos)
694        xscale = 'log'
695        xLabel = "%s(%s)" % (xname, xunits)
696    if xLabel == "log10(x^(4))":
697        data.transformX(DataTransform.toX4, DataTransform.errToX4)
698        xunits = convertUnit(4, xunits)
699        xLabel = "%s^{4}(%s)" % (xname, xunits)
700        xscale = 'log'
701
702    # Y
703    if yLabel == "ln(y)":
704        data.transformY(DataTransform.toLogX, DataTransform.errToLogX)
705        yLabel = "\ln{(%s)}(%s)" % (yname, yunits)
706    if yLabel == "y":
707        data.transformY(DataTransform.toX, DataTransform.errToX)
708        yLabel = "%s(%s)" % (yname, yunits)
709    if yLabel == "log10(y)":
710        data.transformY(DataTransform.toX_pos, DataTransform.errToX_pos)
711        yscale = 'log'
712        yLabel = "%s(%s)" % (yname, yunits)
713    if yLabel == "y^(2)":
714        data.transformY(DataTransform.toX2, DataTransform.errToX2)
715        yunits = convertUnit(2, yunits)
716        yLabel = "%s^{2}(%s)" % (yname, yunits)
717    if yLabel == "1/y":
718        data.transformY(DataTransform.toOneOverX, DataTransform.errOneOverX)
719        yunits = convertUnit(-1, yunits)
720        yLabel = "1/%s(%s)" % (yname, yunits)
721    if yLabel == "y*x^(2)":
722        data.transformY(DataTransform.toYX2, DataTransform.errToYX2)
723        xunits = convertUnit(2, xunits)
724        yLabel = "%s \ \ %s^{2}(%s%s)" % (yname, xname, yunits, xunits)
725    if yLabel == "y*x^(4)":
726        data.transformY(DataTransform.toYX4, DataTransform.errToYX4)
727        xunits = convertUnit(4, xunits)
728        yLabel = "%s \ \ %s^{4}(%s%s)" % (yname, xname, yunits, xunits)
729    if yLabel == "1/sqrt(y)":
730        data.transformY(DataTransform.toOneOverSqrtX, DataTransform.errOneOverSqrtX)
731        yunits = convertUnit(-0.5, yunits)
732        yLabel = "1/\sqrt{%s}(%s)" % (yname, yunits)
733    if yLabel == "ln(y*x)":
734        data.transformY(DataTransform.toLogXY, DataTransform.errToLogXY)
735        yLabel = "\ln{(%s \ \ %s)}(%s%s)" % (yname, xname, yunits, xunits)
736    if yLabel == "ln(y*x^(2))":
737        data.transformY(DataTransform.toLogYX2, DataTransform.errToLogYX2)
738        xunits = convertUnit(2, xunits)
739        yLabel = "\ln (%s \ \ %s^{2})(%s%s)" % (yname, xname, yunits, xunits)
740    if yLabel == "ln(y*x^(4))":
741        data.transformY(DataTransform.toLogYX4, DataTransform.errToLogYX4)
742        xunits = convertUnit(4, xunits)
743        yLabel = "\ln (%s \ \ %s^{4})(%s%s)" % (yname, xname, yunits, xunits)
744    if yLabel == "log10(y*x^(4))":
745        data.transformY(DataTransform.toYX4, DataTransform.errToYX4)
746        xunits = convertUnit(4, xunits)
747        yscale = 'log'
748        yLabel = "%s \ \ %s^{4}(%s%s)" % (yname, xname, yunits, xunits)
749
750    # Perform the transformation of data in data1d->View
751    data.transformView()
752
753    return (xLabel, yLabel, xscale, yscale)
754
755def dataFromItem(item):
756    """
757    Retrieve Data1D/2D component from QStandardItem.
758    The assumption - data stored in SasView standard, in child 0
759    """
760    return item.child(0).data() #.toPyObject()
761
762def formatNumber(value, high=False):
763    """
764    Return a float in a standardized, human-readable formatted string.
765    This is used to output readable (e.g. x.xxxe-y) values to the panel.
766    """
767    try:
768        value = float(value)
769    except:
770        output = "NaN"
771        return output.lstrip().rstrip()
772
773    if high:
774        output = "%-7.5g" % value
775
776    else:
777        output = "%-5.3g" % value
778    return output.lstrip().rstrip()
779
780def convertUnitToHTML(unit):
781    """
782    Convert ASCII unit display into well rendering HTML
783    """
784    if unit == "1/A":
785        return "&#x212B;<sup>-1</sup>"
786    elif unit == "1/cm":
787        return "cm<sup>-1</sup>"
788    elif unit == "Ang":
789        return "&#x212B;"
790    elif unit == "1e-6/Ang^2":
791        return "10<sup>-6</sup>/&#x212B;<sup>2</sup>"
792    elif unit == "inf":
793        return "&#x221e;"
794    elif unit == "-inf":
795        return "-&#x221e;"
796    else:
797        return unit
798
799def parseName(name, expression):
800    """
801    remove "_" in front of a name
802    """
803    if re.match(expression, name) is not None:
804        word = re.split(expression, name, 1)
805        for item in word:           
806            if item.lstrip().rstrip() != '':
807                return item
808    else:
809        return name
Note: See TracBrowser for help on using the repository browser.