import marimo __generated_with = "0.23.2" app = marimo.App() @app.cell(hide_code=True) def _(): import marimo as mo return (mo,) @app.cell(hide_code=True) def _(mo): mo.md( r""" # Pulling Cards from the Library Ecosystem `psychscanner-primal` doesn't ship every task card it can run -- two sibling repos hold public, versioned card indexes instead: - **[psyscan-library](https://github.com/saurabhr/psyscan-library)** -- hand-curated, vetted task/experiment cards, one PASS gate away from merge (every card is run against a real mock-LLM check before it's accepted). Fetched with `download_lib()`, built into this package. - **[psychscanner-cog-atlas](https://github.com/saurabhr/psychscanner-cog-atlas)** -- ~850 cards auto-generated from every task in the public [Cognitive Atlas](https://www.cognitiveatlas.org/tasks) ontology. No built-in fetch helper exists for this one (it's a plain git checkout), so this page clones it directly. Both hand back plain `psychscanner` task-card JSON -- once fetched, running a card is identical regardless of which index it came from. This page runs one card from each, against the built-in `mock-llm` family (no API key, no network needed for the model calls themselves -- only the two clone steps below touch the network). """ ) return @app.cell(hide_code=True) def _(mo): mo.md( r""" ## 1. A vetted card from `psyscan-library` `download_lib()` clones/updates a cached checkout and hands back the `tasks/` path for the installed distro (`primal`, since that's what's running this page). `run_card()` then does the rest -- `task_library()` lookup, `ExpCardInit`/`ExpCard`, `ScannerModel().run()` -- in one call. """ ) return @app.cell def _(): import tempfile from pathlib import Path from psychscanner import download_lib, run_card, to_csv lib_paths = download_lib() # library="primal" (default) -- matches this page's install proj_dir_a = Path(tempfile.mkdtemp(prefix="psychscanner_library_tutorial_")) results_a = run_card( "rm_singleturn_demo", dirs=lib_paths["tasks"], projectname="from_psyscan_library", proj_dir=proj_dir_a, ) return Path, download_lib, proj_dir_a, results_a, run_card, tempfile, to_csv @app.cell(hide_code=True) def _(mo, results_a): mo.md(f"`run_card()` against the psyscan-library card returned **{len(results_a)}** result batch(es).") return @app.cell(hide_code=True) def _(mo): mo.md( r""" ## 2. A Cognitive-Atlas-derived card from `psychscanner-cog-atlas` No `download_lib()`-style helper exists for this index yet, so this clones it directly (shallow, single branch -- the same `git`-via-`subprocess` pattern `download_lib()` itself uses internally) and points `task_library()` at its `tasks/non_reward/` folder. `digit_span_task.json` is tagged `source.compatible_with: ["psychscanner", "psychscanner-primal"]` in the card's own metadata, so it's confirmed to run on this distro. """ ) return @app.cell def _(Path, tempfile): import subprocess cog_atlas_dir = Path(tempfile.mkdtemp(prefix="psychscanner_cog_atlas_")) subprocess.run( [ "git", "clone", "--depth", "1", "--branch", "main", "https://github.com/saurabhr/psychscanner-cog-atlas.git", str(cog_atlas_dir), ], check=True, capture_output=True, ) return cog_atlas_dir, subprocess @app.cell def _(cog_atlas_dir, run_card, tempfile, Path): proj_dir_b = Path(tempfile.mkdtemp(prefix="psychscanner_library_tutorial_")) results_b = run_card( "digit_span_task", dirs=cog_atlas_dir / "tasks" / "non_reward", projectname="from_cog_atlas", proj_dir=proj_dir_b, ) return proj_dir_b, results_b @app.cell(hide_code=True) def _(mo, results_b): mo.md(f"`run_card()` against the cog-atlas card returned **{len(results_b)}** result batch(es).") return @app.cell(hide_code=True) def _(mo): mo.md( r""" ## 3. Both, side by side Same `run_card()` call, same `ExpCard`/`ScannerModel` pipeline, two different origins for the task-card JSON -- the library a card comes from is irrelevant to how it runs once fetched. """ ) return @app.cell def _(proj_dir_a, proj_dir_b, to_csv): # source=a directory scans recursively for the .psyscan checkpoint # files run_card() just wrote, no ExpCard/ScannerModel handle needed. df_a = to_csv(proj_dir_a) df_b = to_csv(proj_dir_b) return df_a, df_b @app.cell(hide_code=True) def _(mo, df_a, df_b): mo.md( f""" | Source | Task | Rows | |---|---|---| | psyscan-library | `rm_singleturn_demo` | {len(df_a)} | | psychscanner-cog-atlas | `digit_span_task` | {len(df_b)} | """ ) return @app.cell(hide_code=True) def _(mo): mo.md( r""" ## Which index should a real task come from? - **Publishing your own new task?** Contribute it to `psyscan-library` (or, if it maps to an existing Cognitive Atlas ontology entry, a correction/addition to `psychscanner-cog-atlas`) -- see **Contribute a task card** in the sibling doc page for the exact PR workflow. - **Just need something that already runs?** Either index works the same way from here: `download_lib()`/a plain clone, then `task_library()`/`run_card()`. `psyscan-library`'s cards are hand-vetted for both distros; `psychscanner-cog-atlas`'s `source.compatible_with` field on each card tells you which distro(s) it's confirmed to run on before you try. """ ) return if __name__ == "__main__": app.run()