Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 36 additions & 7 deletions FastSurferCNN/utils/run_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,45 @@ def out_str(self, encoding="utf-8"):
def err_str(self, encoding="utf-8"):
return self.err.decode(encoding=encoding)

def forward_output(
self,
file: io.TextIOBase | None = None,
encoding: str = "utf-8",
out_prefix: str = "",
err_prefix: str = "!",
):
"""
Forward the content of this MessageBuffer to a file or stream.

Parameters
----------
file : IO.TextIO, optional
The file or stream to which the output should be forwarded (defaults to stdout).
encoding : str, default="utf-8"
Charset to encode.
out_prefix : str, default=""
String to prefix lines from the stdout output.
err_prefix : str, default="!"
String to prefix lines from the stderr output.
"""
if file is None:
from sys import stdout
file = stdout
for line in self.out_str(encoding=encoding).splitlines():
print(f"{out_prefix}{line}", file=file)
for line in self.err_str(encoding=encoding).splitlines():
print(f"{err_prefix}{line}", file=file)
Comment thread
dkuegler marked this conversation as resolved.


class Popen(subprocess.Popen):
"""
Extension of subprocess.Popen for convenience.
"""
_starttime: datetime | None = None

def __init__(self, *args, **kwargs):
def __init__(self, args, /, **kwargs):
self._starttime = datetime.now()
super().__init__(*args, **kwargs)
super().__init__(args, **kwargs)
Comment thread
dkuegler marked this conversation as resolved.

def messages(self, timeout: float) -> Generator[MessageBuffer, None, None]:
"""
Expand Down Expand Up @@ -216,7 +245,7 @@ async def async_finish(self, timeout: float = None) -> MessageBuffer:
def forward_output(
self,
file: io.TextIOBase | None = None,
encoding: str | None = None,
encoding: str = "utf-8",
timeout: float | None = None,
out_prefix: str = "",
err_prefix: str = "!",
Expand All @@ -228,7 +257,7 @@ def forward_output(
----------
file : IO.TextIO, optional
The file or stream to which the output should be forwarded.
encoding : str, optional
encoding : str, default="utf-8"
Charset to encode.
timeout : float, optional
Interval to let the child process, before returning to the parent (this) process.
Expand All @@ -255,15 +284,15 @@ def forward_output(


class PyPopen(Popen):
def __init__(self, args: Sequence[str], *_args, **kwargs):
def __init__(self, args: Sequence[str], /, **kwargs):
"""
Create a python process with same flags, and additional args.

Parameters
----------
args : Sequence[str]
Arguments to python process.
additional arguments as in subprocess.Popen
additional keyword arguments as in subprocess.Popen

See Also
--------
Expand All @@ -289,5 +318,5 @@ def __init__(self, args: Sequence[str], *_args, **kwargs):
flags = "".join(k for k, v in all_flags.items() if getattr(sys.flags, v) == 1)
flags = [] if len(flags) == 0 else ["-" + flags]
super().__init__(
[sys.executable] + flags + list(args), *_args, **kwargs
[sys.executable] + flags + list(args), **kwargs
)
2 changes: 1 addition & 1 deletion recon_surf/recon-surf.sh
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,7 @@ for hemi in lh rh ; do
RunIt "$cmd" "$LF" "$CMDF"
else
# instead of mris_sphere, directly project to sphere with spectral approach equivalent to -qsphere (23sec)
cmda=("${binpath}spherically_project_wrapper.py" --hemi "$hemi" --sdir "$sdir" --subject "$subject")
cmda=("${binpath}spherically_project_wrapper.py" --hemi "$hemi" --sd "$SUBJECTS_DIR" --subject "$subject")
run_it_cmdf "$LF" "$CMDF" $python "${cmda[@]}" --threads "$threads_hemi"
fi

Expand Down
21 changes: 14 additions & 7 deletions recon_surf/spherically_project_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,20 @@ def setup_options():
options : argparse.Namespace
Namespace object holding options.
"""
from os import environ
# Validation settings
parser = argparse.ArgumentParser(description="Wrapper for spherical projection")

parser.add_argument("--hemi", type=str, help="Hemisphere to analyze.")
parser.add_argument("--sdir", type=Path, help="Surface directory of subject.")
parser.add_argument("--subject", type=str, help="Name (ID) of subject.")
parser.add_argument("--threads", type=int, help="Number of threads to use.")
parser.add_argument("--hemi", choices=("lh", "rh"), help="Hemisphere to analyze.", required=True)
parser.add_argument(
"--sd",
type=Path,
help="Subjects directory $SUBJECTS_DIR.",
default=Path(environ.get("SUBJECTS_DIR", Path.cwd())),
required="SUBJECTS_DIR" not in environ,
)
parser.add_argument("--subject", type=str, help="Name (ID) of subject.", required=True)
parser.add_argument("--threads", type=int, help="Number of threads to use.", default=1)

args = parser.parse_args()
return args
Expand All @@ -56,8 +63,8 @@ def setup_options():

from recon_surf.spherically_project import spherically_project_surface

source_surface = opts.sdir / f"{opts.hemi}.smoothwm.nofix"
projected_surface = opts.sdir / f"{opts.hemi}.qsphere.nofix"
source_surface = opts.sd / opts.subject / "surf" / f"{opts.hemi}.smoothwm.nofix"
projected_surface = opts.sd / opts.subject / "surf" / f"{opts.hemi}.qsphere.nofix"
print(f"Reading in surface: {source_surface} ...")

# make sure the process has a username, so nibabel does not crash in write_geometry
Expand Down Expand Up @@ -88,6 +95,6 @@ def setup_options():
fallback += ("-threads", str(opts.threads), "-itkthreads", str(opts.threads))

print(f"spherical_project.py failed.\nRunning fallback command: {' '.join(fallback)}")
process = Popen(fallback, env=dict(environ, SUBJECTS_DIR=str(opts.sdir)))
process = Popen(fallback, env=dict(environ, SUBJECTS_DIR=str(opts.sd)))
done = process.forward_output(encoding="utf-8", timeout=None)
sys.exit(done.retcode)