API Reference

Core Classes

The package exposes three primary classes through neurodesign:

from neurodesign import Experiment, Design, Optimisation

The compatibility import path from neurodesign.classes import ... resolves to the same class objects implemented in neurodesign/classes.py.

Public construction and selection routes:

  • create sampled designs with Experiment.create_design(...)

  • create fully manual flat one-event designs with Experiment.create_manual_design(...)

  • run search with Optimisation.optimise()

  • retrieve reported designs with Optimisation.selected_design(rank)

Direct Design(...) construction is not a user-facing version-2 workflow.

Experiment

class neurodesign.Experiment(TR, P, C, rho, n_stimuli, stim_duration=None, event_durations=None, trial_start_interval=0.0, post_event_interval=0.0, event_transition_interval=0.0, inter_trial_interval=0.0, rest_every_n_trials=None, rest_interval=0.0, n_trials=None, duration=None, resolution=0.1, FeMax=1, FdMax=1, FcMax=1, FfMax=1, maxrep=None, hardprob=False, confoundorder=3, order=None, trial_templates=None, trials=None, trial_template_probabilities=None, n_conceptual_trials=None, seed=None, ordertype='random', restnum=None, restdur=None, trial_max=None, **kwargs)[source]

Bases: object

Store the experiment specification and generate realized designs.

Version 2 distinguishes conceptual trials from flattened modeled events: conceptual-trial counts govern sampling and trial boundaries, while the realized event axis governs event-level timing and Ff/Fc calculations.

make_design_rng(salt=0)[source]

Create a reproducible RNG derived from the experiment seed.

Return type:

Generator

sample_template_id(rng)[source]

Sample one template identifier from the configured template weights.

Return type:

str

sample_trial_sequence(rng)[source]

Sample a full conceptual-trial template sequence.

Return type:

list[str]

countstim()[source]

Compute duration summaries implied by the active scheduling mode.

CreateTsComp()[source]

Build scan-grid and modeling-grid time bases.

CreateLmComp()[source]

Build HRF, drift, and whitening components used by design scoring.

canonical()[source]

Construct the canonical SPM-style HRF basis on the modeling grid.

static drift(s, deg=3)[source]

Return polynomial drift regressors evaluated at sample locations.

static spm_Gpdf(s, h, l)[source]

Evaluate the gamma density used by the canonical HRF.

ff_max_for_event_count(event_count)[source]

Return the Ff normalization constant for a given event count.

Return type:

float

fc_max_for_event_count(event_count, confoundorder=None)[source]

Return the Fc normalization constant for a given event count.

Return type:

float

max_eff()[source]

Initialize cached normalization constants for the active experiment.

realize_manual_flat_design(order, inter_trial_intervals, all_event_durations=None)[source]

Materialize a flat one-event schedule from explicit event inputs.

create_manual_design(order, inter_trial_intervals, event_durations=None)[source]

Wrap a manually specified flat schedule in a Design.

Return type:

Design

create_design(seed=None)[source]

Sample or realize one design under the active scheduling mode.

Return type:

Design

export_specification()[source]

Export the experiment specification with separated trial/event counts.

Return type:

dict[str, Any]

specification_hash()[source]

Return a deterministic hash of the exported experiment specification.

Return type:

str

realize_flat_order(order, rng)[source]

Realize timing arrays for a classic flat one-event order.

realize_from_trial_sequence(trial_sequence, rng, template_sequence=None)[source]

Realize a full event-level schedule from conceptual-trial templates.

event_sequence_from_template_ids(template_sequence)[source]

Flatten a conceptual-trial template sequence into modeled event codes.

Design

class neurodesign.Design(experiment=None, schedule=None, trial_sequence=None, template_sequence=None)[source]

Bases: object

Represent one realized fMRI design with explicit event-level timing.

The design stores the flattened modeled-event order, the realized schedule arrays derived from an Experiment, and the computed efficiency metrics used for reporting and optimisation.

check_maxrep(maxrep)[source]

Return False if any flattened event category repeats too often.

check_hardprob()[source]

Check whether the realized flattened event proportions match P.

spawn_resampled_timing(rng)[source]

Resample timing while preserving the same conceptual-trial structure.

Return type:

Design

crossover(other, seed=1234)[source]

Create offspring designs by recombining order or template sequences.

mutation(q, seed=1234)[source]

Randomly perturb a design while respecting the active design mode.

designmatrix()[source]

Build event-level and convolved design matrices for this schedule.

Xnonconv represents the realized modeled-event occupancy on the scan grid. Xconv is the HRF-convolved event-regressor matrix used by the estimation efficiency metrics.

FeCalc(Aoptimality=True)[source]

Compute estimation-efficiency score Fe for the deconvolved model.

FdCalc(Aoptimality=True)[source]

Compute detection-efficiency score Fd for the convolved model.

FcCalc(confoundorder=3)[source]

Compute transition-balance score Fc on the flattened event axis.

FfCalc()[source]

Compute frequency-balance score Ff on the flattened event axis.

FCalc(weights, Aoptimality=True, confoundorder=3)[source]

Compute all requested component scores and their weighted objective.

export_schedule()[source]

Return the row-wise event schedule used for reports and validation.

Return type:

list[dict[str, Any]]

export_payload()[source]

Export schedule arrays, counts, and metrics for downstream artifacts.

Return type:

dict[str, Any]

stable_hash()[source]

Return a deterministic hash of the exported realized design payload.

Return type:

str

Optimisation

class neurodesign.Optimisation(experiment, weights, preruncycles, cycles, seed=None, I=4, G=20, R=None, q=0.01, Aoptimality=True, folder=None, outdes=3, convergence=1000, max_candidate_attempts=10000, optimisation='GA')[source]

Bases: object

Run the genetic-algorithm design search loop for a configured experiment.

Typical usage is optimisation.optimise() followed by optimisation.selected_design(0) to retrieve the best representative design; see MIGRATION_2.0.md for the full recommended workflow.

change_seed()[source]

Increment the optimisation seed to start a fresh search trajectory.

check_develop(design, weights=None)[source]

Validate and score a candidate design before keeping it.

add_new_designs(weights=None, R=None)[source]

Populate the current generation with newly sampled candidate designs.

to_next_generation(weights=None, seed=1234, optimisation=None)[source]

Advance one generation of the configured search strategy.

clear(weights=None)[source]

Reset the current population while preserving the last best design.

The preserved design’s cached F/Fe/Fd/Fc/Ff were computed under whichever weight vector was active in the phase that just ended (e.g. a Fe-only or Fd-only calibration prerun). Comparing that stale score directly against designs freshly scored under a different weight vector is invalid – component scores live on different numeric scales, so a leftover Fe-phase score can spuriously outrank every real candidate in a following Fd-phase (or vice versa). Rescoring the preserved design under weights (the vector that will govern the upcoming phase, defaulting to self.weights) keeps it on the same footing as the rest of the population.

optimise()[source]

Run the full optimisation procedure, including normalization passes.

If Fc/Ff are uncalibrated (FcMax/FfMax left at 1), they are calibrated analytically first. If Fe/Fd have positive weight and are uncalibrated (FeMax/FdMax left at 1), a short preruncycles-generation prerun optimising that metric alone is run to estimate its calibration reference. The main search then runs for cycles generations (or until convergence triggers early stopping).

Returns:

self, with designs holding the final generation and bestdesign holding the single highest-scoring design found. Call evaluate() (or selected_design(), which calls it automatically) to obtain clustered representative outputs.

Return type:

Optimisation

selected_design(rank=0)[source]

Return one evaluated representative design from the current selected outputs.

This is the recommended public entry point for retrieving a design after optimise(); it calls evaluate() automatically the first time it is needed.

Parameters:

rank (int) – Index into the outdes clustered representative designs (0-indexed). Each cluster’s representative is the highest-scoring design within that cluster; clusters are not necessarily ordered by score, so rank=0 is one representative design rather than guaranteed to be the single global best (use bestdesign for that).

Returns:

The representative design for the requested cluster rank.

Return type:

Design

evaluate()[source]

Cluster final designs and choose representative reported outputs.

Clusters the final generation’s designs into outdes groups via k-means on their convolved design matrices, then within each cluster keeps the highest-scoring design as that cluster’s representative. Reorders self.designs so cluster representatives are retrievable via self.out (populated here) and selected_design().

Returns:

self, with designs reordered by cluster, out holding each cluster’s representative-design index, clus holding each reordered design’s cluster label, and cov holding the pairwise design-signal correlation matrix.

Return type:

Optimisation

download()[source]

Write report artifacts, schedule exports, and onset files to disk.

static pearsonr(signals, nstim)[source]

Compute pairwise mean regressor correlations between candidate designs.

Utility Modules

generate

neurodesign.generate.order(nstim, ntrials, probabilities, ordertype, seed=None, rng=None)[source]

Sample a flat stimulus order for legacy one-event design modes.

Parameters define the number of stimulus categories, desired sequence length, target category probabilities, and the sampling strategy (random, blocked, or msequence).

neurodesign.generate.iti(ntrials, model, min=None, mean=None, max=None, lam=None, resolution=0.1, seed=None, rng=None)[source]

Sample a legacy event-aligned ITI vector.

The returned vector always has length ntrials and begins with 0 so that element i can be interpreted as the gap immediately preceding the i-th event in the historical API.

msequence

Generate m sequences.

Loosely translated from http://fmriserver.ucsd.edu/ttliu

class neurodesign.msequence.Msequence[source]

Bases: object

Create instance for an order of experimental trials.

GenMseq(mLen, stimtypeno, seed)[source]

Generate a random msequence given the length of the desired sequence and the number of different values.

Parameters:
  • stimtypeno (int) – Number of different stimulus types

  • mLen (int) – The length of the requested msequence (will be shorter than full msequence)

  • seed (int) – Seed with which msequence is sampled.

Mseq(baseVal, powerVal, shift=None, whichSeq=None, userTaps=None)[source]

Generate a specific msequence given the base and power values.

Parameters:
  • baseVal (int) – The base value of the msequence (equivalent to number of stimuli)

  • powerVal (int) – The power of the msequence

  • shift (int | None) – Shift of the msequence

  • whichSeq (int | None) – Index of the sequence desired in the taps file.

  • userTaps (list) – if user wants to specify own polynomial taps

tapsfnc()[source]

Generate taps leading to msequences.

static qadd(a, b, base)[source]

Add two elements of the Galois field of the given base via lookup table.

static qmult(a, b, base)[source]

Multiply two elements of the Galois field of the given base via lookup table.

report

neurodesign.report.make_report(population, outfile='NeuroDesign.pdf')[source]

Create a report of a finished design optimisation.

class neurodesign.report.PdfImage(img_data, width=200, height=200)[source]

Bases: Flowable

wrap(availWidth, availHeight)[source]

This will be called by the enclosing frame before objects are asked their size, drawn or whatever. It returns the size actually used.

draw()[source]