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

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

Startup time improvements - hiding expensive imports and such

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