|
7 | 7 | import os
|
8 | 8 |
|
9 | 9 | from ... import logging
|
10 |
| -from ..base import TraitedSpec, File, traits, InputMultiPath, OutputMultiPath, isdefined |
11 |
| -from .base import FSCommand, FSTraitedSpec, FSCommandOpenMP, FSTraitedSpecOpenMP |
| 10 | +from ..base import TraitedSpec, File, traits, InputMultiPath, OutputMultiPath, isdefined, InputMultiObject, Directory |
| 11 | +from .base import FSCommand, FSTraitedSpec, FSCommandOpenMP, FSTraitedSpecOpenMP, CommandLine |
| 12 | +from .preprocess import ReconAllInputSpec |
| 13 | +from ..io import FreeSurferSource |
12 | 14 |
|
13 | 15 | __docformat__ = "restructuredtext"
|
14 | 16 | iflogger = logging.getLogger("nipype.interface")
|
@@ -251,3 +253,200 @@ def _list_outputs(self):
|
251 | 253 | outputs = self.output_spec().get()
|
252 | 254 | outputs["out_file"] = os.path.abspath(self.inputs.out_file)
|
253 | 255 | return outputs
|
| 256 | + |
| 257 | + |
| 258 | +class BaseReconAllInputSpec(ReconAllInputSpec): |
| 259 | + subject_id = traits.Str(argstr="-subjid %s", desc="subject name") |
| 260 | + base_id = traits.Str(argstr="-base %s", desc="base template name", xor=["subject_id"]) |
| 261 | + timepoints = InputMultiObject( |
| 262 | + traits.Str(), argstr="-tp %s...", desc="processed time point to use in template" |
| 263 | + ) |
| 264 | + |
| 265 | +class BaseReconAllOutputSpec(FreeSurferSource.output_spec): |
| 266 | + subjects_dir = Directory(exists=True, desc="FreeSurfer subjects directory") |
| 267 | + subject_id = traits.Str(desc="Subject template name") |
| 268 | + |
| 269 | +class BaseReconAll(CommandLine): |
| 270 | + """Uses the longitudinal pipeline of recon-all to create a template for a given number of subject's sessions. |
| 271 | +
|
| 272 | + Examples |
| 273 | + -------- |
| 274 | + >>> from nipype.interfaces.freesurfer.longitudinal import BaseReconAll |
| 275 | + >>> baserecon = BaseReconAll() |
| 276 | + >>> baserecon.inputs.base_id = 'sub-template' |
| 277 | + >>> baserecon.inputs.timepoints = ['ses-1','ses-2'] |
| 278 | + >>> baserecon.inputs.directive = 'all' |
| 279 | + >>> baserecon.inputs.subjects_dir = '.' |
| 280 | + >>> baserecon.cmdline |
| 281 | + 'recon-all -all -base sub-template -sd . -tp ses-1 -tp ses-2' |
| 282 | + """ |
| 283 | + |
| 284 | + _cmd = "recon-all" |
| 285 | + input_spec = BaseReconAllInputSpec |
| 286 | + output_spec = BaseReconAllOutputSpec |
| 287 | + _can_resume = True |
| 288 | + force_run = False |
| 289 | + |
| 290 | + def _gen_subjects_dir(self): |
| 291 | + return os.getcwd() |
| 292 | + |
| 293 | + |
| 294 | + def _gen_filename(self, name): |
| 295 | + if name == "subjects_dir": |
| 296 | + return self._gen_subjects_dir() |
| 297 | + return None |
| 298 | + |
| 299 | + |
| 300 | + def _list_outputs(self): |
| 301 | + if isdefined(self.inputs.subjects_dir): |
| 302 | + subjects_dir = self.inputs.subjects_dir |
| 303 | + else: |
| 304 | + subjects_dir = self._gen_subjects_dir() |
| 305 | + |
| 306 | + if isdefined(self.inputs.hemi): |
| 307 | + hemi = self.inputs.hemi |
| 308 | + else: |
| 309 | + hemi = "both" |
| 310 | + |
| 311 | + outputs = self._outputs().get() |
| 312 | + |
| 313 | + outputs.update( |
| 314 | + FreeSurferSource(subject_id=self.inputs.base_id, |
| 315 | + subjects_dir=subjects_dir, hemi=hemi)._list_outputs() |
| 316 | + ) |
| 317 | + outputs["subject_id"] = self.inputs.base_id |
| 318 | + outputs["subjects_dir"] = subjects_dir |
| 319 | + return outputs |
| 320 | + |
| 321 | + |
| 322 | + def _is_resuming(self): |
| 323 | + subjects_dir = self.inputs.subjects_dir |
| 324 | + if not isdefined(subjects_dir): |
| 325 | + subjects_dir = self._gen_subjects_dir() |
| 326 | + if os.path.isdir(os.path.join(subjects_dir, self.inputs.base_id, "mri")): |
| 327 | + return True |
| 328 | + return False |
| 329 | + |
| 330 | + |
| 331 | + def _format_arg(self, name, trait_spec, value): |
| 332 | + return super(BaseReconAll, self)._format_arg(name, trait_spec, value) |
| 333 | + |
| 334 | + |
| 335 | + @property |
| 336 | + def cmdline(self): |
| 337 | + cmd = super(BaseReconAll, self).cmdline |
| 338 | + |
| 339 | + if not self._is_resuming(): |
| 340 | + return cmd |
| 341 | + |
| 342 | + subjects_dir = self.inputs.subjects_dir |
| 343 | + if not isdefined(subjects_dir): |
| 344 | + subjects_dir = self._gen_subjects_dir() |
| 345 | + |
| 346 | + directive = self.inputs.directive |
| 347 | + if not isdefined(directive): |
| 348 | + steps = [] |
| 349 | + |
| 350 | + iflogger.info(f"recon-all: {cmd}") |
| 351 | + return cmd |
| 352 | + |
| 353 | + |
| 354 | +class LongReconAllInputSpec(ReconAllInputSpec): |
| 355 | + subject_id = traits.Str(argstr="-subjid %s", desc="subject name") |
| 356 | + long_id = traits.Tuple( |
| 357 | + traits.Str(), |
| 358 | + traits.Str(), |
| 359 | + argstr="-long %s %s", |
| 360 | + desc="longitudinal name followed by base template name", |
| 361 | + xor=["subject_id"] |
| 362 | + ) |
| 363 | + |
| 364 | + |
| 365 | +class LongReconAllOutputSpec(FreeSurferSource.output_spec): |
| 366 | + subjects_dir = Directory(exists=True, desc="FreeSurfer subjects directory") |
| 367 | + subject_id = traits.Str(desc="Subject template name") |
| 368 | + |
| 369 | + |
| 370 | +class LongReconAll(CommandLine): |
| 371 | + """Uses FreeSurfer's longitudinal recon-all to process a subject given |
| 372 | + the previously processed base template. |
| 373 | +
|
| 374 | + Examples |
| 375 | + --------- |
| 376 | +
|
| 377 | + >>> from nipype.interfaces.freesurfer.longitudinal import LongReconAll |
| 378 | + >>> longrecon = LongReconAll() |
| 379 | + >>> longrecon.inputs.long_id = ("ses-1","sub-template") |
| 380 | + >>> longrecon.inputs.directive = "all" |
| 381 | + >>> longrecon.inputs.subjects_dir = "." |
| 382 | + >>> longrecon.cmdline |
| 383 | + 'recon-all -all -long ses-1 sub-template -sd .' |
| 384 | + """ |
| 385 | + |
| 386 | + _cmd = "recon-all" |
| 387 | + input_spec = LongReconAllInputSpec |
| 388 | + output_spec = LongReconAllOutputSpec |
| 389 | + _can_resume = True |
| 390 | + force_run = False |
| 391 | + |
| 392 | + def _gen_subjects_dir(self): |
| 393 | + return os.getcwd() |
| 394 | + |
| 395 | + def _gen_filename(self, name): |
| 396 | + if name == "subjects_dir": |
| 397 | + return self._gen_subjects_dir() |
| 398 | + return None |
| 399 | + |
| 400 | + def _list_outputs(self): |
| 401 | + subject_id = f"{self.inputs.long_id[0]}.long.{self.inputs.long_id[1]}" |
| 402 | + |
| 403 | + if isdefined(self.inputs.subjects_dir): |
| 404 | + subjects_dir = self.inputs.subjects_dir |
| 405 | + else: |
| 406 | + subjects_dir = self._gen_subjects_dir() |
| 407 | + |
| 408 | + if isdefined(self.inputs.hemi): |
| 409 | + hemi = self.inputs.hemi |
| 410 | + else: |
| 411 | + hemi = "both" |
| 412 | + |
| 413 | + outputs = self._outputs().get() |
| 414 | + |
| 415 | + outputs.update( |
| 416 | + FreeSurferSource( |
| 417 | + subject_id=subject_id, subjects_dir=subjects_dir, hemi=hemi |
| 418 | + )._list_outputs() |
| 419 | + ) |
| 420 | + outputs["subject_id"] = subject_id |
| 421 | + outputs["subjects_dir"] = subjects_dir |
| 422 | + return outputs |
| 423 | + |
| 424 | + def _is_resuming(self): |
| 425 | + subjects_dir = self.inputs.subjects_dir |
| 426 | + subject_id = f"{self.inputs.long_id[0]}.long{self.inputs.long_id[1]}" |
| 427 | + if not isdefined(subjects_dir): |
| 428 | + subjects_dir = self._gen_subjects_dir() |
| 429 | + if os.path.isdir(os.path.join(subjects_dir, subject_id, "mri")): |
| 430 | + return True |
| 431 | + return False |
| 432 | + |
| 433 | + def _format_arg(self, name, trait_spec, value): |
| 434 | + return super(LongReconAll, self)._format_arg(name, trait_spec, value) |
| 435 | + |
| 436 | + @property |
| 437 | + def cmdline(self): |
| 438 | + cmd = super(LongReconAll, self).cmdline |
| 439 | + |
| 440 | + if not self._is_resuming(): |
| 441 | + return cmd |
| 442 | + |
| 443 | + subjects_dir = self.inputs.subjects_dir |
| 444 | + if not isdefined(subjects_dir): |
| 445 | + subjects_dir = self._gen_subjects_dir() |
| 446 | + |
| 447 | + directive = self.inputs.directive |
| 448 | + if not isdefined(directive): |
| 449 | + steps = [] |
| 450 | + |
| 451 | + iflogger.info(f"recon-all: {cmd}") |
| 452 | + return cmd |
0 commit comments