diff --git a/doc/git_diagram.py b/doc/git_diagram.py index 231f06ca..81d7bd23 100644 --- a/doc/git_diagram.py +++ b/doc/git_diagram.py @@ -20,9 +20,9 @@ legend = "".join(legend.split("\n")) nodes = dict( - upstream="LABSN/expyfun\n" "master\n" " ", - maint="Eric89GXL/expyfun\n" "master\n" "other_branch", - dev="rkmaddox/expyfun\n" "master\n" "fix_branch", + upstream="LABSN/expyfun\nmaster\n ", + maint="Eric89GXL/expyfun\nmaster\nother_branch", + dev="rkmaddox/expyfun\nmaster\nfix_branch", maint_clone="/home/larsoner/expyfun\n" "master (origin/master)\n" "other_branch (origin/other_branch)\n" @@ -31,7 +31,7 @@ "master (origin/master)\n" "fix_branch (origin/fix_branch)\n" " ", - user_clone="/home/akclee/expyfun\n" "master (origin/master)\n" " \n" " ", + user_clone="/home/akclee/expyfun\nmaster (origin/master)\n \n ", legend=legend, ) diff --git a/examples/experiments/keypress.py b/examples/experiments/keypress.py index c5b28d18..a0339191 100644 --- a/examples/experiments/keypress.py +++ b/examples/experiments/keypress.py @@ -37,7 +37,7 @@ ############### # screen_prompt pressed = ec.screen_prompt( - "press any key\n\nscreen_prompt(" f"max_wait={wait_dur})", + f"press any key\n\nscreen_prompt(max_wait={wait_dur})", max_wait=wait_dur, timestamp=True, ) @@ -51,7 +51,7 @@ ################## # wait_for_presses - ec.screen_text(f"press some keys\n\nwait_for_presses(max_wait={wait_dur})" "") + ec.screen_text(f"press some keys\n\nwait_for_presses(max_wait={wait_dur})") screenshot = ec.screenshot() ec.flip() pressed = ec.wait_for_presses(wait_dur) @@ -60,7 +60,7 @@ message = "no keys pressed" else: message = [ - f"{key} pressed after {round(time, 4)} secs\n" "" for key, time in pressed + f"{key} pressed after {round(time, 4)} secs\n" for key, time in pressed ] message = "".join(message) ec.screen_prompt(message, msg_dur) @@ -69,7 +69,7 @@ ############################################ # wait_for_presses, relative to master clock ec.screen_text( - f"press some keys\n\nwait_for_presses(max_wait={wait_dur}, " "relative_to=0.0)" + f"press some keys\n\nwait_for_presses(max_wait={wait_dur}, relative_to=0.0)" ) ec.flip() pressed = ec.wait_for_presses(wait_dur, relative_to=0.0) @@ -77,9 +77,7 @@ if not len(pressed): message = "no keys pressed" else: - message = [ - f"{key} pressed at {round(time, 4)} secs\n" "" for key, time in pressed - ] + message = [f"{key} pressed at {round(time, 4)} secs\n" for key, time in pressed] message = "".join(message) ec.screen_prompt(message, msg_dur) ec.wait_secs(isi) @@ -87,7 +85,7 @@ ########################################## # listen_presses / wait_secs / get_presses ec.screen_text( - f"press some keys\n\nlisten_presses()\nwait_secs({wait_dur})" "\nget_presses()" + f"press some keys\n\nlisten_presses()\nwait_secs({wait_dur})\nget_presses()" ) ec.flip() ec.listen_presses() @@ -98,7 +96,7 @@ message = "no keys pressed" else: message = [ - f"{key} pressed after {round(time, 4)} secs\n" "" for key, time in pressed + f"{key} pressed after {round(time, 4)} secs\n" for key, time in pressed ] message = "".join(message) ec.screen_prompt(message, msg_dur) @@ -119,9 +117,7 @@ if not len(pressed): message = "no keys pressed" else: - message = [ - f"{key} pressed at {round(time, 4)} secs\n" "" for key, time in pressed - ] + message = [f"{key} pressed at {round(time, 4)} secs\n" for key, time in pressed] message = "".join(message) ec.screen_prompt(message, msg_dur) ec.wait_secs(isi) @@ -132,7 +128,7 @@ countdown = ec.current_time + disp_time ec.call_on_next_flip(ec.listen_presses) ec.screen_text( - "press some keys\n\nlisten_presses()" f"\nwhile loop {disp_time}\nget_presses()" + f"press some keys\n\nlisten_presses()\nwhile loop {disp_time}\nget_presses()" ) ec.flip() while ec.current_time < countdown: @@ -151,7 +147,7 @@ message = "no keys pressed" else: message = [ - f"{key} pressed after {round(time, 4)} secs\n" "" for key, time in pressed + f"{key} pressed after {round(time, 4)} secs\n" for key, time in pressed ] message = "".join(message) ec.screen_prompt(message, msg_dur) @@ -183,9 +179,7 @@ if not len(pressed): message = "no keys pressed" else: - message = [ - f"{key} pressed at {round(time, 4)} secs\n" "" for key, time in pressed - ] + message = [f"{key} pressed at {round(time, 4)} secs\n" for key, time in pressed] message = "".join(message) ec.screen_prompt(message, msg_dur) diff --git a/examples/experiments/keyrelease.py b/examples/experiments/keyrelease.py index 2c9be464..3752ef49 100644 --- a/examples/experiments/keyrelease.py +++ b/examples/experiments/keyrelease.py @@ -69,7 +69,7 @@ if not len(events): message = "no keys pressed" else: - message = [f"{k} {r} after {round(t, 4)} secs\n" "" for k, t, r in events] + message = [f"{k} {r} after {round(t, 4)} secs\n" for k, t, r in events] message = "".join(message) ec.screen_prompt(message, msg_dur) ec.wait_secs(isi) diff --git a/examples/experiments/progress_bar.py b/examples/experiments/progress_bar.py index ec6c62c0..0160e44b 100644 --- a/examples/experiments/progress_bar.py +++ b/examples/experiments/progress_bar.py @@ -30,7 +30,7 @@ pb = ProgressBar(ec, [0, -0.1, 1.5, 0.1], units="norm") ec.screen_prompt( - "Press the number shown on the screen. Start by pressing" " 1.", + "Press the number shown on the screen. Start by pressing 1.", font_size=16, live_keys=[1], max_wait=max_wait, @@ -51,7 +51,7 @@ pb.update_bar(percent) # display the progress bar with some text ec.screen_text( - f"You've completed {percent} %. Press any key to proceed." "", + f"You've completed {percent} %. Press any key to proceed.", [0, 0.1], wrap=False, font_size=16, diff --git a/examples/simple_experiment.py b/examples/simple_experiment.py index 54804e8a..acf58080 100644 --- a/examples/simple_experiment.py +++ b/examples/simple_experiment.py @@ -147,11 +147,9 @@ message = "Too slow!" elif int(pressed) == stim_num + 1: running_total += 1 - message = "Correct! Your reaction time was " f"{round(timestamp, 3)}" + message = f"Correct! Your reaction time was {round(timestamp, 3)}" else: - message = ( - f"You pressed {pressed}, the correct answer was " f"{stim_num + 1}." - ) + message = f"You pressed {pressed}, the correct answer was {stim_num + 1}." ec.screen_prompt(message, max_wait=feedback_dur) ec.wait_secs(isi) @@ -184,7 +182,7 @@ running_total += sum(correct) ec.call_on_next_flip(ec.stop_noise()) ec.screen_prompt( - f"You got {sum(correct)} out of {len(answers)} correct." "", + f"You got {sum(correct)} out of {len(answers)} correct.", max_wait=feedback_dur, ) ec.trial_ok() diff --git a/examples/stimuli/crm_stimuli.py b/examples/stimuli/crm_stimuli.py index 263d3017..df60d3e8 100644 --- a/examples/stimuli/crm_stimuli.py +++ b/examples/stimuli/crm_stimuli.py @@ -53,7 +53,7 @@ ) # print the valid callsigns -print(f'Valid callsigns are {crm_info()["callsign"]}') +print(f"Valid callsigns are {crm_info()['callsign']}") # read a sentence in from the hard drive x1 = 0.5 * crm_sentence(fs, "m", "0", "c", "r", "5", path=crm_path) @@ -79,7 +79,7 @@ stim_fs=40000, ) as ec: ec.screen_text( - "Report the color and number spoken by the female " "talker.", wrap=True + "Report the color and number spoken by the female talker.", wrap=True ) screenshot = ec.screenshot() ec.flip() diff --git a/expyfun/_experiment_controller.py b/expyfun/_experiment_controller.py index 2cbdb02c..1d520e9b 100644 --- a/expyfun/_experiment_controller.py +++ b/expyfun/_experiment_controller.py @@ -255,7 +255,7 @@ def __init__( and value is not None and not isinstance(value, str) ): - raise TypeError(f"{value} must be string or None" "") + raise TypeError(f"{value} must be string or None") if key in edit_list and value is None: self._exp_info[key] = get_keyboard_input(f"{key}: ") else: @@ -272,7 +272,7 @@ def __init__( os.mkdir(output_dir) basename = op.join( output_dir, - "{}_{}" "".format( + "{}_{}".format( self._exp_info["participant"], self._exp_info["date"] ), ) @@ -298,8 +298,7 @@ def __init__( safe_flipping = not (get_config("SAFE_FLIPPING", "").lower() == "false") if not safe_flipping: logger.warning( - "Expyfun: Unsafe flipping mode enabled, flip " - "timing not guaranteed" + "Expyfun: Unsafe flipping mode enabled, flip timing not guaranteed" ) self.safe_flipping = safe_flipping @@ -323,7 +322,7 @@ def __init__( req_mon_keys = ["SCREEN_WIDTH", "SCREEN_DISTANCE", "SCREEN_SIZE_PIX"] missing_keys = [key for key in req_mon_keys if key not in monitor] if missing_keys: - raise KeyError(f"monitor is missing required keys {missing_keys}" "") + raise KeyError(f"monitor is missing required keys {missing_keys}") mon_size = monitor["SCREEN_SIZE_PIX"] monitor["SCREEN_DPI"] = monitor["SCREEN_SIZE_PIX"][0] / ( monitor["SCREEN_WIDTH"] * 0.393701 @@ -365,7 +364,7 @@ def __init__( response_device = get_config("RESPONSE_DEVICE", "keyboard") if response_device not in ["keyboard", "tdt", "cedrus"]: raise ValueError( - 'response_device must be "keyboard", "tdt", ' '"cedrus", or None' + 'response_device must be "keyboard", "tdt", "cedrus", or None' ) self._response_device = response_device @@ -447,7 +446,7 @@ def __init__( window_size = [int(w) for w in window_size] window_size = np.array(window_size) if window_size.ndim != 1 or window_size.size != 2: - raise ValueError("window_size must be 2-element array-like or " "None") + raise ValueError("window_size must be 2-element array-like or None") # open window and setup GL config self._setup_window(window_size, exp_name, full_screen, screen) @@ -458,7 +457,7 @@ def __init__( elif response_device == "tdt": if not isinstance(self._ac, TDTController): raise ValueError( - 'response_device can only be "tdt" if ' "tdt is used for audio" + 'response_device can only be "tdt" if tdt is used for audio' ) self._response_handler = self._ac self._ac._add_keyboard_init(self, force_quit) @@ -489,13 +488,12 @@ def __init__( f"{known_keys}, got {set(trigger_controller)}" ) logger.info( - f'Expyfun: Initializing {trigger_controller["TYPE"]} ' 'triggering mode' + f"Expyfun: Initializing {trigger_controller['TYPE']} triggering mode" ) if trigger_controller["TYPE"] == "tdt": if not isinstance(self._ac, TDTController): raise ValueError( - 'trigger_controller can only be "tdt" if ' - "tdt is used for audio" + 'trigger_controller can only be "tdt" if tdt is used for audio' ) self._tc = self._ac elif trigger_controller["TYPE"] == "sound_card": @@ -543,9 +541,9 @@ def __init__( # finish initialization logger.info("Expyfun: Initialization complete") logger.exp( - "Expyfun: Participant: {0}" "".format(self._exp_info["participant"]) + "Expyfun: Participant: {0}".format(self._exp_info["participant"]) ) - logger.exp("Expyfun: Session: {0}" "".format(self._exp_info["session"])) + logger.exp("Expyfun: Session: {0}".format(self._exp_info["session"])) ok_log = partial(self.write_data_line, "trial_ok", None) self._on_trial_ok.append(ok_log) self._on_trial_ok.append(self.flush) @@ -558,7 +556,7 @@ def __init__( def __repr__(self): """Return a useful string representation of the experiment""" - string = '' "".format( + string = ''.format( self._exp_info["exp_name"], self._exp_info["participant"], self._exp_info["session"], @@ -792,9 +790,7 @@ def start_stimulus(self, start_of_trial=True, flip=True, when=None): """ if start_of_trial: if self._trial_progress != "identified": - raise RuntimeError( - "Trial ID must be stamped before starting " "the trial" - ) + raise RuntimeError("Trial ID must be stamped before starting the trial") self._trial_progress = "started" extra = "flipping screen and " if flip else "" logger.exp(f"Expyfun: Starting stimuli: {extra}playing audio") @@ -1392,7 +1388,7 @@ def check_force_quit(self): def text_input( self, stop_key="return", - instruction_string="Type" " response below", + instruction_string="Type response below", pos=(0, 0), color="white", font_name="Arial", @@ -1863,12 +1859,12 @@ def load_buffer(self, samples): """ if self._playing: raise RuntimeError( - "Previous audio must be stopped before loading " "the buffer" + "Previous audio must be stopped before loading the buffer" ) samples = self._validate_audio(samples) if not np.isclose(self._stim_scaler, 1.0): samples = samples * self._stim_scaler - logger.exp(f"Expyfun: Loading {samples.size} samples to buffer" "") + logger.exp(f"Expyfun: Loading {samples.size} samples to buffer") self._ac.load_buffer(samples) def play(self): @@ -1997,7 +1993,7 @@ def _validate_audio(self, samples): max_samples = 4000000 - 1 if samples.shape[0] > max_samples: raise RuntimeError( - f"Sample too long {samples.shape[0]} > {max_samples}" "" + f"Sample too long {samples.shape[0]} > {max_samples}" ) # resample if needed @@ -2066,7 +2062,7 @@ def set_rms_checking(self, check_rms): """ if check_rms not in [None, "wholefile", "windowed"]: raise ValueError( - 'check_rms must be one of "wholefile", "windowed"' ", or None." + 'check_rms must be one of "wholefile", "windowed", or None.' ) self._slow_rms_warned = False self._check_rms = check_rms @@ -2235,7 +2231,7 @@ def identify_trial(self, **ids): ) ll = max([len(key) for key in ids.keys()]) for key, id_ in ids.items(): - logger.exp(f"Expyfun: Stamp trial ID to {key.ljust(ll)} : {str(id_)}" "") + logger.exp(f"Expyfun: Stamp trial ID to {key.ljust(ll)} : {str(id_)}") if isinstance(id_, dict): self._id_call_dict[key](**id_) else: @@ -2318,7 +2314,7 @@ def stamp_triggers(self, ids, check="binary", wait_for_last=True): _vals = [1, 2, 4, 8] if not all(id_ in _vals for id_ in ids): raise ValueError( - 'with check="binary", ids must all be ' f"1, 2, 4, or 8: {ids}" + f'with check="binary", ids must all be 1, 2, 4, or 8: {ids}' ) self._stamp_ttl_triggers(ids, wait_for_last, False) diff --git a/expyfun/_eyelink_controller.py b/expyfun/_eyelink_controller.py index cfd88dcc..82af26fd 100644 --- a/expyfun/_eyelink_controller.py +++ b/expyfun/_eyelink_controller.py @@ -199,7 +199,7 @@ def __init__(self, ec, link="default", fs=1000, verbose=None): ) if cmd.returncode: raise RuntimeError( - "could not connect to Eyelink @ %s, " "is it turned on?" % link + "could not connect to Eyelink @ %s, is it turned on?" % link ) self._eyelink = DummyEl() if link is None else pylink.EyeLink(link) self._file_list = [] @@ -246,14 +246,14 @@ def _setup(self, fs=1000): # retrieve tracker version and tracker software version v = str(self._eyelink.getTrackerVersion()).strip() - logger.info("Eyelink: Running experiment on a version " f"{v}" " " "tracker.") + logger.info(f"Eyelink: Running experiment on a version {v} tracker.") v = v.split(".") # set EDF file contents logger.debug("EyeLink: Setting file and event filters") fef = "LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT" self._eyelink.setFileEventFilter(fef) - lef = "LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE," "BUTTON,FIXUPDATE,INPUT" + lef = "LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,FIXUPDATE,INPUT" self._eyelink.setLinkEventFilter(lef) fsf = "LEFT,RIGHT,GAZE,HREF,AREA,GAZERES,STATUS,INPUT" lsf = "LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,INPUT" @@ -300,7 +300,7 @@ def _open_file(self): # make absolutely sure we don't break this, but it shouldn't ever # be wrong assert len(file_name) <= 8 - logger.info(f"Eyelink: Opening remote file with filename {file_name}" "") + logger.info(f"Eyelink: Opening remote file with filename {file_name}") _check( self._eyelink.openDataFile(file_name), 'Remote file "' + file_name + '" could not be opened: {0}', @@ -477,7 +477,7 @@ def transfer_remote_file(self, remote_name): EyelinkController.stop """ fname = op.join(self._output_dir, f"{remote_name}.edf") - logger.info(f"Eyelink: saving Eyelink file: {remote_name} ..." "") + logger.info(f"Eyelink: saving Eyelink file: {remote_name} ...") status = self._eyelink.receiveDataFile(remote_name, fname) logger.info(f"Eyelink: transferred {status} bytes") return fname @@ -667,7 +667,7 @@ def custom_calibration( allowed_types = ["H3", "HV5", "HV9", "HV13", "custom"] if ctype not in allowed_types: raise ValueError( - f'ctype cannot be "{ctype}", but must be one of {allowed_types}' "" + f'ctype cannot be "{ctype}", but must be one of {allowed_types}' ) if ctype != "custom": if coordinates is not None: @@ -682,7 +682,7 @@ def custom_calibration( h_max, v_max = self._size[0] / 2.0, self._size[1] / 2.0 for p, m, s in zip((h_pix, v_pix), (h_max, v_max), ("horiz", "vert")): if p > m: - raise ValueError(f"{s} too large ({p} > {m})" "") + raise ValueError(f"{s} too large ({p} > {m})") # make the locations if ctype == "HV5": mat = np.array([[0, 0], [1, 0], [-1, 0], [0, 1], [0, -1]]) @@ -723,7 +723,7 @@ def custom_calibration( elif ctype == "custom": mat = np.array(coordinates, float) if mat.ndim != 2 or mat.shape[-1] != 2: - raise ValueError("Each coordinate must be a list with length 2" ".") + raise ValueError("Each coordinate must be a list with length 2.") offsets = mat * np.array([h_pix, v_pix]) coords = self._size / 2.0 + offsets n_samples = coords.shape[0] @@ -755,7 +755,7 @@ def get_eye_position(self): sample = self._eyelink.getNewestSample() if sample is None: raise RuntimeError( - "No sample data, consider starting a " "recording using el.start()" + "No sample data, consider starting a recording using el.start()" ) if sample.isBinocular(): eye_pos = ( diff --git a/expyfun/_git.py b/expyfun/_git.py index fb8d1908..8abd8d19 100644 --- a/expyfun/_git.py +++ b/expyfun/_git.py @@ -27,7 +27,7 @@ def _check_git(): def _check_version_format(version): """Helper to ensure version is of proper format""" if not isinstance(version, str) or len(version) != 7: - raise TypeError(f"version must be a string of length 7, got {version}" "") + raise TypeError(f"version must be a string of length 7, got {version}") def _active_version(wd): @@ -57,10 +57,10 @@ def download_version(version="current", dest_dir=None): if dest_dir is None: dest_dir = os.getcwd() if not isinstance(dest_dir, str) or not op.isdir(dest_dir): - raise OSError(f"Destination directory {dest_dir} does not exist" "") + raise OSError(f"Destination directory {dest_dir} does not exist") if op.isdir(op.join(dest_dir, "expyfun")): raise OSError( - f'Destination directory {dest_dir} already has "expyfun" ' "subdirectory" + f'Destination directory {dest_dir} already has "expyfun" subdirectory' ) # fetch locally and get the proper version @@ -77,7 +77,7 @@ def download_version(version="current", dest_dir=None): try: run_subprocess(["git", "checkout", version], cwd=expyfun_dir, env=env) except Exception as exp: - raise RuntimeError(f"Could not check out version {version}: {str(exp)}" "") + raise RuntimeError(f"Could not check out version {version}: {str(exp)}") assert _active_version(expyfun_dir) == version # install @@ -146,6 +146,5 @@ def assert_version(version): _check_version_format(version) if this_version.lower() != version.lower(): raise AssertionError( - f"Requested version {version} does not match current " - f"version {this_version}" + f"Requested version {version} does not match current version {this_version}" ) diff --git a/expyfun/_input_controllers.py b/expyfun/_input_controllers.py index 57631a09..79ebe78a 100644 --- a/expyfun/_input_controllers.py +++ b/expyfun/_input_controllers.py @@ -257,9 +257,7 @@ def _correct_presses(self, events, timestamp, relative_to, kind="presses"): def _init_wait_press(self, max_wait, min_wait, live_keys, relative_to): """Prepare for ``wait_one_press`` and ``wait_for_presses``.""" if np.isinf(max_wait) and live_keys == []: - raise ValueError( - "max_wait cannot be infinite if there are no live" " keys." - ) + raise ValueError("max_wait cannot be infinite if there are no live keys.") if not min_wait <= max_wait: raise ValueError("min_wait must be less than max_wait") start_time = self.master_clock() @@ -485,7 +483,7 @@ def _init_wait_click( """Actions common to ``wait_one_click`` and ``wait_for_clicks``""" if np.isinf(max_wait) and live_buttons == []: raise ValueError( - "max_wait cannot be infinite if there are no live" " mouse buttons." + "max_wait cannot be infinite if there are no live mouse buttons." ) if not min_wait <= max_wait: raise ValueError("min_wait must be less than max_wait") diff --git a/expyfun/_sound_controllers/_rtmixer.py b/expyfun/_sound_controllers/_rtmixer.py index 71673853..0cd21f00 100644 --- a/expyfun/_sound_controllers/_rtmixer.py +++ b/expyfun/_sound_controllers/_rtmixer.py @@ -221,7 +221,7 @@ def delete(self): logger.exp(f"Could not fetch mixer stats ({exc})") else: logger.exp( - f"{stats.output_underflows} underflows " f"{stats.blocks} blocks" + f"{stats.output_underflows} underflows {stats.blocks} blocks" ) def __del__(self): # noqa diff --git a/expyfun/_sound_controllers/_sound_controller.py b/expyfun/_sound_controllers/_sound_controller.py index bef54133..a1dffdd9 100644 --- a/expyfun/_sound_controllers/_sound_controller.py +++ b/expyfun/_sound_controllers/_sound_controller.py @@ -268,7 +268,7 @@ def load_buffer(self, samples): if (trig2_start >= 0 and trig2_start <= stim_len) or ( trig2_start < 0 and abs(trig2_start) >= extra ): - warnings.warn("Drift triggers overlap" " with onset triggers.") + warnings.warn("Drift triggers overlap with onset triggers.") if (trig2_start > 0 and trig2_start > sample_len - trig2_len) or ( trig2_start < 0 and abs(trig2_start) >= sample_len ): diff --git a/expyfun/_tdt_controller.py b/expyfun/_tdt_controller.py index 859e3479..a214695d 100644 --- a/expyfun/_tdt_controller.py +++ b/expyfun/_tdt_controller.py @@ -124,9 +124,7 @@ def __init__(self, tdt_params, ec): tdt_params = _check_params(tdt_params, keys, defaults, "tdt_params") if tdt_params["TYPE"] != "tdt": raise ValueError( - 'tdt_params["TYPE"] must be "tdt", not ' "{0}".format( - tdt_params["TYPE"] - ) + 'tdt_params["TYPE"] must be "tdt", not {0}'.format(tdt_params["TYPE"]) ) for key in ("TDT_DELAY", "TDT_TRIG_DELAY"): tdt_params[key] = int(tdt_params[key]) @@ -135,9 +133,7 @@ def __init__(self, tdt_params, ec): self._model = tdt_params["TDT_MODEL"] legal_models = ["RM1", "RP2", "RZ6", "RP2legacy", "dummy"] if self.model not in legal_models: - raise ValueError( - f'TDT_MODEL="{self.model}" must be one of ' f"{legal_models}" - ) + raise ValueError(f'TDT_MODEL="{self.model}" must be one of {legal_models}') if tdt_params["TDT_CIRCUIT_PATH"] is None and self.model != "dummy": cl = dict(RM1="RM1", RP2="RM1", RP2legacy="RP2legacy", RZ6="RZ6") diff --git a/expyfun/_trigger_controllers.py b/expyfun/_trigger_controllers.py index 24d43c98..9ccad7a7 100644 --- a/expyfun/_trigger_controllers.py +++ b/expyfun/_trigger_controllers.py @@ -97,7 +97,7 @@ def __init__( self._portname = str(base) else: raise NotImplementedError( - "Parallel port triggering only " "supported on Linux and Windows" + "Parallel port triggering only supported on Linux and Windows" ) else: # mode == 'dummy': self._port = self._portname = None @@ -181,7 +181,7 @@ def decimals_to_binary(decimals, n_bits): binary = list() for d, b in zip(decimals, n_bits): if d > 2**b - 1: - raise ValueError(f"cannot convert number {d} using {b} bits" "") + raise ValueError(f"cannot convert number {d} using {b} bits") binary.extend([int(bb) for bb in np.binary_repr(d, b)]) assert len(binary) == n_bits.sum() # make sure we didn't do something dumb return binary @@ -212,7 +212,7 @@ def binary_to_decimals(binary, n_bits): raise ValueError("n_bits must all be > 0") if n_bits.sum() != len(binary): raise ValueError( - "the sum of n_bits must be equal to the number of " "elements in binary" + "the sum of n_bits must be equal to the number of elements in binary" ) offset = 0 outs = [] diff --git a/expyfun/_utils.py b/expyfun/_utils.py index 9440d468..3d3c5cc9 100644 --- a/expyfun/_utils.py +++ b/expyfun/_utils.py @@ -269,7 +269,7 @@ def check_units(units): """ good_units = ["norm", "pix", "deg", "cm"] if units not in good_units: - raise ValueError(f'"units" must be one of {good_units}, not {units}' "") + raise ValueError(f'"units" must be one of {good_units}, not {units}') ############################################################################### @@ -551,7 +551,7 @@ def fetch_data_file(fname): fname_out = op.join(path, fname) if not op.isdir(op.dirname(fname_out)): os.makedirs(op.dirname(fname_out)) - fname_url = f"https://github.com/LABSN/expyfun-data/raw/master/{fname}" "" + fname_url = f"https://github.com/LABSN/expyfun-data/raw/master/{fname}" try: # until we get proper certificates context = ssl._create_unverified_context() @@ -709,7 +709,7 @@ def set_config(key, value): else: config = dict() logger.info( - "Attempting to create new expyfun configuration " "file:\n%s" % config_path + "Attempting to create new expyfun configuration file:\n%s" % config_path ) if value is None: config.pop(key, None) @@ -961,7 +961,7 @@ def _check_params(params, keys, defaults, name): for k in params.keys(): if k not in keys: raise KeyError( - 'Unrecognized key in {0}["{1}"], must be ' "one of {2}".format( + 'Unrecognized key in {0}["{1}"], must be one of {2}'.format( name, k, ", ".join(keys) ) ) diff --git a/expyfun/analyze/_analyze.py b/expyfun/analyze/_analyze.py index defac1dc..322b7fff 100644 --- a/expyfun/analyze/_analyze.py +++ b/expyfun/analyze/_analyze.py @@ -223,7 +223,7 @@ def fit_sigmoid(x, y, p0=None, fixed=()): p_types = ("lower", "upper", "midpt", "slope") for f in fixed: if f not in p_types: - raise ValueError(f"fixed {f} not in parameter list {p_types}" "") + raise ValueError(f"fixed {f} not in parameter list {p_types}") fixed = np.array([(True if f in fixed else False) for f in p_types], bool) kwargs = dict() @@ -304,7 +304,7 @@ def fit(x): whiskers = quartiles + np.array((-1.5, 1.5)) * np.diff(quartiles) n_bad = np.sum(np.logical_or(np.less(x, whiskers[0]), np.greater(x, whiskers[1]))) if n_bad > 0 and warn: - warnings.warn(f"{n_bad} likely bad values in x (of {x.size})" "") + warnings.warn(f"{n_bad} likely bad values in x (of {x.size})") peak = np.maximum(0, (df - 2)) * scale return peak diff --git a/expyfun/analyze/_viz.py b/expyfun/analyze/_viz.py index 5bac4dd1..eed00f7c 100644 --- a/expyfun/analyze/_viz.py +++ b/expyfun/analyze/_viz.py @@ -232,7 +232,7 @@ def barplot( bar_names = h.columns.tolist() if axis == 0 else h.index.tolist() # check arg errors if gap_size < 0 or gap_size >= 1: - raise ValueError('Barplot argument "gap_size" must be in the range ' "[0, 1).") + raise ValueError('Barplot argument "gap_size" must be in the range [0, 1).') if err_bars is not None: if isinstance(err_bars, str) and err_bars not in ["sd", "se", "ci"]: raise ValueError( @@ -241,13 +241,9 @@ def barplot( ) if brackets is not None: if any([len(x) != 2 for x in brackets]): - raise ValueError( - "Each top-level element of brackets must have " "length 2." - ) + raise ValueError("Each top-level element of brackets must have length 2.") if not len(brackets) == len(bracket_text): - raise ValueError( - "Mismatch between number of brackets and bracket " "labels." - ) + raise ValueError("Mismatch between number of brackets and bracket labels.") # handle single-element args if isinstance(bracket_text, str): bracket_text = [bracket_text] @@ -332,8 +328,7 @@ def barplot( ) elif not h.shape == np.array(err_bars).shape: raise ValueError( - 'When "err_bars" is array-like it must have ' - 'the same shape as "h".' + 'When "err_bars" is array-like it must have the same shape as "h".' ) err = np.atleast_1d(err_bars) bar_kwargs["yerr"] = err diff --git a/expyfun/io/_parse.py b/expyfun/io/_parse.py index ea8a0a8a..739e09a3 100644 --- a/expyfun/io/_parse.py +++ b/expyfun/io/_parse.py @@ -101,16 +101,16 @@ def read_tab( header = list(set([line[1] for line in lines])) header.sort() if group_start not in header: - raise ValueError(f'group_start "{group_start}" not in header: {header}' "") + raise ValueError(f'group_start "{group_start}" not in header: {header}') if group_end == group_start: - raise ValueError("group_start cannot equal group_end, use " "group_end=None") + raise ValueError("group_start cannot equal group_end, use group_end=None") header = [header.pop(header.index(group_start))] + header b1s = np.where([line[1] == group_start for line in lines])[0] if group_end is None: b2s = np.concatenate((b1s[1:], [len(lines)])) else: # group_end is not None if group_end not in header: - raise ValueError(f'group_end "{group_end}" not in header ({header})' "") + raise ValueError(f'group_end "{group_end}" not in header ({header})') header.append(header.pop(header.index(group_end))) b2s = np.where([line[1] == group_end for line in lines])[0] if len(b1s) == len(b2s) + 1 and allow_last_missing: @@ -182,8 +182,7 @@ def reconstruct_tracker(fname): tracker_stop_idx = np.setdiff1d(tracker_stop_idx, used_stop_idx) if len(tracker_stop_idx) == 0: raise ValueError( - f"Tracker {tracker_id} has not stopped. All Trackers " - "must be stopped." + f"Tracker {tracker_id} has not stopped. All Trackers must be stopped." ) tracker_stop_idx = tracker_stop_idx[0] used_stop_idx.append(tracker_stop_idx) diff --git a/expyfun/io/_wav.py b/expyfun/io/_wav.py index 3daf2ef1..1546ba5d 100644 --- a/expyfun/io/_wav.py +++ b/expyfun/io/_wav.py @@ -60,13 +60,11 @@ def write_wav(fname, data, fs, dtype=np.int16, overwrite=False, verbose=None): If not None, override default verbose level. """ if not overwrite and op.isfile(fname): - raise OSError( - f"File {op.basename(fname)} exists, overwrite=True must be " "used" - ) + raise OSError(f"File {op.basename(fname)} exists, overwrite=True must be used") if not np.dtype(type(fs)).kind == "i": fs = int(fs) warnings.warn( - "Warning: sampling rate is being cast to integer and " "may be truncated." + "Warning: sampling rate is being cast to integer and may be truncated." ) data = np.atleast_2d(data) if np.dtype(dtype).kind not in ["i", "f"]: @@ -74,14 +72,14 @@ def write_wav(fname, data, fs, dtype=np.int16, overwrite=False, verbose=None): if np.dtype(dtype).kind == "f": if not _has_scipy_version("0.13"): raise RuntimeError( - "cannot write float datatype unless " "scipy >= 0.13 is installed" + "cannot write float datatype unless scipy >= 0.13 is installed" ) elif np.dtype(dtype).itemsize == 8: raise RuntimeError("Writing 64-bit integers is not supported") if np.dtype(data.dtype).kind == "f": if np.dtype(dtype).kind == "i" and np.max(np.abs(data)) > 1.0: raise ValueError( - "Data must be between -1 and +1 when saving " "with an integer dtype" + "Data must be between -1 and +1 when saving with an integer dtype" ) _print_wav_info("Writing", data, dtype) max_val = _get_dtype_norm(dtype) @@ -92,7 +90,7 @@ def write_wav(fname, data, fs, dtype=np.int16, overwrite=False, verbose=None): def _print_wav_info(pre, data, dtype): """Helper to print WAV info""" logger.info( - "{0} WAV file with {1} channel{3} and {2} samples " "(format {4})".format( + "{0} WAV file with {1} channel{3} and {2} samples (format {4})".format( pre, data.shape[0], data.shape[1], "s" if data.shape[0] != 1 else "", dtype ) ) diff --git a/expyfun/stimuli/_crm.py b/expyfun/stimuli/_crm.py index 33b7be21..882a9c44 100644 --- a/expyfun/stimuli/_crm.py +++ b/expyfun/stimuli/_crm.py @@ -355,7 +355,7 @@ def crm_sentence( path = join(path, str(int(fs))) if not os.path.isdir(path): raise RuntimeError( - "prepare_corpus has not yet been run " "for sampling rate of %i" % fs + "prepare_corpus has not yet been run for sampling rate of %i" % fs ) fn = join( path, @@ -372,7 +372,7 @@ def crm_sentence( x = read_wav(fn, verbose=False)[0][0] * ref_rms / _rms_prepped else: raise RuntimeError( - "prepare_corpus has not yet been run for the " "requested talker" + "prepare_corpus has not yet been run for the requested talker" ) if ramp_dur: x = window_edges(x, _fs_binary, dur=ramp_dur) @@ -454,7 +454,7 @@ def crm_response_menu( numbers = [str(_check("number", number) + 1) for number in numbers] if len(colors) != len(np.unique(colors)) or len(numbers) != len(np.unique(numbers)): - raise ValueError("There can be no repeated colors or numbers in the " "menu.") + raise ValueError("There can be no repeated colors or numbers in the menu.") # Draw the buttons rects = [] @@ -518,7 +518,7 @@ def __init__(self, fs, ref_rms=0.01, ramp_dur=0.01, stereo=False, path=None): path = join(_get_user_home_path(), ".expyfun", "data", "crm") if not os.path.isdir(join(path, str(fs))): raise RuntimeError( - "prepare_corpus has not yet been run " "for sampling rate of %i" % fs + "prepare_corpus has not yet been run for sampling rate of %i" % fs ) self._excluded = [] self._all_stim = {} @@ -592,6 +592,6 @@ def sentence(self, sex, talker_num, callsign, color, number): ) if stim_id in self._excluded: raise RuntimeError( - "prepare_corpus has not yet been run for the " "requested talker" + "prepare_corpus has not yet been run for the requested talker" ) return self._all_stim[stim_id].copy() diff --git a/expyfun/stimuli/_hrtf.py b/expyfun/stimuli/_hrtf.py index 85477da5..8ff7e228 100644 --- a/expyfun/stimuli/_hrtf.py +++ b/expyfun/stimuli/_hrtf.py @@ -62,18 +62,18 @@ def _get_hrtf(angle, source, fs, interp=False): leftward = True read_angle = float(-angle) if read_angle not in angles and not interp: - raise ValueError(f'angle "{angle}" must be one of +/-{list(angles)}' "") + raise ValueError(f'angle "{angle}" must be one of +/-{list(angles)}') brir = data["brir"] if read_angle in angles: interp = False if not interp: idx = np.where(angles == read_angle)[0] if len(idx) != 1: - raise ValueError(f'angle "{angle}" not uniquely found in angles' "") + raise ValueError(f'angle "{angle}" not uniquely found in angles') brir = brir[idx[0]] else: # interpolation if source != "cipic": - raise ValueError("source must be " "cipic" " when interp=True") + raise ValueError("source must be cipic when interp=True") # pull in files containing known hrtfs and extract magnitude and phase fname = fetch_data_file(f"hrtf/pair_cipic_{fs}.hdf5") @@ -87,7 +87,6 @@ def _get_hrtf(angle, source, fs, interp=False): if idx > len(pairs): raise ValueError( f'angle magnitude "{read_angle}" must be smaller than "{pairs[-1][-1]}"' - "" ) knowns = np.array([angles[idx - 1], angles[idx]]) index = np.where(pairs == knowns)[0][0] @@ -186,9 +185,7 @@ def convolve_hrtf(data, fs, angle, source="cipic", interp=False): known_sources = ["barb", "cipic"] known_fs = [24414, 44100] # must be sorted if source not in known_sources: - raise ValueError( - f'Source "{source}" unknown, must be one of {known_sources}' "" - ) + raise ValueError(f'Source "{source}" unknown, must be one of {known_sources}') if not isinstance(interp, bool): raise ValueError("interp must be bool") data = np.array(data, np.float64) diff --git a/expyfun/stimuli/_stimuli.py b/expyfun/stimuli/_stimuli.py index 0adbbd45..8b52e9a0 100644 --- a/expyfun/stimuli/_stimuli.py +++ b/expyfun/stimuli/_stimuli.py @@ -55,7 +55,7 @@ def window_edges(sig, fs, dur=0.01, axis=-1, window="hann", edges="both"): win = signal.windows.get_window(window, 2 * win_len)[:win_len] valid_edges = ("leading", "trailing", "both") if edges not in valid_edges: - raise ValueError(f'edges must be one of {valid_edges}, not "{edges}"' "") + raise ValueError(f'edges must be one of {valid_edges}, not "{edges}"') # now we can actually do the calculation flattop = np.ones(sig_len, dtype=np.float64) if edges in ("trailing", "both"): # eliminate trailing @@ -165,7 +165,7 @@ def add_pad(sounds, alignment="start"): will be 2-dimensional (channels, samples). """ if alignment not in ["start", "center", "end"]: - raise ValueError("alignment must be either 'start', 'center', " "or 'end'") + raise ValueError("alignment must be either 'start', 'center', or 'end'") x = [np.atleast_2d(y) for y in sounds] if not np.all(y.ndim == 2 for y in x): raise ValueError("Sound data must have no more than 2 dimensions.") diff --git a/expyfun/stimuli/_tracker.py b/expyfun/stimuli/_tracker.py index bd599ed6..45744305 100644 --- a/expyfun/stimuli/_tracker.py +++ b/expyfun/stimuli/_tracker.py @@ -30,8 +30,7 @@ def _check_callback(callback): if not callable(callback): raise TypeError( - "callback must be a callable, None, or an instance of " - "ExperimentController." + "callback must be a callable, None, or an instance of ExperimentController." ) return callback @@ -163,8 +162,7 @@ def __init__( change_indices = [0] if not np.isscalar(step_size_up): raise ValueError( - "If step_size_up is longer than 1, you must " - "specify change indices." + "If step_size_up is longer than 1, you must specify change indices." ) if not np.isscalar(step_size_down): raise ValueError( @@ -173,7 +171,7 @@ def __init__( ) self._change_indices = np.asarray(change_indices) if change_rule not in ["trials", "reversals"]: - raise ValueError("change_rule must be either 'trials' or " "'reversals'") + raise ValueError("change_rule must be either 'trials' or 'reversals'") self._change_rule = change_rule step_size_up = np.atleast_1d(step_size_up) @@ -886,10 +884,7 @@ def __init__(self, callback, trackers, max_lag=1, pace_rule="reversals", rand=No and pace_rule == "reversals" ): raise ValueError( - "pace_rule must be " - "trials" - " to deal trials from" - " a TrackerBinom object" + "pace_rule must be trials to deal trials from a TrackerBinom object" ) if rand is None: self._seed = int(time.time()) @@ -897,7 +892,7 @@ def __init__(self, callback, trackers, max_lag=1, pace_rule="reversals", rand=No else: self._seed = None if not isinstance(rand, np.random.RandomState): - raise TypeError("rand must be of type " "numpy.random.RandomState") + raise TypeError("rand must be of type numpy.random.RandomState") self._rand = rand self._trial_complete = True self._tracker_history = np.array([], dtype=int) diff --git a/expyfun/stimuli/_vocoder.py b/expyfun/stimuli/_vocoder.py index d68a4027..da12c99f 100644 --- a/expyfun/stimuli/_vocoder.py +++ b/expyfun/stimuli/_vocoder.py @@ -177,7 +177,7 @@ def get_carriers(data, fs, edges, order=2, axis=-1, mode="tone", rate=None, seed """ # check args if mode not in ("noise", "tone", "poisson"): - raise ValueError(f'mode must be "noise", "tone", or "poisson", not {mode}' "") + raise ValueError(f'mode must be "noise", "tone", or "poisson", not {mode}') if isinstance(seed, np.random.RandomState): rng = seed elif seed is None: @@ -186,8 +186,7 @@ def get_carriers(data, fs, edges, order=2, axis=-1, mode="tone", rate=None, seed rng = np.random.RandomState(seed) else: raise TypeError( - '"seed" must be an int, an instance of ' - "numpy.random.RandomState, or None." + '"seed" must be an int, an instance of numpy.random.RandomState, or None.' ) carrs = [] fs = float(fs) diff --git a/expyfun/tests/test_experiment_controller.py b/expyfun/tests/test_experiment_controller.py index f92ad4ec..6b5c8228 100644 --- a/expyfun/tests/test_experiment_controller.py +++ b/expyfun/tests/test_experiment_controller.py @@ -736,7 +736,7 @@ def test_sound_card_triggering(hide_window): with ExperimentController(*std_args, n_channels=1, **kwargs) as ec: ec.identify_trial(ttl_id=[1, 0], ec_id="") with pytest.warns( - UserWarning, match="Drift triggers overlap with " "onset triggers." + UserWarning, match="Drift triggers overlap with onset triggers." ): ec.load_buffer(np.zeros(ec.stim_fs)) ec.start_stimulus() diff --git a/expyfun/tests/test_logging.py b/expyfun/tests/test_logging.py index 9a698fa7..b12bf9d8 100644 --- a/expyfun/tests/test_logging.py +++ b/expyfun/tests/test_logging.py @@ -65,4 +65,4 @@ def assert_have_all(data, should_have): __tracebackhide__ = operator.methodcaller("errisinstance", AssertionError) for s in should_have: if s not in data: - raise AssertionError(f'Missing data: "{s}" in:\n{data}' "") + raise AssertionError(f'Missing data: "{s}" in:\n{data}') diff --git a/expyfun/tests/test_utils.py b/expyfun/tests/test_utils.py index fc18e96f..2e68e59b 100644 --- a/expyfun/tests/test_utils.py +++ b/expyfun/tests/test_utils.py @@ -76,7 +76,7 @@ def test_audio_dims(): with pytest.raises(ValueError, match="channel count 1 did not .* 3"): _fix_audio_dims(x, 3) for dim in (1, 3): - want = "signal channel count 2 did not match required channel " "count %s" % dim + want = "signal channel count 2 did not match required channel count %s" % dim with pytest.raises(ValueError, match=want): _fix_audio_dims(y, dim) for n_channels in (1, 2, 3): diff --git a/expyfun/visual/_visual.py b/expyfun/visual/_visual.py index 669decb3..5b288614 100644 --- a/expyfun/visual/_visual.py +++ b/expyfun/visual/_visual.py @@ -748,7 +748,7 @@ def set_radius(self, radius, units="norm"): check_units(units) radius = np.atleast_1d(radius).astype(float) if radius.ndim != 1 or radius.size > 2: - raise ValueError("radius must be a 1- or 2-element " "array-like vector") + raise ValueError("radius must be a 1- or 2-element array-like vector") if radius.size == 1: radius = np.r_[radius, radius] # convert to pixel (OpenGL) units @@ -876,7 +876,7 @@ def set_radii(self, radii, units="norm"): """ radii = np.array(radii, float) if radii.ndim != 1 or radii.size != len(self): - raise ValueError(f"radii must contain exactly {len(self)} radii" "") + raise ValueError(f"radii must contain exactly {len(self)} radii") for idx, radius in enumerate(radii): self.set_radius(radius, idx, units) @@ -902,9 +902,7 @@ def set_colors(self, colors): colors as the number of circles. """ if not isinstance(colors, (tuple, list)) or len(colors) != len(self): - raise ValueError( - f"colors must be a list or tuple with {len(self)} colors" "" - ) + raise ValueError(f"colors must be a list or tuple with {len(self)} colors") for idx, color in enumerate(colors): self.set_color(color, idx) @@ -1061,7 +1059,7 @@ def set_image(self, image_buffer): if image_buffer.ndim == 2: # grayscale image_buffer = np.tile(image_buffer[..., np.newaxis], (1, 1, 3)) if not image_buffer.ndim == 3 or image_buffer.shape[2] not in [3, 4]: - raise RuntimeError(f"image_buffer incorrect size: {image_buffer.shape}" "") + raise RuntimeError(f"image_buffer incorrect size: {image_buffer.shape}") # add alpha channel if necessary dims = image_buffer.shape fmt = "RGB" if dims[2] == 3 else "RGBA" @@ -1290,7 +1288,7 @@ def play(self, auto_draw=True): self._playing = True else: warnings.warn( - "ExperimentController.video.play() called when " "already playing." + "ExperimentController.video.play() called when already playing." ) return self._ec.get_time() @@ -1314,7 +1312,7 @@ def pause(self): self._playing = False else: warnings.warn( - "ExperimentController.video.pause() called when " "already paused." + "ExperimentController.video.pause() called when already paused." ) return self._ec.get_time()