terminal

Methods for running the Terminal GUI

Classes:

Terminal(self[, parent, flags])

Central host to a swarm of Pilot s and user-facing gui objects.

class Terminal(self, parent: PySide6.QtWidgets.QWidget | None = None, flags: PySide6.QtCore.Qt.WindowType = Default(Qt.WindowFlags))

Bases: QMainWindow

Central host to a swarm of Pilot s and user-facing gui objects.

Called as a module with the -f flag to give the location of a prefs file, eg:

python terminal.py -f prefs_file.json

if the -f flag is not passed, looks in the default location for prefs (ie. /usr/autopilot/prefs.json)

**Listens used by the internal Net_Node **

Key

Method

Description

‘STATE’

l_state()

A Pi has changed state

‘PING’

l_ping()

Someone wants to know if we’re alive

‘DATA’

l_data()

Receiving data to store

‘HANDSHAKE’

l_handshake()

Pilot first contact, telling us it’s alive and its IP

Note

See autopilot.prefs for full list of prefs needed by terminal!

Note

The Terminal class is currently a subclass of PySide6.QtWidgets.QMainWindow – it will be refactored to inherit from Agent as the agent system is formalized.

Variables:
  • node (Net_Node) – Our Net_Node we use to communicate with our main networking object

  • networking (Terminal_Station) – Our networking object to communicate with the outside world

  • subjects (dict) – A dictionary mapping subject ID to Subject object.

  • layout (QtWidgets.QGridLayout) – Layout used to organize widgets

  • control_panel (Control_Panel) – Control Panel to manage pilots and subjects

  • data_panel (Plot_Widget) – Plots for each pilot and subject.

  • logo (QtWidgets.QLabel) – Label holding our beautiful logo ;X

  • logger (logging.Logger) – Used to log messages and network events.

  • settings (PySide2.QtCore.QSettings) – QSettings used to store pyside configuration like window size, stored in prefs.get("TERMINAL_SETTINGS_FN")

Initialize self. See help(type(self)) for accurate signature.

Methods:

calibrate_ports()

Calibrate hardware.gpio.Solenoid objects.

closeEvent(event)

When Closing the Terminal Window, close any running subject objects, 'KILL' our networking object.

heartbeat([once])

Perioducally send an INIT message that checks the status of connected pilots

initUI()

Initializes graphical elements of Terminal.

l_data(value)

A Pilot has sent us data.

l_handshake(value)

Pilot is sending its IP and state on startup.

l_ping(value)

Todo

Reminder to implement heartbeating.

l_state(value)

A Pilot has changed state, keep track of it.

manage_plugins()

new_pilot([name, ip, pilot_prefs])

Make a new entry in Terminal.pilots and make appropriate GUI elements.

new_protocol()

Open a gui.Protocol_Wizard to create a new protocol.

new_subject()

ping_pilot(pilot)

plot_psychometric()

Select subject, step, and variables to plot a psychometric curve

reassign_protocols()

Batch reassign protocols and steps.

reset_ui()

Clear Layout and call initUI() again

stream_video()

Open a window to stream videos from a connected pilot.

subject_weights()

Gets recent weights from all subjects and open a gui.Weights window to view or set weights.

test_bandwidth()

Test bandwidth of Pilot connection with variable sized arrays as paylods

toggle_start(starting, pilot[, subject])

Start or Stop running the currently selected subject's task.

update_protocols()

If we change the protocol file, update the stored version in subject files

Attributes:

pilots

A dictionary mapping pilot ID to its attributes, including a list of its subjects assigned to it, its IP, etc.

protocols

List of protocol names available in PROTOCOLDIR

staticMetaObject

subject_list

Get a list of all subject IDs

subject_protocols

Returns: subject_protocols (dict): a dictionary of subjects: [protocol, step]

calibrate_ports()

Calibrate hardware.gpio.Solenoid objects.

See gui.Calibrate_Water.

After calibration routine, send results to pilot for storage.

closeEvent(event)

When Closing the Terminal Window, close any running subject objects, ‘KILL’ our networking object.

heartbeat(once=False)

Perioducally send an INIT message that checks the status of connected pilots

sent with frequency according to Terminal.heartbeat_dur

Parameters:

once (bool) – if True, do a single heartbeat but don’t start a thread to do more.

initUI()

Initializes graphical elements of Terminal.

Including…

  • Toolbar

  • gui.Control_Panel

  • plots.Plot_Widget

l_data(value)

A Pilot has sent us data.

value field of message should have subject and pilot added to dictionary for identification.

Any key in value that matches a column in the subject’s trial data table will be saved.

If the subject graduates after receiving this piece of data, stop the current task running on the Pilot and send the new one.

Parameters:

value (dict) – A dict of field-value pairs to save

l_handshake(value)

Pilot is sending its IP and state on startup.

If we haven’t heard of this pilot before, make a new entry in pilots and gui.Control_Panel.update_db() .

Parameters:

value (dict) – dict containing ip and state

l_ping(value)

Todo

Reminder to implement heartbeating.

Note

Currently unused, as Terminal Net_Node stability hasn’t been a problem and no universal system of heartbeating has been established (global stability has not been an issue).

Parameters:

value – (unused)

l_state(value)

A Pilot has changed state, keep track of it.

Parameters:

value (dict) – dict containing state .

manage_plugins()
new_pilot(name: str | None = None, ip: str = '', pilot_prefs: dict | None = None)

Make a new entry in Terminal.pilots and make appropriate GUI elements.

Parameters:
  • ip (str) – Optional. if given, stored in db.

  • name (str) – If None, prompted for a name, otherwise used for entry in pilot DB.

new_protocol()

Open a gui.Protocol_Wizard to create a new protocol.

Prompts for name of protocol, then saves in prefs.get(‘PROTOCOLDIR’)

new_subject()
property pilots: OrderedDict

A dictionary mapping pilot ID to its attributes, including a list of its subjects assigned to it, its IP, etc.

Returns:

like self.pilots['pilot_id'] = {'subjects': ['subject_0', 'subject_1'], 'ip': '192.168.0.101'}

Return type:

dict

ping_pilot(pilot)
plot_psychometric()

Select subject, step, and variables to plot a psychometric curve

property protocols: list

List of protocol names available in PROTOCOLDIR

Returns:

list of protocol names in prefs.get('PROTOCOLDIR')

Return type:

list

reassign_protocols()

Batch reassign protocols and steps.

Opens a gui.Reassign window after getting protocol data, and applies any changes made in the window.

reset_ui()

Clear Layout and call initUI() again

staticMetaObject = PySide6.QtCore.QMetaObject("Terminal" inherits "QMainWindow": )
stream_video()

Open a window to stream videos from a connected pilot.

Choose from connected pilots and configured Camera objects (prefs.json sent by Pilots in Pilot.handshake() ). Stream video, save to file.

Todo

Configure camera parameters!!!

property subject_list: list

Get a list of all subject IDs

Returns:

list of all subject IDs present in Terminal.pilots

Return type:

list

property subject_protocols: dict

Returns: subject_protocols (dict): a dictionary of subjects: [protocol, step]

subject_weights()

Gets recent weights from all subjects and open a gui.Weights window to view or set weights.

test_bandwidth()

Test bandwidth of Pilot connection with variable sized arrays as paylods

See gui.Bandwidth_Test

toggle_start(starting, pilot, subject=None)

Start or Stop running the currently selected subject’s task. Sends a message containing the task information to the concerned pilot.

Each Pilot_Panel is given a lambda function that calls this one with the arguments specified See Pilot_Button, as it is what calls this function.

Parameters:
  • starting (bool) – Does this button press mean we are starting (True) or stopping (False) the task?

  • pilot – Which Pilot is starting or stopping?

  • subject – Which Subject is currently selected?

update_protocols()

If we change the protocol file, update the stored version in subject files