Source code for fsleyes.actions.importdataseries

#
# importdataseries.py - The ImportDataSeriesAction.
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""This module provides the :class:`ImportDataSeriesAction`, which is used by
:class:`.PlotPanel` views to import data series from a text file.
"""

import            os
import os.path as op
import numpy   as np

import fsleyes_widgets.numberdialog as numdlg
import fsl.data.image               as fslimage
import fsl.utils.settings           as fslsettings

import fsleyes.strings              as strings
import fsleyes.plotting             as plotting
import fsleyes.colourmaps           as fslcm


from . import base


[docs]class ImportDataSeriesAction(base.Action):
[docs] def __init__(self, overlayList, displayCtx, plotPanel): base.Action.__init__(self, overlayList, displayCtx, self.__doImport) self.__plotPanel = plotPanel
def __doImport(self): import wx frame = wx.GetApp().GetTopWindow() # Ask the user where to get the data msg = strings.messages[self, 'selectFile'] fromDir = fslsettings.read('loadSaveOverlayDir', os.getcwd()) dlg = wx.FileDialog(frame, message=msg, defaultDir=fromDir, style=wx.FD_OPEN) if dlg.ShowModal() != wx.ID_OK: return filePath = dlg.GetPath() fileName = op.basename(filePath) # Load the file, show an # error if it fails try: # Assuming that the data series # to plot are stored as columns data = np.loadtxt(filePath, dtype=np.float).T # Make sure the data is 2D, to # make code below easier and # happier. if len(data.shape) == 1: data = data.reshape((1, -1)) except Exception as e: title = strings.titles[ self, 'error'] msg = strings.messages[self, 'error'].format( filePath, '{}: {}'.format(type(e).__name__, str(e))) wx.MessageBox(msg, title, wx.ICON_ERROR | wx.OK) return fslsettings.write('loadSaveOverlayDir', filePath) # Ask the user the x axis scaling factor. # If the currently selected overlay is # Nifti and 4D, default to its pixdim[3] overlay = self.displayCtx.getSelectedOverlay() if overlay is not None and \ isinstance(overlay, fslimage.Nifti) and \ len(overlay.shape) == 4 and \ self.__plotPanel.usePixdim: xscale = overlay.pixdim[3] else: xscale = 1 title = strings.titles[ self, 'selectXScale'] msg = strings.messages[self, 'selectXScale'] # If the user pushes 'Ok', the entered value # is used as a fixed X axis interval. Otherwise, # it is assumed that the first column in the # file is the x axis data. dlg = numdlg.NumberDialog( frame, title=title, message=msg, initial=xscale, minValue=1e-5, cancelText=strings.labels[self, 'firstColumnIsX']) firstColumnIsX = dlg.ShowModal() != wx.ID_OK xscale = dlg.GetValue() # Add the data series series = [] if firstColumnIsX: xdata = data[0, :] ydata = data[1:, :] else: xdata = np.arange(0, data.shape[1] * xscale, xscale, dtype=np.float) ydata = data for i, ydata in enumerate(ydata): x = np.array(xdata) y = np.array(ydata) fin = np.isfinite(x) & np.isfinite(y) x = x[fin] y = y[fin] ds = plotting.DataSeries(None, self.overlayList, self.displayCtx, self.__plotPanel) ds.setData(x, y) # If we recognise the file name, # we can give it a useful label. label = strings.plotLabels.get( '{}.{}' .format(fileName, i), '{} [{}]'.format(fileName, i)) ds.label = label ds.lineWidth = 1 ds.colour = fslcm.randomDarkColour() series.append(ds) self.__plotPanel.dataSeries.extend(series)