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

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

Assure default file for saving has an extension

  • Property mode set to 100644
File size: 26.2 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    if not extension:
559        extension = ".txt"
560    default_name += "_out" + extension
561
562    wildcard = "Text files (*.txt);;"\
563                "CanSAS 1D files(*.xml)"
564    kwargs = {
565        'caption'   : 'Save As',
566        'directory' : default_name,
567        'filter'    : wildcard,
568        'parent'    : None,
569    }
570    # Query user for filename.
571    filename = QtGui.QFileDialog.getSaveFileName(**kwargs)
572
573    # User cancelled.
574    if not filename:
575        return
576
577    filename = str(filename)
578
579    #Instantiate a loader
580    loader = Loader()
581    if os.path.splitext(filename)[1].lower() == ".txt":
582        onTXTSave(data, filename)
583    if os.path.splitext(filename)[1].lower() == ".xml":
584        loader.save(filename, data, ".xml")
585
586def saveData2D(data):
587    """
588    Save data2d dialog
589    """
590    default_name = os.path.basename(data.filename)
591    default_name, _ = os.path.splitext(default_name)
592    ext_format = ".dat"
593    default_name += "_out" + ext_format
594
595    wildcard = "IGOR/DAT 2D file in Q_map (*.dat)"
596    kwargs = {
597        'caption'   : 'Save As',
598        'directory' : default_name,
599        'filter'    : wildcard,
600        'parent'    : None,
601    }
602    # Query user for filename.
603    filename = QtGui.QFileDialog.getSaveFileName(**kwargs)
604
605    # User cancelled.
606    if not filename:
607        return
608    filename = str(filename)
609    #Instantiate a loader
610    loader = Loader()
611
612    if os.path.splitext(filename)[1].lower() == ext_format:
613        loader.save(filename, data, ext_format)
614
615class FormulaValidator(QtGui.QValidator):
616    def __init__(self, parent=None):
617        super(FormulaValidator, self).__init__(parent)
618 
619    def validate(self, input, pos):
620        try:
621            Formula(str(input))
622            self._setStyleSheet("")
623            return QtGui.QValidator.Acceptable, pos
624
625        except Exception as e:
626            self._setStyleSheet("background-color:pink;")
627            return QtGui.QValidator.Intermediate, pos
628
629    def _setStyleSheet(self, value):
630        try:
631            if self.parent():
632                self.parent().setStyleSheet(value)
633        except:
634            pass
635
636def xyTransform(data, xLabel="", yLabel=""):
637    """
638    Transforms x and y in View and set the scale
639    """
640    # Changing the scale might be incompatible with
641    # currently displayed data (for instance, going
642    # from ln to log when all plotted values have
643    # negative natural logs).
644    # Go linear and only change the scale at the end.
645    xscale = 'linear'
646    yscale = 'linear'
647    # Local data is either 1D or 2D
648    if data.id == 'fit':
649        return
650
651    # control axis labels from the panel itself
652    yname, yunits = data.get_yaxis()
653    xname, xunits = data.get_xaxis()
654
655    # Goes through all possible scales
656    # self.x_label is already wrapped with Latex "$", so using the argument
657
658    # X
659    if xLabel == "x":
660        data.transformX(DataTransform.toX, DataTransform.errToX)
661        xLabel = "%s(%s)" % (xname, xunits)
662    if xLabel == "x^(2)":
663        data.transformX(DataTransform.toX2, DataTransform.errToX2)
664        xunits = convertUnit(2, xunits)
665        xLabel = "%s^{2}(%s)" % (xname, xunits)
666    if xLabel == "x^(4)":
667        data.transformX(DataTransform.toX4, DataTransform.errToX4)
668        xunits = convertUnit(4, xunits)
669        xLabel = "%s^{4}(%s)" % (xname, xunits)
670    if xLabel == "ln(x)":
671        data.transformX(DataTransform.toLogX, DataTransform.errToLogX)
672        xLabel = "\ln{(%s)}(%s)" % (xname, xunits)
673    if xLabel == "log10(x)":
674        data.transformX(DataTransform.toX_pos, DataTransform.errToX_pos)
675        xscale = 'log'
676        xLabel = "%s(%s)" % (xname, xunits)
677    if xLabel == "log10(x^(4))":
678        data.transformX(DataTransform.toX4, DataTransform.errToX4)
679        xunits = convertUnit(4, xunits)
680        xLabel = "%s^{4}(%s)" % (xname, xunits)
681        xscale = 'log'
682
683    # Y
684    if yLabel == "ln(y)":
685        data.transformY(DataTransform.toLogX, DataTransform.errToLogX)
686        yLabel = "\ln{(%s)}(%s)" % (yname, yunits)
687    if yLabel == "y":
688        data.transformY(DataTransform.toX, DataTransform.errToX)
689        yLabel = "%s(%s)" % (yname, yunits)
690    if yLabel == "log10(y)":
691        data.transformY(DataTransform.toX_pos, DataTransform.errToX_pos)
692        yscale = 'log'
693        yLabel = "%s(%s)" % (yname, yunits)
694    if yLabel == "y^(2)":
695        data.transformY(DataTransform.toX2, DataTransform.errToX2)
696        yunits = convertUnit(2, yunits)
697        yLabel = "%s^{2}(%s)" % (yname, yunits)
698    if yLabel == "1/y":
699        data.transformY(DataTransform.toOneOverX, DataTransform.errOneOverX)
700        yunits = convertUnit(-1, yunits)
701        yLabel = "1/%s(%s)" % (yname, yunits)
702    if yLabel == "y*x^(2)":
703        data.transformY(DataTransform.toYX2, DataTransform.errToYX2)
704        xunits = convertUnit(2, xunits)
705        yLabel = "%s \ \ %s^{2}(%s%s)" % (yname, xname, yunits, xunits)
706    if yLabel == "y*x^(4)":
707        data.transformY(DataTransform.toYX4, DataTransform.errToYX4)
708        xunits = convertUnit(4, xunits)
709        yLabel = "%s \ \ %s^{4}(%s%s)" % (yname, xname, yunits, xunits)
710    if yLabel == "1/sqrt(y)":
711        data.transformY(DataTransform.toOneOverSqrtX, DataTransform.errOneOverSqrtX)
712        yunits = convertUnit(-0.5, yunits)
713        yLabel = "1/\sqrt{%s}(%s)" % (yname, yunits)
714    if yLabel == "ln(y*x)":
715        data.transformY(DataTransform.toLogXY, DataTransform.errToLogXY)
716        yLabel = "\ln{(%s \ \ %s)}(%s%s)" % (yname, xname, yunits, xunits)
717    if yLabel == "ln(y*x^(2))":
718        data.transformY(DataTransform.toLogYX2, DataTransform.errToLogYX2)
719        xunits = convertUnit(2, xunits)
720        yLabel = "\ln (%s \ \ %s^{2})(%s%s)" % (yname, xname, yunits, xunits)
721    if yLabel == "ln(y*x^(4))":
722        data.transformY(DataTransform.toLogYX4, DataTransform.errToLogYX4)
723        xunits = convertUnit(4, xunits)
724        yLabel = "\ln (%s \ \ %s^{4})(%s%s)" % (yname, xname, yunits, xunits)
725    if yLabel == "log10(y*x^(4))":
726        data.transformY(DataTransform.toYX4, DataTransform.errToYX4)
727        xunits = convertUnit(4, xunits)
728        yscale = 'log'
729        yLabel = "%s \ \ %s^{4}(%s%s)" % (yname, xname, yunits, xunits)
730
731    # Perform the transformation of data in data1d->View
732    data.transformView()
733
734    return (xLabel, yLabel, xscale, yscale)
735
736def dataFromItem(item):
737    """
738    Retrieve Data1D/2D component from QStandardItem.
739    The assumption - data stored in SasView standard, in child 0
740    """
741    return item.child(0).data().toPyObject()
742
743def formatNumber(value, high=False):
744    """
745    Return a float in a standardized, human-readable formatted string.
746    This is used to output readable (e.g. x.xxxe-y) values to the panel.
747    """
748    try:
749        value = float(value)
750    except:
751        output = "NaN"
752        return output.lstrip().rstrip()
753
754    if high:
755        output = "%-7.5g" % value
756
757    else:
758        output = "%-5.3g" % value
759    return output.lstrip().rstrip()
760
761def convertUnitToHTML(unit):
762    """
763    Convert ASCII unit display into well rendering HTML
764    """
765    if unit == "1/A":
766        return "&#x212B;<sup>-1</sup>"
767    elif unit == "1/cm":
768        return "cm<sup>-1</sup>"
769    elif unit == "Ang":
770        return "&#x212B;"
771    elif unit == "1e-6/Ang^2":
772        return "10<sup>-6</sup>/&#x212B;<sup>2</sup>"
773    elif unit == "inf":
774        return "&#x221e;"
775    elif unit == "-inf":
776        return "-&#x221e;"
777    else:
778        return unit
779
780def parseName(name, expression):
781    """
782    remove "_" in front of a name
783    """
784    if re.match(expression, name) is not None:
785        word = re.split(expression, name, 1)
786        for item in word:           
787            if item.lstrip().rstrip() != '':
788                return item
789    else:
790        return name
Note: See TracBrowser for help on using the repository browser.