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

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 6ff2eb3 was 6ff2eb3, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

Magnetic angles image widget

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