guohanghui commited on
Commit
ccad381
·
verified ·
1 Parent(s): b14d8e2

Update nilearn/mcp_output/mcp_plugin/mcp_service.py

Browse files
nilearn/mcp_output/mcp_plugin/mcp_service.py CHANGED
@@ -1,97 +1,274 @@
1
  import os
2
  import sys
3
-
4
- # Path settings to include the local source directory
5
- source_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "source")
6
- if source_path not in sys.path:
7
- sys.path.insert(0, source_path)
8
 
9
  from fastmcp import FastMCP
 
10
 
11
- # Import core modules from the local source directory
12
- from nilearn.image import image
13
- from nilearn.glm import first_level
14
- from nilearn.decoding import decoder
15
- from nilearn.plotting import plotting
 
16
 
17
  # Create the FastMCP service application
18
  mcp = FastMCP("nilearn_service")
19
 
20
- @mcp.tool(name="load_image", description="Load and process a neuroimaging file")
21
- def load_image(file_path: str) -> dict:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  """
23
- Load and process a neuroimaging file.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  Parameters:
26
- - file_path (str): Path to the neuroimaging file.
 
27
 
28
  Returns:
29
- - dict: A dictionary containing success, result, or error.
30
  """
31
  try:
32
- img = image.load_img(file_path)
33
- return {"success": True, "result": img}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  except Exception as e:
35
- return {"success": False, "error": str(e)}
 
36
 
37
- @mcp.tool(name="run_glm", description="Run a General Linear Model on fMRI data")
38
- def run_glm(data: str, design_matrix: str) -> dict:
 
 
 
39
  """
40
- Run a General Linear Model on fMRI data.
41
 
42
  Parameters:
43
- - data (str): Path to the fMRI data.
44
- - design_matrix (str): Path to the design matrix file.
45
 
46
  Returns:
47
- - dict: A dictionary containing success, result, or error.
48
  """
49
  try:
50
- fmri_img = image.load_img(data)
51
- design = first_level.make_first_level_design_matrix(fmri_img, design_matrix)
52
- model = first_level.FirstLevelModel()
53
- model = model.fit(fmri_img, design_matrices=design)
54
- return {"success": True, "result": model}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  except Exception as e:
56
- return {"success": False, "error": str(e)}
57
 
58
- @mcp.tool(name="decode_brain_data", description="Decode brain data using a machine learning model")
59
- def decode_brain_data(data: str, labels: str) -> dict:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  """
61
- Decode brain data using a machine learning model.
62
 
63
  Parameters:
64
- - data (str): Path to the brain data.
65
- - labels (str): Path to the labels file.
 
66
 
67
  Returns:
68
- - dict: A dictionary containing success, result, or error.
69
  """
70
  try:
71
- brain_data = image.load_img(data)
72
- model = decoder.Decoder()
73
- model.fit(brain_data, labels)
74
- return {"success": True, "result": model}
 
 
 
 
 
 
 
 
75
  except Exception as e:
76
- return {"success": False, "error": str(e)}
 
77
 
78
- @mcp.tool(name="plot_stat_map", description="Plot a statistical map")
79
- def plot_stat_map(stat_map: str, bg_img: str) -> dict:
80
  """
81
- Plot a statistical map.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
 
83
  Parameters:
84
- - stat_map (str): Path to the statistical map.
85
- - bg_img (str): Path to the background image.
86
 
87
  Returns:
88
- - dict: A dictionary containing success, result, or error.
89
  """
90
  try:
91
- display = plotting.plot_stat_map(stat_map, bg_img=bg_img)
92
- return {"success": True, "result": display}
 
 
 
 
 
93
  except Exception as e:
94
- return {"success": False, "error": str(e)}
 
95
 
96
  def create_app() -> FastMCP:
97
  """
 
1
  import os
2
  import sys
3
+ from typing import List, Optional
 
 
 
 
4
 
5
  from fastmcp import FastMCP
6
+ import numpy as np
7
 
8
+ # Import nilearn modules (from PyPI installed package)
9
+ from nilearn import image, datasets, plotting
10
+ from nilearn.maskers import NiftiMasker
11
+ from nilearn.connectome import ConnectivityMeasure
12
+ from nilearn.decoding import Decoder
13
+ from nilearn.glm.first_level import FirstLevelModel, make_first_level_design_matrix
14
 
15
  # Create the FastMCP service application
16
  mcp = FastMCP("nilearn_service")
17
 
18
+
19
+ @mcp.tool(name="get_nilearn_version", description="Get nilearn library version")
20
+ def get_nilearn_version() -> dict:
21
+ """
22
+ Get the nilearn library version.
23
+
24
+ Returns:
25
+ - dict: Version information.
26
+ """
27
+ try:
28
+ import nilearn
29
+ return {
30
+ "success": True,
31
+ "result": {
32
+ "version": nilearn.__version__,
33
+ "description": "Machine learning for neuroimaging in Python"
34
+ },
35
+ "error": None
36
+ }
37
+ except Exception as e:
38
+ return {"success": False, "result": None, "error": str(e)}
39
+
40
+
41
+ @mcp.tool(name="list_available_atlases", description="List available brain atlases in nilearn")
42
+ def list_available_atlases() -> dict:
43
  """
44
+ List available brain atlases in nilearn datasets.
45
+
46
+ Returns:
47
+ - dict: Available atlases and their descriptions.
48
+ """
49
+ try:
50
+ atlases = {
51
+ "aal": "Automated Anatomical Labeling atlas",
52
+ "destrieux": "Destrieux cortical atlas (aparc.a2009s)",
53
+ "harvard_oxford": "Harvard-Oxford cortical/subcortical atlas",
54
+ "msdl": "MSDL probabilistic atlas (39 regions)",
55
+ "pauli_2017": "Subcortical atlas (Pauli et al. 2017)",
56
+ "schaefer_2018": "Schaefer cortical parcellation",
57
+ "yeo_2011": "Yeo intrinsic functional networks (7 or 17 networks)",
58
+ "difumo": "DiFuMo atlas (64, 128, 256, 512, or 1024 dimensions)",
59
+ "talairach": "Talairach atlas"
60
+ }
61
+ return {"success": True, "result": atlases, "error": None}
62
+ except Exception as e:
63
+ return {"success": False, "result": None, "error": str(e)}
64
+
65
+
66
+ @mcp.tool(name="fetch_atlas", description="Fetch a brain atlas from nilearn datasets")
67
+ def fetch_atlas(atlas_name: str, n_rois: int = None) -> dict:
68
+ """
69
+ Fetch a brain atlas from nilearn datasets.
70
 
71
  Parameters:
72
+ - atlas_name: Name of the atlas ('aal', 'msdl', 'schaefer_2018', 'yeo_2011', etc.)
73
+ - n_rois: Number of ROIs (for atlases that support it)
74
 
75
  Returns:
76
+ - dict: Atlas information including number of regions.
77
  """
78
  try:
79
+ if atlas_name == "aal":
80
+ atlas = datasets.fetch_atlas_aal()
81
+ return {
82
+ "success": True,
83
+ "result": {
84
+ "atlas_name": "AAL",
85
+ "n_regions": len(atlas.labels),
86
+ "labels": atlas.labels[:10], # First 10 labels as sample
87
+ "description": "Automated Anatomical Labeling atlas"
88
+ },
89
+ "error": None
90
+ }
91
+ elif atlas_name == "msdl":
92
+ atlas = datasets.fetch_atlas_msdl()
93
+ return {
94
+ "success": True,
95
+ "result": {
96
+ "atlas_name": "MSDL",
97
+ "n_regions": len(atlas.labels),
98
+ "labels": atlas.labels,
99
+ "description": "Multi-Subject Dictionary Learning atlas"
100
+ },
101
+ "error": None
102
+ }
103
+ elif atlas_name == "schaefer_2018":
104
+ n_rois = n_rois or 100
105
+ atlas = datasets.fetch_atlas_schaefer_2018(n_rois=n_rois)
106
+ return {
107
+ "success": True,
108
+ "result": {
109
+ "atlas_name": f"Schaefer {n_rois}",
110
+ "n_regions": n_rois,
111
+ "labels": list(atlas.labels[:10]),
112
+ "description": "Schaefer cortical parcellation"
113
+ },
114
+ "error": None
115
+ }
116
+ else:
117
+ return {"success": False, "result": None, "error": f"Unknown atlas: {atlas_name}"}
118
  except Exception as e:
119
+ return {"success": False, "result": None, "error": str(e)}
120
+
121
 
122
+ @mcp.tool(name="compute_connectivity_matrix", description="Compute functional connectivity matrix from time series")
123
+ def compute_connectivity_matrix(
124
+ time_series: List[List[float]],
125
+ connectivity_kind: str = "correlation"
126
+ ) -> dict:
127
  """
128
+ Compute functional connectivity matrix from ROI time series.
129
 
130
  Parameters:
131
+ - time_series: 2D list of shape (n_timepoints, n_regions)
132
+ - connectivity_kind: Type of connectivity ('correlation', 'partial correlation', 'covariance')
133
 
134
  Returns:
135
+ - dict: Connectivity matrix and statistics.
136
  """
137
  try:
138
+ ts_array = np.array(time_series)
139
+
140
+ conn_measure = ConnectivityMeasure(kind=connectivity_kind)
141
+ connectivity = conn_measure.fit_transform([ts_array])[0]
142
+
143
+ # Get lower triangle values (excluding diagonal)
144
+ lower_tri = connectivity[np.tril_indices_from(connectivity, k=-1)]
145
+
146
+ return {
147
+ "success": True,
148
+ "result": {
149
+ "shape": list(connectivity.shape),
150
+ "connectivity_kind": connectivity_kind,
151
+ "mean_connectivity": float(np.mean(lower_tri)),
152
+ "std_connectivity": float(np.std(lower_tri)),
153
+ "min_connectivity": float(np.min(lower_tri)),
154
+ "max_connectivity": float(np.max(lower_tri)),
155
+ "matrix_preview": connectivity[:5, :5].tolist() if connectivity.shape[0] >= 5 else connectivity.tolist()
156
+ },
157
+ "error": None
158
+ }
159
  except Exception as e:
160
+ return {"success": False, "result": None, "error": str(e)}
161
 
162
+
163
+ @mcp.tool(name="list_decoding_estimators", description="List available decoding estimators")
164
+ def list_decoding_estimators() -> dict:
165
+ """
166
+ List available machine learning estimators for brain decoding.
167
+
168
+ Returns:
169
+ - dict: Available estimators and their descriptions.
170
+ """
171
+ try:
172
+ estimators = {
173
+ "svc": "Support Vector Classification (linear kernel)",
174
+ "svc_l1": "SVC with L1 penalty for feature selection",
175
+ "svc_l2": "SVC with L2 penalty",
176
+ "logistic": "Logistic Regression",
177
+ "logistic_l1": "Logistic Regression with L1 penalty",
178
+ "logistic_l2": "Logistic Regression with L2 penalty",
179
+ "ridge": "Ridge Regression (for continuous targets)",
180
+ "ridge_classifier": "Ridge Classifier"
181
+ }
182
+ return {"success": True, "result": estimators, "error": None}
183
+ except Exception as e:
184
+ return {"success": False, "result": None, "error": str(e)}
185
+
186
+
187
+ @mcp.tool(name="resample_image", description="Resample a neuroimaging volume to new resolution")
188
+ def resample_image(
189
+ target_affine_diag: List[float] = None,
190
+ target_shape: List[int] = None,
191
+ interpolation: str = "continuous"
192
+ ) -> dict:
193
  """
194
+ Get parameters for resampling neuroimaging data.
195
 
196
  Parameters:
197
+ - target_affine_diag: Diagonal elements of target affine (voxel sizes)
198
+ - target_shape: Target shape [x, y, z]
199
+ - interpolation: 'continuous', 'linear', or 'nearest'
200
 
201
  Returns:
202
+ - dict: Resampling configuration.
203
  """
204
  try:
205
+ if target_affine_diag is None:
206
+ target_affine_diag = [3.0, 3.0, 3.0] # 3mm isotropic
207
+ if target_shape is None:
208
+ target_shape = [61, 73, 61] # MNI152 standard shape at 3mm
209
+
210
+ config = {
211
+ "target_affine_diagonal": target_affine_diag,
212
+ "target_shape": target_shape,
213
+ "interpolation": interpolation,
214
+ "description": f"Resample to {target_affine_diag[0]}mm isotropic resolution"
215
+ }
216
+ return {"success": True, "result": config, "error": None}
217
  except Exception as e:
218
+ return {"success": False, "result": None, "error": str(e)}
219
+
220
 
221
+ @mcp.tool(name="get_glm_contrast_types", description="List available GLM contrast types")
222
+ def get_glm_contrast_types() -> dict:
223
  """
224
+ List available contrast types for first-level GLM analysis.
225
+
226
+ Returns:
227
+ - dict: Contrast types and descriptions.
228
+ """
229
+ try:
230
+ contrasts = {
231
+ "t": "T-contrast: tests linear combination of parameters",
232
+ "F": "F-contrast: tests multiple linear hypotheses simultaneously",
233
+ "effects": {
234
+ "condition_effect": "Main effect of a single condition",
235
+ "differential": "Difference between two conditions (A - B)",
236
+ "conjunction": "Common activation across conditions",
237
+ "interaction": "Interaction between factors"
238
+ },
239
+ "examples": {
240
+ "condition_a": "[1, 0, 0, ...]",
241
+ "condition_a_vs_b": "[1, -1, 0, ...]",
242
+ "any_condition": "[[1, 0, 0], [0, 1, 0], [0, 0, 1]]"
243
+ }
244
+ }
245
+ return {"success": True, "result": contrasts, "error": None}
246
+ except Exception as e:
247
+ return {"success": False, "result": None, "error": str(e)}
248
+
249
+
250
+ @mcp.tool(name="smooth_image", description="Smooth a neuroimaging volume")
251
+ def smooth_image(fwhm: float = 6.0) -> dict:
252
+ """
253
+ Get configuration for smoothing neuroimaging data.
254
 
255
  Parameters:
256
+ - fwhm: Full Width at Half Maximum in mm (default: 6.0)
 
257
 
258
  Returns:
259
+ - dict: Smoothing configuration.
260
  """
261
  try:
262
+ config = {
263
+ "fwhm": fwhm,
264
+ "description": f"Gaussian smoothing with {fwhm}mm FWHM kernel",
265
+ "function": "nilearn.image.smooth_img",
266
+ "usage": f"smoothed_img = smooth_img(img, fwhm={fwhm})"
267
+ }
268
+ return {"success": True, "result": config, "error": None}
269
  except Exception as e:
270
+ return {"success": False, "result": None, "error": str(e)}
271
+
272
 
273
  def create_app() -> FastMCP:
274
  """