## 🏁 Getting Started with psyflow Welcome to **psyflow**, a lightweight framework for building PsychoPy experiments with modular, chainable components. This guide walks you through installation, basic setup, and running your first trial. ### 1. Installation Ensure you have PsychoPy installed: pip install psychopy Then install psyflow (replace with actual package name if on PyPI): pip install psyflow Or if you’re working from source: git clone https://github.com/your-org/psyflow.git cd psyflow pip install -e . ### 2. Basic Experiment Structure A typical psyflow experiment has these core steps: 1. **Configure** experiment settings (`TaskSettings`) 2. **Collect** participant info (`SubInfo`) 3. **Build** stimuli (`StimBank`) 4. **Define** triggers (a dictionary of codes + `TriggerSender`) 5. **Create** a trial (`StimUnit`) 6. **Run** the trial and collect data ### 3. Configure Your Task from psyflow import TaskSettings config = { "total_blocks": 2, "total_trials": 20, "seed_mode": "same_within_sub", "key_list": ["left", "right"], "conditions": ["reward", "neutral"], "bg_color": "black" } settings = TaskSettings.from_dict(config) Later, after collecting `subject_id`: settings.add_subinfo({"subject_id": "001", "session_name": "A"}) This creates `settings.block_seed`, `settings.log_file`, and `settings.res_file`. ### 4. Collect Participant Info import yaml from psyflow import SubInfo config = yaml.safe_load(open("subinfo.yaml")) collector = SubInfo(config) subinfo = collector.collect() # opens GUI # e.g., {'subject_id':'001', 'session_name':'A'} Pass `subinfo` into settings via `add_subinfo()` above. ### 5. Build Your Stimuli from psyflow import StimBank from psychopy.visual import TextStim, Circle stim_bank = StimBank(win) @stim_bank.define("fix") def make_fix(win): return TextStim(win, text="+", color="white") stim_bank.add_from_dict({ "target": {"type":"circle","radius":0.5,"fillColor":"red"} }) stim_bank.preload_all() Retrieve with: fix = stim_bank.get("fix") tgt = stim_bank.get("target") ### 6. Set Up Triggers import yaml from psyflow import TriggerSender with open("triggers.yaml") as f: triggers = yaml.safe_load(f) sender = TriggerSender(lambda code: port.write(bytes([code]))) ### 7. Create & Run a Trial from psyflow import StimUnit trial = StimUnit("T1", win, kb, triggersender=sender) trial \ .add_stim(fix, tgt) \ .on_start(lambda u: u.send_trigger(triggers["fix_onset"])) \ .capture_response( keys=["left","right"], duration=1.0, onset_trigger=triggers["fix_onset"], response_trigger={"left":triggers["resp_L"], "right":triggers["resp_R"]}, timeout_trigger=triggers["timeout"], correct_keys=["left"], highlight_stim={"left": highlight_left, "right": highlight_right} ) \ .on_end(lambda u: print("Result:", u.state)) \ .run(frame_based=True) Inspect `trial.state`, save or append to data file. ### 8. Putting It All Together Combine loops over blocks and trials: for b in range(settings.total_blocks): # generate conditions, run trial sequence... pass Use `settings.res_file` to write headers and `trial.to_dict()` for rows. Congratulations—you’ve run your first psyflow trial! Explore additional features in each class’s documentation to customize timing, logging, and more. Happy experimenting!