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

Last change on this file since 6b43c58 was 88e1f57, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

Fixed chart update upon consecutive fitting.
Fixed 1D default charts - now only two (combined data/fit + residuals)
Minor text fixes

  • Property mode set to 100644
File size: 26.9 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 urlparse
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
247    # Check if data with the same ID is already present
248    for index in range(item.rowCount()):
249        plot_item = item.child(index)
250        if plot_item.isCheckable():
251            plot_data = plot_item.child(0).data().toPyObject()
252            if plot_data.id is not None and plot_data.id == py_update_data.id:
253                # replace data section in item
254                plot_item.child(0).setData(update_data)
255                plot_item.setText(name)
256                # Plot title
257                plot_item.child(1).child(0).setText("Title: %s"%name)
258                # Force redisplay
259                return
260
261    # Create the new item
262    checkbox_item = createModelItemWithPlot(update_data, name)
263
264    # Append the new row to the main item
265    item.appendRow(checkbox_item)
266
267def createModelItemWithPlot(update_data, name=""):
268    """
269    Creates a checkboxed QStandardItem named "name"
270    Adds QVariant 'update_data' to that row.
271    """
272    assert isinstance(update_data, QtCore.QVariant)
273    py_update_data = update_data.toPyObject()
274
275    checkbox_item = QtGui.QStandardItem()
276    checkbox_item.setCheckable(True)
277    checkbox_item.setCheckState(QtCore.Qt.Checked)
278    checkbox_item.setText(name)
279
280    # Add "Info" item
281    if isinstance(py_update_data, (Data1D, Data2D)):
282        # If Data1/2D added - extract Info from it
283        info_item = infoFromData(py_update_data)
284    else:
285        # otherwise just add a naked item
286        info_item = QtGui.QStandardItem("Info")
287
288    # Add the actual Data1D/Data2D object
289    object_item = QtGui.QStandardItem()
290    object_item.setData(update_data)
291
292    # Set the data object as the first child
293    checkbox_item.setChild(0, object_item)
294
295    # Set info_item as the second child
296    checkbox_item.setChild(1, info_item)
297
298    # And return the newly created item
299    return checkbox_item
300
301def updateModelItem(item, update_data, name=""):
302    """
303    Adds a simple named child to QStandardItem
304    """
305    assert isinstance(item, QtGui.QStandardItem)
306    assert isinstance(update_data, list)
307
308    # Add the actual Data1D/Data2D object
309    object_item = QtGui.QStandardItem()
310    object_item.setText(name)
311    object_item.setData(QtCore.QVariant(update_data))
312
313    # Append the new row to the main item
314    item.appendRow(object_item)
315
316def itemFromFilename(filename, model_item):
317    """
318    Returns the model item text=filename in the model
319    """
320    assert isinstance(model_item, QtGui.QStandardItemModel)
321    assert isinstance(filename, basestring)
322
323    # Iterate over model looking for named items
324    item = list(filter(lambda i: str(i.text()) == filename,
325                  [model_item.item(index) for index in range(model_item.rowCount())]))
326    return item[0] if len(item)>0 else None
327
328def plotsFromFilename(filename, model_item):
329    """
330    Returns the list of plots for the item with text=filename in the model
331    """
332    assert isinstance(model_item, QtGui.QStandardItemModel)
333    assert isinstance(filename, basestring)
334
335    plot_data = []
336    # Iterate over model looking for named items
337    for index in range(model_item.rowCount()):
338        item = model_item.item(index)
339        if str(item.text()) == filename:
340            # TODO: assure item type is correct (either data1/2D or Plotter)
341            plot_data.append(item.child(0).data().toPyObject())
342            # Going 1 level deeper only
343            for index_2 in range(item.rowCount()):
344                item_2 = item.child(index_2)
345                if item_2 and item_2.isCheckable():
346                    # TODO: assure item type is correct (either data1/2D or Plotter)
347                    plot_data.append(item_2.child(0).data().toPyObject())
348
349    return plot_data
350
351def plotsFromCheckedItems(model_item):
352    """
353    Returns the list of plots for items in the model which are checked
354    """
355    assert isinstance(model_item, QtGui.QStandardItemModel)
356
357    plot_data = []
358    # Iterate over model looking for items with checkboxes
359    for index in range(model_item.rowCount()):
360        item = model_item.item(index)
361        if item.isCheckable() and item.checkState() == QtCore.Qt.Checked:
362            # TODO: assure item type is correct (either data1/2D or Plotter)
363            plot_data.append((item, item.child(0).data().toPyObject()))
364        # Going 1 level deeper only
365        for index_2 in range(item.rowCount()):
366            item_2 = item.child(index_2)
367            if item_2 and item_2.isCheckable() and item_2.checkState() == QtCore.Qt.Checked:
368                # TODO: assure item type is correct (either data1/2D or Plotter)
369                plot_data.append((item_2, item_2.child(0).data().toPyObject()))
370
371    return plot_data
372
373def infoFromData(data):
374    """
375    Given Data1D/Data2D object, extract relevant Info elements
376    and add them to a model item
377    """
378    assert isinstance(data, (Data1D, Data2D))
379
380    info_item = QtGui.QStandardItem("Info")
381
382    title_item = QtGui.QStandardItem("Title: " + data.title)
383    info_item.appendRow(title_item)
384    run_item = QtGui.QStandardItem("Run: " + str(data.run))
385    info_item.appendRow(run_item)
386    type_item = QtGui.QStandardItem("Type: " + str(data.__class__.__name__))
387    info_item.appendRow(type_item)
388
389    if data.path:
390        path_item = QtGui.QStandardItem("Path: " + data.path)
391        info_item.appendRow(path_item)
392
393    if data.instrument:
394        instr_item = QtGui.QStandardItem("Instrument: " + data.instrument)
395        info_item.appendRow(instr_item)
396
397    process_item = QtGui.QStandardItem("Process")
398    if isinstance(data.process, list) and data.process:
399        for process in data.process:
400            process_date = process.date
401            process_date_item = QtGui.QStandardItem("Date: " + process_date)
402            process_item.appendRow(process_date_item)
403
404            process_descr = process.description
405            process_descr_item = QtGui.QStandardItem("Description: " + process_descr)
406            process_item.appendRow(process_descr_item)
407
408            process_name = process.name
409            process_name_item = QtGui.QStandardItem("Name: " + process_name)
410            process_item.appendRow(process_name_item)
411
412    info_item.appendRow(process_item)
413
414    return info_item
415
416def openLink(url):
417    """
418    Open a URL in an external browser.
419    Check the URL first, though.
420    """
421    parsed_url = urlparse.urlparse(url)
422    if parsed_url.scheme:
423        webbrowser.open(url)
424    else:
425        msg = "Attempt at opening an invalid URL"
426        raise AttributeError, msg
427
428def retrieveData1d(data):
429    """
430    Retrieve 1D data from file and construct its text
431    representation
432    """
433    if not isinstance(data, Data1D):
434        msg = "Incorrect type passed to retrieveData1d"
435        raise AttributeError, msg
436    try:
437        xmin = min(data.x)
438        ymin = min(data.y)
439    except:
440        msg = "Unable to find min/max of \n data named %s" % \
441                    data.filename
442        #logging.error(msg)
443        raise ValueError, msg
444
445    text = data.__str__()
446    text += 'Data Min Max:\n'
447    text += 'X_min = %s:  X_max = %s\n' % (xmin, max(data.x))
448    text += 'Y_min = %s:  Y_max = %s\n' % (ymin, max(data.y))
449    if data.dy is not None:
450        text += 'dY_min = %s:  dY_max = %s\n' % (min(data.dy), max(data.dy))
451    text += '\nData Points:\n'
452    x_st = "X"
453    for index in range(len(data.x)):
454        if data.dy is not None and len(data.dy) > index:
455            dy_val = data.dy[index]
456        else:
457            dy_val = 0.0
458        if data.dx is not None and len(data.dx) > index:
459            dx_val = data.dx[index]
460        else:
461            dx_val = 0.0
462        if data.dxl is not None and len(data.dxl) > index:
463            if index == 0:
464                x_st = "Xl"
465            dx_val = data.dxl[index]
466        elif data.dxw is not None and len(data.dxw) > index:
467            if index == 0:
468                x_st = "Xw"
469            dx_val = data.dxw[index]
470
471        if index == 0:
472            text += "<index> \t<X> \t<Y> \t<dY> \t<d%s>\n" % x_st
473        text += "%s \t%s \t%s \t%s \t%s\n" % (index,
474                                                data.x[index],
475                                                data.y[index],
476                                                dy_val,
477                                                dx_val)
478    return text
479
480def retrieveData2d(data):
481    """
482    Retrieve 2D data from file and construct its text
483    representation
484    """
485    if not isinstance(data, Data2D):
486        msg = "Incorrect type passed to retrieveData2d"
487        raise AttributeError, msg
488
489    text = data.__str__()
490    text += 'Data Min Max:\n'
491    text += 'I_min = %s\n' % min(data.data)
492    text += 'I_max = %s\n\n' % max(data.data)
493    text += 'Data (First 2501) Points:\n'
494    text += 'Data columns include err(I).\n'
495    text += 'ASCII data starts here.\n'
496    text += "<index> \t<Qx> \t<Qy> \t<I> \t<dI> \t<dQparal> \t<dQperp>\n"
497    di_val = 0.0
498    dx_val = 0.0
499    dy_val = 0.0
500    len_data = len(data.qx_data)
501    for index in xrange(0, len_data):
502        x_val = data.qx_data[index]
503        y_val = data.qy_data[index]
504        i_val = data.data[index]
505        if data.err_data is not None:
506            di_val = data.err_data[index]
507        if data.dqx_data is not None:
508            dx_val = data.dqx_data[index]
509        if data.dqy_data is not None:
510            dy_val = data.dqy_data[index]
511
512        text += "%s \t%s \t%s \t%s \t%s \t%s \t%s\n" % (index,
513                                                        x_val,
514                                                        y_val,
515                                                        i_val,
516                                                        di_val,
517                                                        dx_val,
518                                                        dy_val)
519        # Takes too long time for typical data2d: Break here
520        if index >= 2500:
521            text += ".............\n"
522            break
523
524    return text
525
526def onTXTSave(data, path):
527    """
528    Save file as formatted txt
529    """
530    with open(path,'w') as out:
531        has_errors = True
532        if data.dy == None or data.dy == []:
533            has_errors = False
534        # Sanity check
535        if has_errors:
536            try:
537                if len(data.y) != len(data.dy):
538                    has_errors = False
539            except:
540                has_errors = False
541        if has_errors:
542            if data.dx is not None and data.dx != []:
543                out.write("<X>   <Y>   <dY>   <dX>\n")
544            else:
545                out.write("<X>   <Y>   <dY>\n")
546        else:
547            out.write("<X>   <Y>\n")
548
549        for i in range(len(data.x)):
550            if has_errors:
551                if data.dx is not None and data.dx != []:
552                    if  data.dx[i] != None:
553                        out.write("%g  %g  %g  %g\n" % (data.x[i],
554                                                        data.y[i],
555                                                        data.dy[i],
556                                                        data.dx[i]))
557                    else:
558                        out.write("%g  %g  %g\n" % (data.x[i],
559                                                    data.y[i],
560                                                    data.dy[i]))
561                else:
562                    out.write("%g  %g  %g\n" % (data.x[i],
563                                                data.y[i],
564                                                data.dy[i]))
565            else:
566                out.write("%g  %g\n" % (data.x[i],
567                                        data.y[i]))
568
569def saveData1D(data):
570    """
571    Save 1D data points
572    """
573    default_name = os.path.basename(data.filename)
574    default_name, extension = os.path.splitext(default_name)
575    if not extension:
576        extension = ".txt"
577    default_name += "_out" + extension
578
579    wildcard = "Text files (*.txt);;"\
580                "CanSAS 1D files(*.xml)"
581    kwargs = {
582        'caption'   : 'Save As',
583        'directory' : default_name,
584        'filter'    : wildcard,
585        'parent'    : None,
586    }
587    # Query user for filename.
588    filename = QtGui.QFileDialog.getSaveFileName(**kwargs)
589
590    # User cancelled.
591    if not filename:
592        return
593
594    filename = str(filename)
595
596    #Instantiate a loader
597    loader = Loader()
598    if os.path.splitext(filename)[1].lower() == ".txt":
599        onTXTSave(data, filename)
600    if os.path.splitext(filename)[1].lower() == ".xml":
601        loader.save(filename, data, ".xml")
602
603def saveData2D(data):
604    """
605    Save data2d dialog
606    """
607    default_name = os.path.basename(data.filename)
608    default_name, _ = os.path.splitext(default_name)
609    ext_format = ".dat"
610    default_name += "_out" + ext_format
611
612    wildcard = "IGOR/DAT 2D file in Q_map (*.dat)"
613    kwargs = {
614        'caption'   : 'Save As',
615        'directory' : default_name,
616        'filter'    : wildcard,
617        'parent'    : None,
618    }
619    # Query user for filename.
620    filename = QtGui.QFileDialog.getSaveFileName(**kwargs)
621
622    # User cancelled.
623    if not filename:
624        return
625    filename = str(filename)
626    #Instantiate a loader
627    loader = Loader()
628
629    if os.path.splitext(filename)[1].lower() == ext_format:
630        loader.save(filename, data, ext_format)
631
632class FormulaValidator(QtGui.QValidator):
633    def __init__(self, parent=None):
634        super(FormulaValidator, self).__init__(parent)
635 
636    def validate(self, input, pos):
637        try:
638            Formula(str(input))
639            self._setStyleSheet("")
640            return QtGui.QValidator.Acceptable, pos
641
642        except Exception as e:
643            self._setStyleSheet("background-color:pink;")
644            return QtGui.QValidator.Intermediate, pos
645
646    def _setStyleSheet(self, value):
647        try:
648            if self.parent():
649                self.parent().setStyleSheet(value)
650        except:
651            pass
652
653def xyTransform(data, xLabel="", yLabel=""):
654    """
655    Transforms x and y in View and set the scale
656    """
657    # Changing the scale might be incompatible with
658    # currently displayed data (for instance, going
659    # from ln to log when all plotted values have
660    # negative natural logs).
661    # Go linear and only change the scale at the end.
662    xscale = 'linear'
663    yscale = 'linear'
664    # Local data is either 1D or 2D
665    if data.id == 'fit':
666        return
667
668    # control axis labels from the panel itself
669    yname, yunits = data.get_yaxis()
670    xname, xunits = data.get_xaxis()
671
672    # Goes through all possible scales
673    # self.x_label is already wrapped with Latex "$", so using the argument
674
675    # X
676    if xLabel == "x":
677        data.transformX(DataTransform.toX, DataTransform.errToX)
678        xLabel = "%s(%s)" % (xname, xunits)
679    if xLabel == "x^(2)":
680        data.transformX(DataTransform.toX2, DataTransform.errToX2)
681        xunits = convertUnit(2, xunits)
682        xLabel = "%s^{2}(%s)" % (xname, xunits)
683    if xLabel == "x^(4)":
684        data.transformX(DataTransform.toX4, DataTransform.errToX4)
685        xunits = convertUnit(4, xunits)
686        xLabel = "%s^{4}(%s)" % (xname, xunits)
687    if xLabel == "ln(x)":
688        data.transformX(DataTransform.toLogX, DataTransform.errToLogX)
689        xLabel = "\ln{(%s)}(%s)" % (xname, xunits)
690    if xLabel == "log10(x)":
691        data.transformX(DataTransform.toX_pos, DataTransform.errToX_pos)
692        xscale = 'log'
693        xLabel = "%s(%s)" % (xname, xunits)
694    if xLabel == "log10(x^(4))":
695        data.transformX(DataTransform.toX4, DataTransform.errToX4)
696        xunits = convertUnit(4, xunits)
697        xLabel = "%s^{4}(%s)" % (xname, xunits)
698        xscale = 'log'
699
700    # Y
701    if yLabel == "ln(y)":
702        data.transformY(DataTransform.toLogX, DataTransform.errToLogX)
703        yLabel = "\ln{(%s)}(%s)" % (yname, yunits)
704    if yLabel == "y":
705        data.transformY(DataTransform.toX, DataTransform.errToX)
706        yLabel = "%s(%s)" % (yname, yunits)
707    if yLabel == "log10(y)":
708        data.transformY(DataTransform.toX_pos, DataTransform.errToX_pos)
709        yscale = 'log'
710        yLabel = "%s(%s)" % (yname, yunits)
711    if yLabel == "y^(2)":
712        data.transformY(DataTransform.toX2, DataTransform.errToX2)
713        yunits = convertUnit(2, yunits)
714        yLabel = "%s^{2}(%s)" % (yname, yunits)
715    if yLabel == "1/y":
716        data.transformY(DataTransform.toOneOverX, DataTransform.errOneOverX)
717        yunits = convertUnit(-1, yunits)
718        yLabel = "1/%s(%s)" % (yname, yunits)
719    if yLabel == "y*x^(2)":
720        data.transformY(DataTransform.toYX2, DataTransform.errToYX2)
721        xunits = convertUnit(2, xunits)
722        yLabel = "%s \ \ %s^{2}(%s%s)" % (yname, xname, yunits, xunits)
723    if yLabel == "y*x^(4)":
724        data.transformY(DataTransform.toYX4, DataTransform.errToYX4)
725        xunits = convertUnit(4, xunits)
726        yLabel = "%s \ \ %s^{4}(%s%s)" % (yname, xname, yunits, xunits)
727    if yLabel == "1/sqrt(y)":
728        data.transformY(DataTransform.toOneOverSqrtX, DataTransform.errOneOverSqrtX)
729        yunits = convertUnit(-0.5, yunits)
730        yLabel = "1/\sqrt{%s}(%s)" % (yname, yunits)
731    if yLabel == "ln(y*x)":
732        data.transformY(DataTransform.toLogXY, DataTransform.errToLogXY)
733        yLabel = "\ln{(%s \ \ %s)}(%s%s)" % (yname, xname, yunits, xunits)
734    if yLabel == "ln(y*x^(2))":
735        data.transformY(DataTransform.toLogYX2, DataTransform.errToLogYX2)
736        xunits = convertUnit(2, xunits)
737        yLabel = "\ln (%s \ \ %s^{2})(%s%s)" % (yname, xname, yunits, xunits)
738    if yLabel == "ln(y*x^(4))":
739        data.transformY(DataTransform.toLogYX4, DataTransform.errToLogYX4)
740        xunits = convertUnit(4, xunits)
741        yLabel = "\ln (%s \ \ %s^{4})(%s%s)" % (yname, xname, yunits, xunits)
742    if yLabel == "log10(y*x^(4))":
743        data.transformY(DataTransform.toYX4, DataTransform.errToYX4)
744        xunits = convertUnit(4, xunits)
745        yscale = 'log'
746        yLabel = "%s \ \ %s^{4}(%s%s)" % (yname, xname, yunits, xunits)
747
748    # Perform the transformation of data in data1d->View
749    data.transformView()
750
751    return (xLabel, yLabel, xscale, yscale)
752
753def dataFromItem(item):
754    """
755    Retrieve Data1D/2D component from QStandardItem.
756    The assumption - data stored in SasView standard, in child 0
757    """
758    return item.child(0).data().toPyObject()
759
760def formatNumber(value, high=False):
761    """
762    Return a float in a standardized, human-readable formatted string.
763    This is used to output readable (e.g. x.xxxe-y) values to the panel.
764    """
765    try:
766        value = float(value)
767    except:
768        output = "NaN"
769        return output.lstrip().rstrip()
770
771    if high:
772        output = "%-7.5g" % value
773
774    else:
775        output = "%-5.3g" % value
776    return output.lstrip().rstrip()
777
778def convertUnitToHTML(unit):
779    """
780    Convert ASCII unit display into well rendering HTML
781    """
782    if unit == "1/A":
783        return "&#x212B;<sup>-1</sup>"
784    elif unit == "1/cm":
785        return "cm<sup>-1</sup>"
786    elif unit == "Ang":
787        return "&#x212B;"
788    elif unit == "1e-6/Ang^2":
789        return "10<sup>-6</sup>/&#x212B;<sup>2</sup>"
790    elif unit == "inf":
791        return "&#x221e;"
792    elif unit == "-inf":
793        return "-&#x221e;"
794    else:
795        return unit
796
797def parseName(name, expression):
798    """
799    remove "_" in front of a name
800    """
801    if re.match(expression, name) is not None:
802        word = re.split(expression, name, 1)
803        for item in word:           
804            if item.lstrip().rstrip() != '':
805                return item
806    else:
807        return name
Note: See TracBrowser for help on using the repository browser.