Skip to content

Commit

Permalink
clean-up layout
Browse files Browse the repository at this point in the history
  • Loading branch information
bimac committed Dec 19, 2024
1 parent b48184d commit 20a1f18
Showing 1 changed file with 48 additions and 46 deletions.
94 changes: 48 additions & 46 deletions iblrig/gui/online_plots.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import ctypes
import json
import os
from collections.abc import Iterable
from pathlib import Path
from typing import Any

Expand All @@ -23,7 +24,6 @@
)
from qtpy.QtGui import QColor, QFont, QIcon, QLinearGradient, QPainter, QPixmap, QTransform
from qtpy.QtWidgets import (
QAbstractItemView,
QApplication,
QFrame,
QGraphicsRectItem,
Expand Down Expand Up @@ -59,7 +59,7 @@ def __init__(self, *args, **kwargs):
self.plotItem.getAxis(axis).setTextPen('k')


class SingleBarChart(PlotWidget):
class SingleBarChartWidget(PlotWidget):
"""A bar chart with a single column"""

def __init__(self, *args, barBrush='k', **kwargs):
Expand All @@ -78,6 +78,33 @@ def setValue(self, value: float):
self._barGraphItem.setOpts(height=value)


class FunctionWidget(PlotWidget):
"""A widget for psychometric and chronometric functions"""

def __init__(self, *args, colors: pg.ColorMap, probabilities: Iterable[float], **kwargs):
super().__init__(*args, **kwargs)
self.plotItem.addItem(pg.InfiniteLine(0, 90, 'black'))
for axis in ('left', 'bottom'):
self.plotItem.getAxis(axis).setGrid(128)
self.plotItem.getAxis(axis).setTextPen('k')
self.plotItem.getAxis('bottom').setLabel('Signed Contrast')
self.plotItem.setXRange(-1, 1, padding=0.05)
legend = pg.LegendItem(pen='lightgray', brush='w', offset=(45, 35), verSpacing=-5, labelTextColor='k')
legend.setParentItem(self.plotItem.graphicsItem())
legend.setZValue(1)
self.plotDataItems = dict()
for idx, probability in enumerate(probabilities):
self.plotDataItems[probability] = self.plotItem.plot(connect='all')
color = colors.getByIndex(idx)
self.plotDataItems[probability].setData(x=[1, np.NAN], y=[np.NAN, 1])
self.plotDataItems[probability].setPen(pg.mkPen(color=color, width=2))
self.plotDataItems[probability].setSymbol('o')
self.plotDataItems[probability].setSymbolPen(color)
self.plotDataItems[probability].setSymbolBrush(color)
self.plotDataItems[probability].setSymbolSize(5)
legend.addItem(self.plotDataItems[probability], f'p = {probability:0.1f}')


class TrialsTableModel(DataFrameTableModel):
"""A table model that displays status tips for entries in the trials table."""

Expand Down Expand Up @@ -544,56 +571,29 @@ def __init__(self, raw_data_folder: DirectoryPath, parent: QObject | None = None
subtitle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
layout.addWidget(subtitle, 1, 0, 1, 3)

# trial data
# trial history
self.trials = TrialsWidget(self, self.model.table_model)
self.trials.trialSelected.connect(self.model.setCurrentTrial)
layout.addWidget(self.trials, 2, 0, 2, 1)

# properties common to psychometric/chronometric functions
def common_function_props(plot_widget: pg.PlotWidget) -> dict[Any, pg.PlotDataItem]:
plot_item = plot_widget.plotItem
plot_item.addItem(pg.InfiniteLine(0, 90, 'black'))
for axis in ('left', 'bottom'):
plot_item.getAxis(axis).setGrid(128)
plot_item.getAxis(axis).setTextPen('k')
plot_item.getAxis('bottom').setLabel('Signed Contrast')
plot_item.setXRange(-1, 1, padding=0.05)
legend = pg.LegendItem(pen='lightgray', brush='w', offset=(45, 35), verSpacing=-5, labelTextColor='k')
legend.setParentItem(plot_item.graphicsItem())
legend.setZValue(1)
plot_data_items = dict()
for idx, probability in enumerate(self.model.probability_set):
plot_data_items[probability] = plot_item.plot(connect='all')
color = self.colormap.getByIndex(idx)
plot_data_items[probability].setData(x=[1, np.NAN], y=[np.NAN, 1])
plot_data_items[probability].setPen(pg.mkPen(color=color, width=2))
plot_data_items[probability].setSymbol('o')
plot_data_items[probability].setSymbolPen(color)
plot_data_items[probability].setSymbolBrush(color)
plot_data_items[probability].setSymbolSize(5)
legend.addItem(plot_data_items[probability], f'p = {probability:0.1f}')
return plot_data_items

# psychometric function
self.psychometricFunction = PlotWidget(parent=self)
layout.addWidget(self.psychometricFunction, 2, 1, 1, 1)
self.psychometricFunction.plotItem.setTitle('Psychometric Function', color='k')
self.psychometricFunction.plotItem.getAxis('left').setLabel('Rightward Choices (%)')
self.psychometricFunction.plotItem.setYRange(0, 1, padding=0.05)
self.psychometricFunction.plotItem.addItem(pg.InfiniteLine(0.5, 0, 'black'))
self.psychometricPlots = common_function_props(self.psychometricFunction)
self.psychometricWidget = FunctionWidget(parent=self, colors=self.colormap, probabilities=self.model.probability_set)
self.psychometricWidget.plotItem.setTitle('Psychometric Function', color='k')
self.psychometricWidget.plotItem.getAxis('left').setLabel('Rightward Choices (%)')
self.psychometricWidget.plotItem.addItem(pg.InfiniteLine(0.5, 0, 'black'))
self.psychometricWidget.plotItem.setYRange(0, 1, padding=0.05)
layout.addWidget(self.psychometricWidget, 2, 1, 1, 1)

# chronometric function
self.chronometricFunction = PlotWidget(parent=self)
layout.addWidget(self.chronometricFunction, 3, 1, 1, 1)
self.chronometricFunction.plotItem.setTitle('Chronometric Function', color='k')
self.chronometricFunction.plotItem.getAxis('left').setLabel('Response Time (s)')
self.chronometricFunction.plotItem.setLogMode(x=False, y=True)
self.chronometricFunction.plotItem.setYRange(-1, 2, padding=0.05)
self.chronometricPlots = common_function_props(self.chronometricFunction)
self.chronometricWidget = FunctionWidget(parent=self, colors=self.colormap, probabilities=self.model.probability_set)
self.chronometricWidget.plotItem.setTitle('Chronometric Function', color='k')
self.chronometricWidget.plotItem.getAxis('left').setLabel('Response Time (s)')
self.chronometricWidget.plotItem.setLogMode(x=False, y=True)
self.chronometricWidget.plotItem.setYRange(-1, 2, padding=0.05)
layout.addWidget(self.chronometricWidget, 3, 1, 1, 1)

# performance chart
self.performanceWidget = SingleBarChart(parent=self)
self.performanceWidget = SingleBarChartWidget(parent=self)
self.performanceWidget.setMinimumWidth(155)
self.performanceWidget.plotItem.setTitle('Performance', color='k')
self.performanceWidget.plotItem.getAxis('left').setLabel('Correct Choices (%)')
Expand All @@ -602,7 +602,7 @@ def common_function_props(plot_widget: pg.PlotWidget) -> dict[Any, pg.PlotDataIt
layout.addWidget(self.performanceWidget, 2, 2, 1, 1)

# reward chart
self.rewardWidget = SingleBarChart(parent=self, barBrush='blue')
self.rewardWidget = SingleBarChartWidget(parent=self, barBrush='blue')
self.rewardWidget.plotItem.setTitle('Reward Amount', color='k')
self.rewardWidget.plotItem.getAxis('left').setLabel('Total Reward Volume (μl)')
self.rewardWidget.plotItem.setYRange(0, 1050, padding=0)
Expand Down Expand Up @@ -637,8 +637,10 @@ def updatePlots(self, trial: int):
self.trials.scrollToBottom()
for p in self.model.probability_set:
idx = (p, self.model.signed_contrasts)
self.psychometricPlots[p].setData(x=idx[1], y=self.model.psychometrics.loc[idx, 'choice'].to_list())
self.chronometricPlots[p].setData(x=idx[1], y=self.model.psychometrics.loc[idx, 'response_time'].to_list())
self.psychometricWidget.plotDataItems[p].setData(x=idx[1], y=self.model.psychometrics.loc[idx, 'choice'].to_list())
self.chronometricWidget.plotDataItems[p].setData(
x=idx[1], y=self.model.psychometrics.loc[idx, 'response_time'].to_list()
)
self.performanceWidget.setValue(self.model.percentCorrect())
self.rewardWidget.setValue(self.model.reward_amount)
self.update()
Expand Down

0 comments on commit 20a1f18

Please sign in to comment.