Skip to content

Moved wrapper, cleaner imports #39

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 25, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
2 changes: 2 additions & 0 deletions .github/workflows/create-tag.yml
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@ on:
workflow_dispatch:
workflow_call:
push:
branches:
- main
paths:
- pyproject.toml

2 changes: 1 addition & 1 deletion .mpython/templates/class_header.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from <pkgname>.__wrapper__ import Runtime, MatlabClass
from mpython import Runtime, MatlabClass


class <classname>(MatlabClass):
2 changes: 1 addition & 1 deletion .mpython/templates/docstring.py
Original file line number Diff line number Diff line change
@@ -4,4 +4,4 @@
[Matlab code]( https://github.com/spm/spm/blob/main/<rfilepath> )

Copyright (C) 1995-2025 Functional Imaging Laboratory, Department of Imaging Neuroscience, UCL
"""
"""
28 changes: 0 additions & 28 deletions .mpython/templates/setup.py

This file was deleted.

11 changes: 11 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.11.2
hooks:
# Run the linter.
- id: ruff
args: [ --fix, --ignore=F811]
# Run the formatter.
- id: ruff-format

47 changes: 22 additions & 25 deletions examples/DCM_ERP.py
Original file line number Diff line number Diff line change
@@ -6,42 +6,43 @@
you have to change 'Pbase' to your own analysis-directory, and choose a name ('DCM.xY.Dfile')
of an existing SPM for M/EEG-file with at least two evoked responses.
"""

import os
import spm

num = spm.Array.from_any

# Please replace filenames etc. by your own.
# ----------------------------------------------------------------------
spm.spm('defaults', 'EEG')
spm.spm("defaults", "EEG")

# Data and analysis directories
# ----------------------------------------------------------------------

Pbase = os.path.dirname(__file__) # directory with your data,
Pbase = os.path.dirname(__file__) # directory with your data,

Pdata = os.path.join(Pbase, '.') # data directory in Pbase
Panalysis = os.path.join(Pbase, '.') # analysis directory in Pbase
Pdata = os.path.join(Pbase, ".") # data directory in Pbase
Panalysis = os.path.join(Pbase, ".") # analysis directory in Pbase

os.chdir(Pbase)

# Data filename
# ----------------------------------------------------------------------
DCM = spm.Struct()
DCM.xY.Dfile = 'maeMdfspm8_subject1'
DCM.xY.Dfile = "maeMdfspm8_subject1"

# Parameters and options used for setting up model
# ----------------------------------------------------------------------
DCM.options.analysis = 'ERP' # analyze evoked responses
DCM.options.model = 'ERP' # ERP model
DCM.options.spatial = 'IMG' # spatial model
DCM.options.trials = num([1, 2]) # index of ERPs within ERP/ERF file
DCM.options.Tdcm[0] = 0 # start of peri-stimulus time to be modelled
DCM.options.Tdcm[1] = 200 # end of peri-stimulus time to be modelled
DCM.options.Nmodes = 8 # nr of modes for data selection
DCM.options.h = 1 # nr of DCT components
DCM.options.onset = 60 # selection of onset (prior mean)
DCM.options.D = 1 # downsampling
DCM.options.analysis = "ERP" # analyze evoked responses
DCM.options.model = "ERP" # ERP model
DCM.options.spatial = "IMG" # spatial model
DCM.options.trials = num([1, 2]) # index of ERPs within ERP/ERF file
DCM.options.Tdcm[0] = 0 # start of peri-stimulus time to be modelled
DCM.options.Tdcm[1] = 200 # end of peri-stimulus time to be modelled
DCM.options.Nmodes = 8 # nr of modes for data selection
DCM.options.h = 1 # nr of DCT components
DCM.options.onset = 60 # selection of onset (prior mean)
DCM.options.D = 1 # downsampling

# ----------------------------------------------------------------------
# Data and spatial model
@@ -51,14 +52,10 @@
# ----------------------------------------------------------------------
# Location priors for dipoles
# ----------------------------------------------------------------------
DCM.Lpos = num([
[-42, -22, 7],
[46, -14, 8],
[-61, -32, 8],
[59, -25, 8],
[46, 20, 8]
]).T
DCM.Sname = ['left AI', 'right A1', 'left STG', 'right STG', 'right IFG']
DCM.Lpos = num(
[[-42, -22, 7], [46, -14, 8], [-61, -32, 8], [59, -25, 8], [46, 20, 8]]
).T
DCM.Sname = ["left AI", "right A1", "left STG", "right STG", "right IFG"]
Nareas = DCM.Lpos.shape[1]

# ----------------------------------------------------------------------
@@ -98,11 +95,11 @@
# Between trial effects
# ----------------------------------------------------------------------
DCM.xU.X = num([[0, 1]]).T
DCM.xU.name = ['rare']
DCM.xU.name = ["rare"]

# ----------------------------------------------------------------------
# Invert
# ----------------------------------------------------------------------
DCM.name = 'DCMexample'
DCM.name = "DCMexample"

DCM = spm.spm_dcm_erp(DCM)
79 changes: 40 additions & 39 deletions examples/DCM_fMRI_Attention.ipynb
Original file line number Diff line number Diff line change
@@ -7,12 +7,10 @@
"metadata": {},
"outputs": [],
"source": [
"from spm import * \n",
"from spm import *\n",
"\n",
"import numpy as np\n",
"import os.path as op\n",
"import os \n",
"import scipy.io as sio"
"import os.path as op"
]
},
{
@@ -40,15 +38,20 @@
"metadata": {},
"outputs": [],
"source": [
"data_path = op.join('data', 'attention')\n",
"zip_path = op.join('data', 'attention.zip')\n",
"data_path = op.join(\"data\", \"attention\")\n",
"zip_path = op.join(\"data\", \"attention.zip\")\n",
"if not op.isdir(data_path):\n",
" if not op.isfile(zip_path):\n",
" import wget\n",
" wget.download('https://www.fil.ion.ucl.ac.uk/spm/download/data/attention/attention.zip', 'data')\n",
"\n",
" wget.download(\n",
" \"https://www.fil.ion.ucl.ac.uk/spm/download/data/attention/attention.zip\",\n",
" \"data\",\n",
" )\n",
"\n",
" import shutil\n",
" shutil.unpack_archive(zip_path, 'data', 'zip')"
"\n",
" shutil.unpack_archive(zip_path, \"data\", \"zip\")"
]
},
{
@@ -79,8 +82,8 @@
}
],
"source": [
"spm('Defaults','fMRI')\n",
"spm_jobman('initcfg', nargout=0)"
"spm(\"Defaults\", \"fMRI\")\n",
"spm_jobman(\"initcfg\", nargout=0)"
]
},
{
@@ -108,7 +111,7 @@
"metadata": {},
"outputs": [],
"source": [
"SPM = Runtime.call('load', op.join(data_path, 'GLM', 'SPM.mat'))['SPM']"
"SPM = Runtime.call(\"load\", op.join(data_path, \"GLM\", \"SPM.mat\"))[\"SPM\"]"
]
},
{
@@ -118,11 +121,11 @@
"metadata": {},
"outputs": [],
"source": [
"DCM = Struct() \n",
"DCM = Struct()\n",
"\n",
"xY1 = Runtime.call('load', op.join(data_path,'GLM','VOI_V1_1.mat'))['xY'];\n",
"xY2 = Runtime.call('load', op.join(data_path,'GLM','VOI_V5_1.mat'))['xY'];\n",
"xY3 = Runtime.call('load', op.join(data_path,'GLM','VOI_SPC_1.mat'))['xY'];\n",
"xY1 = Runtime.call(\"load\", op.join(data_path, \"GLM\", \"VOI_V1_1.mat\"))[\"xY\"]\n",
"xY2 = Runtime.call(\"load\", op.join(data_path, \"GLM\", \"VOI_V5_1.mat\"))[\"xY\"]\n",
"xY3 = Runtime.call(\"load\", op.join(data_path, \"GLM\", \"VOI_SPC_1.mat\"))[\"xY\"]\n",
"\n",
"DCM.xY = StructArray(xY1, xY2, xY3)"
]
@@ -134,8 +137,8 @@
"metadata": {},
"outputs": [],
"source": [
"DCM.n = 3; \n",
"DCM.v = xY1['u'].shape[0]; "
"DCM.n = 3\n",
"DCM.v = xY1[\"u\"].shape[0]"
]
},
{
@@ -165,13 +168,13 @@
"outputs": [],
"source": [
"DCM.Y = Struct()\n",
"DCM.Y.dt = SPM.xY.RT;\n",
"DCM.Y.X0 = xY1.X0;\n",
"DCM.Y.dt = SPM.xY.RT\n",
"DCM.Y.X0 = xY1.X0\n",
"\n",
"DCM.Y.y = np.concatenate([xY.u for xY in (xY1, xY2, xY3)], axis=1)\n",
"DCM.Y.name = [xY.name for xY in (xY1, xY2, xY3)]\n",
"DCM.Y.name = [xY.name for xY in (xY1, xY2, xY3)]\n",
"\n",
"DCM.Y.Q = spm_Ce(np.ones((1,DCM.n))*DCM.v);"
"DCM.Y.Q = spm_Ce(np.ones((1, DCM.n)) * DCM.v)"
]
},
{
@@ -198,11 +201,9 @@
"outputs": [],
"source": [
"DCM.U = Struct()\n",
"DCM.U.dt = SPM.Sess.U[0].dt;\n",
"DCM.U.name = [u.name for u in SPM.Sess.U];\n",
"DCM.U.u = np.concatenate([\n",
" u.u[32:] for u in SPM.Sess.U\n",
" ], axis=1);"
"DCM.U.dt = SPM.Sess.U[0].dt\n",
"DCM.U.name = [u.name for u in SPM.Sess.U]\n",
"DCM.U.u = np.concatenate([u.u[32:] for u in SPM.Sess.U], axis=1)"
]
},
{
@@ -230,14 +231,14 @@
"metadata": {},
"outputs": [],
"source": [
"DCM.delays = np.repeat([[SPM['xY']['RT']/2]], DCM.n, 1);\n",
"DCM.TE = 0.04;\n",
"DCM.delays = np.repeat([[SPM[\"xY\"][\"RT\"] / 2]], DCM.n, 1)\n",
"DCM.TE = 0.04\n",
"\n",
"DCM.options = Struct()\n",
"DCM.options.nonlinear = 0;\n",
"DCM.options.two_state = 0;\n",
"DCM.options.stochastic = 0;\n",
"DCM.options.nograph = 1;"
"DCM.options.nonlinear = 0\n",
"DCM.options.two_state = 0\n",
"DCM.options.stochastic = 0\n",
"DCM.options.nograph = 1"
]
},
{
@@ -265,11 +266,11 @@
"outputs": [],
"source": [
"DCM.a = np.array([[1, 1, 0], [1, 1, 1], [0, 1, 1]])\n",
"DCM.b = np.zeros((3,3,3)); \n",
"DCM.b[1,0,1] = 1; \n",
"DCM.b[1,2,2] = 1;\n",
"DCM.b = np.zeros((3, 3, 3))\n",
"DCM.b[1, 0, 1] = 1\n",
"DCM.b[1, 2, 2] = 1\n",
"DCM.c = np.array([[1, 0, 0], [0, 0, 0], [0, 0, 0]])\n",
"DCM.d = np.zeros((3,3,0));\n",
"DCM.d = np.zeros((3, 3, 0))\n",
"\n",
"DCMbwd = spm_dcm_estimate(DCM)"
]
@@ -295,9 +296,9 @@
"metadata": {},
"outputs": [],
"source": [
"DCM.b = np.zeros((3,3,3)); \n",
"DCM.b[1,0,1] = 1; \n",
"DCM.b[1,0,2] = 1;\n",
"DCM.b = np.zeros((3, 3, 3))\n",
"DCM.b[1, 0, 1] = 1\n",
"DCM.b[1, 0, 2] = 1\n",
"\n",
"DCMfwd = spm_dcm_estimate(DCM)"
]
Loading