Module audian.timeaxisitem

Classes

class TimeAxisItem (file_times, *args, **kwargs)
Expand source code
class TimeAxisItem(pg.AxisItem):
    
    def __init__(self, file_times, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setPen('white')
        self._file_times = file_times
        self._starttime = None
        self._starttime_mode = 0


    def setLogMode(self, *args, **kwargs):
        # no log mode!
        pass


    def set_start_time(self, time):
        """ Set time of first data element.

        Parameters
        ----------
        time: datetime or None
            A datetime object for the data and time of the first data element. 
        """
        self._starttime = time
        self.enableAutoSIPrefix(self._starttime is None or
                                self._starttime_mode == 0)


    def set_starttime_mode(self, mode):
        self._starttime_mode = mode
        self.enableAutoSIPrefix(self._starttime is None or
                                self._starttime_mode == 0)


    def tickSpacing(self, minVal, maxVal, size):
        diff = abs(maxVal - minVal)
        if diff == 0:
            return []

        if self._starttime_mode == 2:
            min_idx = np.nonzero(self._file_times <= minVal)[0][-1]
            max_idx = np.nonzero(self._file_times <= maxVal)[0][-1]
            if min_idx != max_idx:
                max_value = self._file_times[max_idx] - self._file_times[min_idx]
            else:
                max_value = maxVal - self._file_times[max_idx]
        else:
            max_value = maxVal

        # estimate width of xtick labels:
        xwidth = QFontMetrics(self.font()).averageCharWidth()
        if self._starttime and self._starttime_mode == 1:
            nx = 8
        elif max_value < 1.0:
            nx = 0
        elif max_value >= 3600:
            nx = 8
        elif max_value >= 60:
            nx = 5
        else:
            nx = 2
        spacing = diff/5
        if spacing < 0.00001:
            nx += 7
        elif spacing < 0.0001:
            nx += 6
        elif spacing < 0.001:
            nx += 5
        elif spacing < 1.0:
            nx += 4
        nx += 4

        # minimum spacing:
        max_ticks = max(2, int(size / (nx*xwidth)))
        min_spacing = diff / max_ticks
        p10unit = 10 ** floor(log10(min_spacing))

        # major ticks:
        factors = [1.0, 2.0, 5.0, 10.0, 20.0, 50.0, 100.0]
        for fac in factors:
            spacing = fac * p10unit
            if spacing >= min_spacing:
                break

        # minor ticks:
        factors = [100.0, 10.0, 1.0, 0.1]
        for fac in factors:
            minor_spacing = fac * p10unit
            if minor_spacing < spacing:
                break
            
        return [(spacing, 0), (minor_spacing, 0)]

    
    def tickStrings(self, values, scale, spacing):
        if len(values) == 0:
            return []
        
        if scale > 1:
            self.setLabel('Time', units='s')
            return [f'{v*scale:.5g}' for v in values]

        if self._starttime_mode == 2:
            vals = []
            for time in values:
                toffs = self._file_times[np.nonzero(self._file_times <= time)[0][-1]]
                vals.append(time - toffs)
            values = vals
        max_value = np.max(values)

        if (self._starttime and self._starttime_mode == 1) or \
           max_value > 3600:
            self.setLabel('Time (h:m:s)', units=None)
            fs = '{hours:.0f}:{mins:02.0f}:{secs:02.0f}'
        elif max_value > 60:
            self.setLabel('Time (m:s)', units=None)
            fs = '{mins:.0f}:{secs:02.0f}'
        else:
            self.setLabel('Time', units='s')
            fs = '{secs:.0f}'
        if spacing < 1:
            fs += '.{micros}'
        
        basetime = dt.datetime(1, 1, 1, 0, 0, 0, 0)
        if self._starttime and self._starttime_mode == 1:
            basetime = self._starttime
        vals = []
        for time in values:
            t = basetime + dt.timedelta(seconds=time)
            if spacing < 0.00001:
                micros = f'{1.0*t.microsecond:06.0f}'
            elif spacing < 0.0001:
                micros = f'{0.1*t.microsecond:05.0f}'
            elif spacing < 0.001:
                micros = f'{0.01*t.microsecond:04.0f}'
            else:
                micros = f'{0.001*t.microsecond:03.0f}'
            time = dict(hours=t.hour, mins=t.minute, secs=t.second,
                        micros=micros)
            vals.append(fs.format(**time))
        return vals

GraphicsItem showing a single plot axis with ticks, values, and label. Can be configured to fit on any side of a plot, Can automatically synchronize its displayed scale with ViewBox items. Ticks can be extended to draw a grid. If maxTickLength is negative, ticks point into the plot.

=============== =============================================================== Arguments: orientation one of 'left', 'right', 'top', or 'bottom' maxTickLength (px) maximum length of ticks to draw. Negative values draw into the plot, positive values draw outward. linkView (ViewBox) causes the range of values displayed in the axis to be linked to the visible range of a ViewBox. showValues (bool) Whether to display values adjacent to ticks pen (QPen) Pen used when drawing axis and (by default) ticks textPen (QPen) Pen used when drawing tick labels. tickPen (QPen) Pen used when drawing ticks. text The text (excluding units) to display on the label for this axis. units The units for this axis. Units should generally be given without any scaling prefix (eg, 'V' instead of 'mV'). The scaling prefix will be automatically prepended based on the range of data displayed. args All extra keyword arguments become CSS style options for the tag which will surround the axis label and units. =============== ===============================================================

Ancestors

  • pyqtgraph.graphicsItems.AxisItem.AxisItem
  • pyqtgraph.graphicsItems.GraphicsWidget.GraphicsWidget
  • pyqtgraph.graphicsItems.GraphicsItem.GraphicsItem
  • PyQt5.QtWidgets.QGraphicsWidget
  • PyQt5.QtWidgets.QGraphicsObject
  • PyQt5.QtCore.QObject
  • PyQt5.QtWidgets.QGraphicsItem
  • PyQt5.QtWidgets.QGraphicsLayoutItem
  • sip.wrapper
  • sip.simplewrapper

Methods

def setLogMode(self, *args, **kwargs)
Expand source code
def setLogMode(self, *args, **kwargs):
    # no log mode!
    pass

Set log scaling for x and/or y axes.

If two positional arguments are provided, the first will set log scaling for the x axis and the second for the y axis. If a single positional argument is provided, it will set the log scaling along the direction of the AxisItem. Alternatively, x and y can be passed as keyword arguments.

If an axis is set to log scale, ticks are displayed on a logarithmic scale and values are adjusted accordingly. (This is usually accessed by changing the log mode of a :func:PlotItem <pyqtgraph.PlotItem.setLogMode>.) The linked ViewBox will be informed of the change.

def set_start_time(self, time)
Expand source code
def set_start_time(self, time):
    """ Set time of first data element.

    Parameters
    ----------
    time: datetime or None
        A datetime object for the data and time of the first data element. 
    """
    self._starttime = time
    self.enableAutoSIPrefix(self._starttime is None or
                            self._starttime_mode == 0)

Set time of first data element.

Parameters

time : datetime or None
A datetime object for the data and time of the first data element.
def set_starttime_mode(self, mode)
Expand source code
def set_starttime_mode(self, mode):
    self._starttime_mode = mode
    self.enableAutoSIPrefix(self._starttime is None or
                            self._starttime_mode == 0)
def tickSpacing(self, minVal, maxVal, size)
Expand source code
def tickSpacing(self, minVal, maxVal, size):
    diff = abs(maxVal - minVal)
    if diff == 0:
        return []

    if self._starttime_mode == 2:
        min_idx = np.nonzero(self._file_times <= minVal)[0][-1]
        max_idx = np.nonzero(self._file_times <= maxVal)[0][-1]
        if min_idx != max_idx:
            max_value = self._file_times[max_idx] - self._file_times[min_idx]
        else:
            max_value = maxVal - self._file_times[max_idx]
    else:
        max_value = maxVal

    # estimate width of xtick labels:
    xwidth = QFontMetrics(self.font()).averageCharWidth()
    if self._starttime and self._starttime_mode == 1:
        nx = 8
    elif max_value < 1.0:
        nx = 0
    elif max_value >= 3600:
        nx = 8
    elif max_value >= 60:
        nx = 5
    else:
        nx = 2
    spacing = diff/5
    if spacing < 0.00001:
        nx += 7
    elif spacing < 0.0001:
        nx += 6
    elif spacing < 0.001:
        nx += 5
    elif spacing < 1.0:
        nx += 4
    nx += 4

    # minimum spacing:
    max_ticks = max(2, int(size / (nx*xwidth)))
    min_spacing = diff / max_ticks
    p10unit = 10 ** floor(log10(min_spacing))

    # major ticks:
    factors = [1.0, 2.0, 5.0, 10.0, 20.0, 50.0, 100.0]
    for fac in factors:
        spacing = fac * p10unit
        if spacing >= min_spacing:
            break

    # minor ticks:
    factors = [100.0, 10.0, 1.0, 0.1]
    for fac in factors:
        minor_spacing = fac * p10unit
        if minor_spacing < spacing:
            break
        
    return [(spacing, 0), (minor_spacing, 0)]

Return values describing the desired spacing and offset of ticks.

This method is called whenever the axis needs to be redrawn and is a good method to override in subclasses that require control over tick locations.

The return value must be a list of tuples, one for each set of ticks::

[
    (major tick spacing, offset),
    (minor tick spacing, offset),
    (sub-minor tick spacing, offset),
    ...
]
def tickStrings(self, values, scale, spacing)
Expand source code
def tickStrings(self, values, scale, spacing):
    if len(values) == 0:
        return []
    
    if scale > 1:
        self.setLabel('Time', units='s')
        return [f'{v*scale:.5g}' for v in values]

    if self._starttime_mode == 2:
        vals = []
        for time in values:
            toffs = self._file_times[np.nonzero(self._file_times <= time)[0][-1]]
            vals.append(time - toffs)
        values = vals
    max_value = np.max(values)

    if (self._starttime and self._starttime_mode == 1) or \
       max_value > 3600:
        self.setLabel('Time (h:m:s)', units=None)
        fs = '{hours:.0f}:{mins:02.0f}:{secs:02.0f}'
    elif max_value > 60:
        self.setLabel('Time (m:s)', units=None)
        fs = '{mins:.0f}:{secs:02.0f}'
    else:
        self.setLabel('Time', units='s')
        fs = '{secs:.0f}'
    if spacing < 1:
        fs += '.{micros}'
    
    basetime = dt.datetime(1, 1, 1, 0, 0, 0, 0)
    if self._starttime and self._starttime_mode == 1:
        basetime = self._starttime
    vals = []
    for time in values:
        t = basetime + dt.timedelta(seconds=time)
        if spacing < 0.00001:
            micros = f'{1.0*t.microsecond:06.0f}'
        elif spacing < 0.0001:
            micros = f'{0.1*t.microsecond:05.0f}'
        elif spacing < 0.001:
            micros = f'{0.01*t.microsecond:04.0f}'
        else:
            micros = f'{0.001*t.microsecond:03.0f}'
        time = dict(hours=t.hour, mins=t.minute, secs=t.second,
                    micros=micros)
        vals.append(fs.format(**time))
    return vals

Return the strings that should be placed next to ticks. This method is called when redrawing the axis and is a good method to override in subclasses. The method is called with a list of tick values, a scaling factor (see below), and the spacing between ticks (this is required since, in some instances, there may be only one tick and thus no other way to determine the tick spacing)

The scale argument is used when the axis label is displaying units which may have an SI scaling prefix. When determining the text to display, use value*scale to correctly account for this prefix. For example, if the axis label's units are set to 'V', then a tick value of 0.001 might be accompanied by a scale value of 1000. This indicates that the label is displaying 'mV', and thus the tick should display 0.001 * 1000 = 1.