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

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 f0bb711 was f0bb711, checked in by celinedurniak <celine.durniak@…>, 7 years ago

Implemented comments from review for Data Operation Panel (ESS-GUI-SasView?-245)

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