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

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

SASVIEW-644: mapping between datasets and fit tabs

  • Property mode set to 100644
File size: 26.7 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
98if os.path.splitext(sys.argv[0])[1].lower() != ".py":
99     HELP_DIRECTORY_LOCATION = "doc"
100else:
101     HELP_DIRECTORY_LOCATION = "docs/sphinx-docs/build/html"
102IMAGES_DIRECTORY_LOCATION = HELP_DIRECTORY_LOCATION + "/_images"
103
104# GUI always starts from the App folder
105#os.chdir(PATH_APP)
106# Read in the local config, which can either be with the main
107# application or in the installation directory
108config = _find_local_config('local_config', PATH_APP)
109
110if config is None:
111    config = _find_local_config('local_config', os.getcwd())
112    #if config is None:
113    #    # Didn't find local config, load the default
114    #    import sas.sasgui.guiframe.config as config
115    #    #logging.info("using default local_config")
116    #else:
117    #    pass
118    #    #logging.info("found local_config in %s", os.getcwd())
119else:
120    pass
121    #logging.info("found local_config in %s", PATH_APP)
122
123c_conf_dir = CustomDir.setup_conf_dir(PATH_APP)
124
125custom_config = _find_local_config('custom_config', c_conf_dir)
126if custom_config is None:
127    custom_config = _find_local_config('custom_config', os.getcwd())
128    if custom_config is None:
129        msgConfig = "Custom_config file was not imported"
130        #logging.info(msgConfig)
131    else:
132        pass
133        #logging.info("using custom_config in %s", os.getcwd())
134else:
135    pass
136    #logging.info("using custom_config from %s", c_conf_dir)
137
138#read some constants from config
139APPLICATION_STATE_EXTENSION = config.APPLICATION_STATE_EXTENSION
140APPLICATION_NAME = config.__appname__
141SPLASH_SCREEN_PATH = config.SPLASH_SCREEN_PATH
142WELCOME_PANEL_ON = config.WELCOME_PANEL_ON
143SPLASH_SCREEN_WIDTH = config.SPLASH_SCREEN_WIDTH
144SPLASH_SCREEN_HEIGHT = config.SPLASH_SCREEN_HEIGHT
145SS_MAX_DISPLAY_TIME = config.SS_MAX_DISPLAY_TIME
146if not WELCOME_PANEL_ON:
147    WELCOME_PANEL_SHOW = False
148else:
149    WELCOME_PANEL_SHOW = True
150try:
151    DATALOADER_SHOW = custom_config.DATALOADER_SHOW
152    TOOLBAR_SHOW = custom_config.TOOLBAR_SHOW
153    FIXED_PANEL = custom_config.FIXED_PANEL
154    if WELCOME_PANEL_ON:
155        WELCOME_PANEL_SHOW = custom_config.WELCOME_PANEL_SHOW
156    PLOPANEL_WIDTH = custom_config.PLOPANEL_WIDTH
157    DATAPANEL_WIDTH = custom_config.DATAPANEL_WIDTH
158    GUIFRAME_WIDTH = custom_config.GUIFRAME_WIDTH
159    GUIFRAME_HEIGHT = custom_config.GUIFRAME_HEIGHT
160    CONTROL_WIDTH = custom_config.CONTROL_WIDTH
161    CONTROL_HEIGHT = custom_config.CONTROL_HEIGHT
162    DEFAULT_PERSPECTIVE = custom_config.DEFAULT_PERSPECTIVE
163    CLEANUP_PLOT = custom_config.CLEANUP_PLOT
164    # custom open_path
165    open_folder = custom_config.DEFAULT_OPEN_FOLDER
166    if open_folder != None and os.path.isdir(open_folder):
167        DEFAULT_OPEN_FOLDER = os.path.abspath(open_folder)
168    else:
169        DEFAULT_OPEN_FOLDER = PATH_APP
170except AttributeError:
171    DATALOADER_SHOW = True
172    TOOLBAR_SHOW = True
173    FIXED_PANEL = True
174    WELCOME_PANEL_SHOW = False
175    PLOPANEL_WIDTH = config.PLOPANEL_WIDTH
176    DATAPANEL_WIDTH = config.DATAPANEL_WIDTH
177    GUIFRAME_WIDTH = config.GUIFRAME_WIDTH
178    GUIFRAME_HEIGHT = config.GUIFRAME_HEIGHT
179    CONTROL_WIDTH = -1
180    CONTROL_HEIGHT = -1
181    DEFAULT_PERSPECTIVE = None
182    CLEANUP_PLOT = False
183    DEFAULT_OPEN_FOLDER = PATH_APP
184
185#DEFAULT_STYLE = config.DEFAULT_STYLE
186
187PLUGIN_STATE_EXTENSIONS = config.PLUGIN_STATE_EXTENSIONS
188OPEN_SAVE_MENU = config.OPEN_SAVE_PROJECT_MENU
189VIEW_MENU = config.VIEW_MENU
190EDIT_MENU = config.EDIT_MENU
191extension_list = []
192if APPLICATION_STATE_EXTENSION is not None:
193    extension_list.append(APPLICATION_STATE_EXTENSION)
194EXTENSIONS = PLUGIN_STATE_EXTENSIONS + extension_list
195try:
196    PLUGINS_WLIST = '|'.join(config.PLUGINS_WLIST)
197except AttributeError:
198    PLUGINS_WLIST = ''
199APPLICATION_WLIST = config.APPLICATION_WLIST
200IS_WIN = True
201IS_LINUX = False
202CLOSE_SHOW = True
203TIME_FACTOR = 2
204NOT_SO_GRAPH_LIST = ["BoxSum"]
205
206class Communicate(QtCore.QObject):
207    """
208    Utility class for tracking of the Qt signals
209    """
210    # File got successfully read
211    fileReadSignal = QtCore.pyqtSignal(list)
212
213    # Open File returns "list" of paths
214    fileDataReceivedSignal = QtCore.pyqtSignal(dict)
215
216    # Update Main window status bar with "str"
217    # Old "StatusEvent"
218    statusBarUpdateSignal = QtCore.pyqtSignal(str)
219
220    # Send data to the current perspective
221    updatePerspectiveWithDataSignal = QtCore.pyqtSignal(list)
222
223    # New data in current perspective
224    updateModelFromPerspectiveSignal = QtCore.pyqtSignal(QtGui.QStandardItem)
225
226    # New theory data in current perspective
227    updateTheoryFromPerspectiveSignal = QtCore.pyqtSignal(QtGui.QStandardItem)
228
229    # New plot requested from the GUI manager
230    # Old "NewPlotEvent"
231    plotRequestedSignal = QtCore.pyqtSignal(list)
232
233    # Plot update requested from a perspective
234    plotUpdateSignal = QtCore.pyqtSignal(list)
235
236    # Progress bar update value
237    progressBarUpdateSignal = QtCore.pyqtSignal(int)
238
239    # Workspace charts added/removed
240    activeGraphsSignal = QtCore.pyqtSignal(list)
241
242    # Current workspace chart's name changed
243    activeGraphName = QtCore.pyqtSignal(tuple)
244
245    # Current perspective changed
246    perspectiveChangedSignal = QtCore.pyqtSignal(str)
247
248    # File/dataset got deleted
249    dataDeletedSignal = QtCore.pyqtSignal(list)
250
251
252def updateModelItemWithPlot(item, update_data, name=""):
253    """
254    Adds a checkboxed row named "name" to QStandardItem
255    Adds QVariant 'update_data' to that row.
256    """
257    assert isinstance(item, QtGui.QStandardItem)
258    assert isinstance(update_data, QtCore.QVariant)
259    py_update_data = update_data.toPyObject()
260
261    # Check if data with the same ID is already present
262    for index in range(item.rowCount()):
263        plot_item = item.child(index)
264        if plot_item.isCheckable():
265            plot_data = plot_item.child(0).data().toPyObject()
266            if plot_data.id is not None and plot_data.id == py_update_data.id:
267                # replace data section in item
268                plot_item.child(0).setData(update_data)
269                plot_item.setText(name)
270                # Plot title
271                plot_item.child(1).child(0).setText("Title: %s"%name)
272                # Force redisplay
273                return
274
275    # Create the new item
276    checkbox_item = createModelItemWithPlot(update_data, name)
277
278    # Append the new row to the main item
279    item.appendRow(checkbox_item)
280
281def createModelItemWithPlot(update_data, name=""):
282    """
283    Creates a checkboxed QStandardItem named "name"
284    Adds QVariant 'update_data' to that row.
285    """
286    assert isinstance(update_data, QtCore.QVariant)
287    py_update_data = update_data.toPyObject()
288
289    checkbox_item = QtGui.QStandardItem()
290    checkbox_item.setCheckable(True)
291    checkbox_item.setCheckState(QtCore.Qt.Checked)
292    checkbox_item.setText(name)
293
294    # Add "Info" item
295    if isinstance(py_update_data, (Data1D, Data2D)):
296        # If Data1/2D added - extract Info from it
297        info_item = infoFromData(py_update_data)
298    else:
299        # otherwise just add a naked item
300        info_item = QtGui.QStandardItem("Info")
301
302    # Add the actual Data1D/Data2D object
303    object_item = QtGui.QStandardItem()
304    object_item.setData(update_data)
305
306    # Set the data object as the first child
307    checkbox_item.setChild(0, object_item)
308
309    # Set info_item as the second child
310    checkbox_item.setChild(1, info_item)
311
312    # And return the newly created item
313    return checkbox_item
314
315def updateModelItem(item, update_data, name=""):
316    """
317    Adds a simple named child to QStandardItem
318    """
319    assert isinstance(item, QtGui.QStandardItem)
320    assert isinstance(update_data, list)
321
322    # Add the actual Data1D/Data2D object
323    object_item = QtGui.QStandardItem()
324    object_item.setText(name)
325    object_item.setData(QtCore.QVariant(update_data))
326
327    # Append the new row to the main item
328    item.appendRow(object_item)
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, basestring)
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 = urlparse.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 != 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 != None and len(data.dy) > index:
457            dy_val = data.dy[index]
458        else:
459            dy_val = 0.0
460        if data.dx != None and len(data.dx) > index:
461            dx_val = data.dx[index]
462        else:
463            dx_val = 0.0
464        if data.dxl != None and len(data.dxl) > index:
465            if index == 0:
466                x_st = "Xl"
467            dx_val = data.dxl[index]
468        elif data.dxw != 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 xrange(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 != None:
508            di_val = data.err_data[index]
509        if data.dqx_data != None:
510            dx_val = data.dqx_data[index]
511        if data.dqy_data != 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 != 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 != 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    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.