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

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 2d0e0c1 was dc5ef15, checked in by Piotr Rozyczko <rozyczko@…>, 8 years ago

Removed qtgui dependency on sasgui and wx SASVIEW-590

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