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

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

Unit tests for fitting options dialog SASVIEW-514

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