ibllib.qc.critical_reasons

Methods for adding QC sign-off notes to Alyx.

Includes a GUI to prompt experimenter for reason for marking session/insertion as CRITICAL. Choices are listed in the global variables. Multiple reasons can be selected. Places info in Alyx session note in a format that is machine retrievable (text->json).

Functions

main

Main function to call to input a reason for marking a session/insertion as CRITICAL programmatically.

main_gui

Main function to call to input a reason for marking an insertion as CRITICAL from the alignment GUI.

Classes

AlignmentSignOffNote

Class for signing off a alignment part of a session and optionally adding a related explanation note.

CriticalInsertionNote

Class for uploading a critical note to an insertion.

CriticalNote

Class for uploading a critical note to a session or insertion.

CriticalSessionNote

Class for uploading a critical note to a session.

Note

PassiveSignOffNote

Class for signing off a passive part of a session and optionally adding a related explanation note.

RawEphysSignOffNote

Class for signing off a raw ephys part of a session and optionally adding a related explanation note.

SignOffNote

Class for signing off a session and optionally adding a related explanation note.

SpikeSortingSignOffNote

Class for signing off a spike sorting part of a session and optionally adding a related explanation note.

TaskSignOffNote

Class for signing off a task part of a session and optionally adding a related explanation note.

VideoSignOffNote

Class for signing off a video part of a session and optionally adding a related explanation note.

main_gui(uuid, reasons_selected, alyx=None)[source]

Main function to call to input a reason for marking an insertion as CRITICAL from the alignment GUI.

It wil create note text, after deleting any similar notes existing already.

Parameters:
  • uuid (uuid.UUID, str) – An insertion ID.

  • reasons_selected (list of str) – A subset of REASONS_INS_CRIT_GUI.

  • alyx (one.webclient.AlyxClient) – An AlyxClient instance.

main(uuid, alyx=None)[source]

Main function to call to input a reason for marking a session/insertion as CRITICAL programmatically.

It will: - ask reasons for selection of critical status - check if ‘other’ reason has been selected, inquire why (free text) - create note text, checking whether similar notes exist already - upload note to Alyx if none exist previously or if overwrite is chosen Q&A are prompted via the Python terminal

Parameters:
  • uuid (uuid.UUID, str) – An experiment UUID or an insertion UUID.

  • alyx (one.webclient.AlyxClient) – An AlyxClient instance.

Examples

Retrieve Alyx note to test

>>> alyx = AlyxClient(base_url='https://dev.alyx.internationalbrainlab.org')
>>> uuid = '2ffd3ed5-477e-4153-9af7-7fdad3c6946b'
>>> main(uuid=uuid, alyx=alyx)

Get notes with pattern

>>> notes = alyx.rest('notes', 'list',
...                   django=f'text__icontains,{STR_NOTES_STATIC},'
...                          f'object_id,{uuid}')
>>> test_json_read = json.loads(notes[0]['text'])
class Note(uuid, alyx, content_type=None)[source]

Bases: ABC

descriptions = []
property default_descriptions
property extra_prompt
property note_title
property n_description
get_content_type()[source]

Infer the content_type from the uuid. Only checks to see if uuid is a session or insertion. If not recognised will raise an error and the content_type must be specified on note initialisation e.g. Note(uuid, alyx, content_type=’subject’)

Returns:

The Alyx model name, inferred from the UUID.

Return type:

str

describe()[source]

Print list of default reasons that can be chosen from :return:

numbered_descriptions()[source]

Return list of numbered default reasons :return:

upload_note(nums=None, other_reason=None, **kwargs)[source]

Upload note to Alyx.

If no values for nums and other_reason are specified, user will receive a prompt in command line asking them to choose from default list of reasons to add to note as well as option for free text. To upload without receiving prompt a value for either nums or other_reason must be given.

Parameters:
  • nums (str) – string of numbers matching those in default descriptions, e.g, ‘1,3’. Options can be seen using note.describe().

  • other_reason (str) – Other comment or reason(s) to add to note.

reasons_prompt()[source]

Prompt for user to enter reasons :return:

other_reason_prompt()[source]

Prompt for user to enter other reasons :return:

abstract format_note(**kwargs)[source]

Method to format text field of note according to type of note wanting to be uploaded

Parameters:

kwargs

Returns:

abstract update_existing_note(note, **kwargs)[source]

Method to specify behavior in the case of a note with the same title already existing

Parameters:
  • note

  • kwargs

Returns:

class CriticalNote(uuid, alyx, content_type=None)[source]

Bases: Note

Class for uploading a critical note to a session or insertion. Do not use directly but use CriticalSessionNote or CriticalInsertionNote instead

format_note(**kwargs)[source]

Method to format text field of note according to type of note wanting to be uploaded

Parameters:

kwargs

Returns:

update_existing_note(notes, **kwargs)[source]

Method to specify behavior in the case of a note with the same title already existing

Parameters:
  • note

  • kwargs

Returns:

delete_note_prompt(notes)[source]
class CriticalInsertionNote(uuid, alyx)[source]

Bases: CriticalNote

Class for uploading a critical note to an insertion.

Examples

>>> note = CriticalInsertionNote(pid, AlyxClient())

Print list of default reasons

>>> note.describe()

To receive a command line prompt to fill in note

>>> note.upload_note()

To upload note automatically without prompt

>>> note.upload_note(nums='1,4', other_reason='lots of bad channels')
descriptions_gui = ['Noise and artifact', 'Drift', 'Poor neural yield', 'Brain Damage', 'Other']
descriptions = ['Histological images missing', 'Track not visible on imaging data']
property default_descriptions
property extra_prompt
property note_title
class CriticalSessionNote(uuid, alyx)[source]

Bases: CriticalNote

Class for uploading a critical note to a session.

Example

>>> note = CriticalInsertionNote(uuid, AlyxClient)

Print list of default reasons

>>> note.describe()

To receive a command line prompt to fill in note

>>> note.upload_note()

To upload note automatically without prompt

>>> note.upload_note(nums='1,4', other_reason='session with no ephys recording')
descriptions = ['within experiment system crash', 'synching impossible', 'dud or mock session', 'essential dataset missing']
property extra_prompt
property note_title
class SignOffNote(uuid, alyx, sign_off_key)[source]

Bases: Note

Class for signing off a session and optionally adding a related explanation note. Do not use directly but use classes that inherit from this class e.g TaskSignOffNote, RawEphysSignOffNote

property extra_prompt
property note_title
upload_note(nums=None, other_reason=None, **kwargs)[source]

Upload note to Alyx.

If no values for nums and other_reason are specified, user will receive a prompt in command line asking them to choose from default list of reasons to add to note as well as option for free text. To upload without receiving prompt a value for either nums or other_reason must be given.

Parameters:
  • nums (str) – string of numbers matching those in default descriptions, e.g, ‘1,3’. Options can be seen using note.describe().

  • other_reason (str) – Other comment or reason(s) to add to note.

sign_off()[source]
format_note(**kwargs)[source]

Method to format text field of note according to type of note wanting to be uploaded

Parameters:

kwargs

Returns:

format_existing_note(orignal_note)[source]
update_existing_note(notes)[source]

Method to specify behavior in the case of a note with the same title already existing

Parameters:
  • note

  • kwargs

Returns:

get_datetime_key()[source]
class TaskSignOffNote(uuid, alyx, sign_off_key)[source]

Bases: SignOffNote

Class for signing off a task part of a session and optionally adding a related explanation note.

Examples

>>> note = TaskSignOffNote(eid, AlyxClient(), '_ephysChoiceWorld_00')

To sign off session without any note

>>> note.sign_off()

Print list of default reasons

>>> note.describe()

To upload note and sign off with prompt

>>> note.upload_note()

To upload note automatically without prompt

>>> note.upload_note(nums='1,4', other_reason='session with no ephys recording')
descriptions = ['raw trial data does not exist', 'wheel data corrupt', 'task data could not be synced', 'stimulus timings unreliable']
class PassiveSignOffNote(uuid, alyx, sign_off_key)[source]

Bases: SignOffNote

Class for signing off a passive part of a session and optionally adding a related explanation note.

Examples

>>> note = PassiveSignOffNote(eid, AlyxClient(), '_passiveChoiceWorld_00')

To sign off session without any note

>>> note.sign_off()

Print list of default reasons

>>> note.describe()

To upload note and sign off with prompt

>>> note.upload_note()

To upload note automatically without prompt

>>> note.upload_note(nums='1,4', other_reason='session with no ephys recording')
descriptions = ['Raw passive data doesn’t exist (no. of spacers = 0)', 'Incorrect number or spacers (i.e passive cutoff midway)', 'RFmap file doesn’t exist', 'Gabor patches couldn’t be extracted', 'Trial playback couldn’t be extracted']
class VideoSignOffNote(uuid, alyx, sign_off_key)[source]

Bases: SignOffNote

Class for signing off a video part of a session and optionally adding a related explanation note.

Examples

>>> note = VideoSignOffNote(eid, AlyxClient(), '_camera_left')

To sign off session without any note

>>> note.sign_off()

Print list of default reasons

>>> note.describe()

To upload note and sign off with prompt

>>> note.upload_note()

To upload note automatically without prompt

>>> note.upload_note(nums='1,4', other_reason='session with no ephys recording')
descriptions = ['The video timestamps are not the same length as the video file (either empty or slightly longer/shorter)', 'The rotary encoder trace doesn’t not appear synced with the video', 'The QC fails because the GPIO file is missing or empty', 'The frame rate in the video header is wrong (the video plays too slow or fast)', 'The resolution is not what is defined in the experiment description file', 'The DLC QC fails because something is obscuring the pupil']
class RawEphysSignOffNote(uuid, alyx, sign_off_key)[source]

Bases: SignOffNote

Class for signing off a raw ephys part of a session and optionally adding a related explanation note.

Examples

>>> note = RawEphysSignOffNote(uuid, AlyxClient(), '_neuropixel_raw_probe00')

To sign off session without any note

>>> note.sign_off()

Print list of default reasons

>>> note.describe()

To upload note and sign off with prompt

>>> note.upload_note()

To upload note automatically without prompt

>>> note.upload_note(nums='1,4', other_reason='session with no ephys recording')
descriptions = ['Data has striping', 'Horizontal band', 'Discontunuity']
class SpikeSortingSignOffNote(uuid, alyx, sign_off_key)[source]

Bases: SignOffNote

Class for signing off a spike sorting part of a session and optionally adding a related explanation note.

Examples

>>> note = SpikeSortingSignOffNote(uuid, AlyxClient(), '_neuropixel_spike_sorting_probe00')

To sign off session without any note

>>> note.sign_off()

Print list of default reasons

>>> note.describe()

To upload note and sign off with prompt

>>> note.upload_note()

To upload note automatically without prompt

>>> note.upload_note(nums='1,4', other_reason='session with no ephys recording')
descriptions = ['Spikesorting could not be run', 'Poor quality spikesorting']
class AlignmentSignOffNote(uuid, alyx, sign_off_key)[source]

Bases: SignOffNote

Class for signing off a alignment part of a session and optionally adding a related explanation note.

Examples

>>> note = AlignmentSignOffNote(uuid, AlyxClient(), '_neuropixel_alignment_probe00')

To sign off session without any note

>>> note.sign_off()

Print list of default reasons

>>> note.describe()

To upload note and sign off with prompt

>>> note.upload_note()

To upload note automatically without prompt

>>> note.upload_note(nums='1,4', other_reason='session with no ephys recording')
descriptions = []