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

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

Fixed pyinstaller build

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