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

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

Partially revert last commit. Went too far.

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