-
Notifications
You must be signed in to change notification settings - Fork 145
Allow relative paths in run_fastsurfer.sh #732
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds functionality to resolve relative paths to absolute paths in the run_fastsurfer.sh script before executing the pipeline. This ensures that path variables used throughout the script are consistently absolute, which can prevent issues when the working directory changes during execution.
- Adds a helper function
convert_to_absolute_path()to resolve paths usingrealpath - Applies path resolution to 14 key path variables including input files, output files, and configuration paths
- Includes error handling with warning messages for failed path conversions
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| eval "var_value=\$$var_name" | ||
|
|
||
| if [ -n "$var_value" ]; then | ||
| if [ -e "$var_value" ] || [ "${var_value#*/}" != "$var_value" ]; then |
Copilot
AI
Sep 30, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The condition [ \"${var_value#*/}\" != \"$var_value\" ] is a complex way to check if a path contains directory separators. Consider using a more readable approach like [[ \"$var_value\" == */* ]] for better maintainability.
| if [ -e "$var_value" ] || [ "${var_value#*/}" != "$var_value" ]; then | |
| if [ -e "$var_value" ] || [[ "$var_value" == */* ]]; then |
Co-authored-by: Copilot <[email protected]>
|
Relative paths have a meaning for almost all files listed in the PR. It means relative path to the subject_dir. So the only "legitimately" improperly supported paths would be relative paths for I have to look at whether there is some logic with T1 being absolute paths, I think there was something... |
dkuegler
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not certain we "fully" want this behavior. We should discuss this, in the past, it was quite clear in the documentation, that t1 and t2 should be absolute paths. For all other files, relative should mean relative to the subject_dir. If this does for some reason not work, that would be a bug.
| convert_to_absolute_path "seg_log" | ||
| convert_to_absolute_path "conformed_name" | ||
| convert_to_absolute_path "norm_name" | ||
| convert_to_absolute_path "norm_name_t2" | ||
| convert_to_absolute_path "asegdkt_segfile" | ||
| convert_to_absolute_path "mask_name" | ||
| convert_to_absolute_path "merged_segfile" | ||
| convert_to_absolute_path "cereb_segfile" | ||
| convert_to_absolute_path "cereb_statsfile" | ||
| convert_to_absolute_path "hypo_segfile" | ||
| convert_to_absolute_path "hypo_statsfile" | ||
| convert_to_absolute_path "asegdkt_vinn_statsfile" | ||
| convert_to_absolute_path "aseg_vinn_statsfile" | ||
| convert_to_absolute_path "aseg_segfile" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All these should not be made absolute
| convert_to_absolute_path "seg_log" | |
| convert_to_absolute_path "conformed_name" | |
| convert_to_absolute_path "norm_name" | |
| convert_to_absolute_path "norm_name_t2" | |
| convert_to_absolute_path "asegdkt_segfile" | |
| convert_to_absolute_path "mask_name" | |
| convert_to_absolute_path "merged_segfile" | |
| convert_to_absolute_path "cereb_segfile" | |
| convert_to_absolute_path "cereb_statsfile" | |
| convert_to_absolute_path "hypo_segfile" | |
| convert_to_absolute_path "hypo_statsfile" | |
| convert_to_absolute_path "asegdkt_vinn_statsfile" | |
| convert_to_absolute_path "aseg_vinn_statsfile" | |
| convert_to_absolute_path "aseg_segfile" |
| } | ||
|
|
||
| # Convert path variables to absolute paths | ||
| convert_to_absolute_path "sd" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer the way this works to be like this
| convert_to_absolute_path "sd" | |
| sd="$(convert_to_absolute_path "$sd")" |
The other version may work, but function that affect variables as a side effect are really ugly and should always be avoided.
| local var_name="$1" | ||
| local var_value | ||
| eval "var_value=\$$var_name" | ||
|
|
||
| if [ -n "$var_value" ]; then | ||
| if [ -e "$var_value" ] || [ "${var_value#*/}" != "$var_value" ]; then | ||
| # Path exists or contains directory separators - convert to absolute | ||
| local abs_path | ||
| abs_path=$(realpath "$var_value" 2>/dev/null) | ||
| if [ $? -eq 0 ] && [ -n "$abs_path" ]; then | ||
| eval "$var_name=\"$abs_path\"" | ||
| else | ||
| echo "WARNING: Failed to convert $var_name to absolute path: $var_value" | tee -a "${tmpLF:-/dev/null}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how you can achieve the var=$(func "$val")" syntax is by echo-ing the return value and sending warnings and error messages to stderr.
| local var_name="$1" | |
| local var_value | |
| eval "var_value=\$$var_name" | |
| if [ -n "$var_value" ]; then | |
| if [ -e "$var_value" ] || [ "${var_value#*/}" != "$var_value" ]; then | |
| # Path exists or contains directory separators - convert to absolute | |
| local abs_path | |
| abs_path=$(realpath "$var_value" 2>/dev/null) | |
| if [ $? -eq 0 ] && [ -n "$abs_path" ]; then | |
| eval "$var_name=\"$abs_path\"" | |
| else | |
| echo "WARNING: Failed to convert $var_name to absolute path: $var_value" | tee -a "${tmpLF:-/dev/null}" | |
| # usage: convert_to_absolute_path <path> [<logfile>] | |
| local var_value="$1" | |
| local logging=("cat") | |
| if [[ "$#" > 1]] ; then logging=(tee -a "$2") ; fi | |
| if [ -n "$var_value" ]; then | |
| if [ -e "$var_value" ] || [ "${var_value#*/}" != "$var_value" ]; then | |
| # Path exists or contains directory separators - convert to absolute | |
| local abs_path | |
| abs_path=$(realpath "$var_value" 2>/dev/null) | |
| if [ $? -eq 0 ] && [ -n "$abs_path" ]; then | |
| echo "$abs_path" | |
| else | |
| echo "WARNING: Failed to convert $var_name to absolute path: $var_value" | "${logging[@]}" &>2 |
Overall, this function should probably be moved to functions.sh.
Also, logging can be done more elegantly like indicated.
|
|
||
| # Convert path variables to absolute paths | ||
| convert_to_absolute_path "sd" | ||
| convert_to_absolute_path "t1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically, --t1 and --t2 are documented as follows:
--t1 <T1_input> T1 full head input (not bias corrected). Requires an
ABSOLUTE Path!
--t2 <T2_input> *Optional* T2 full head input (does not have to be bias
corrected, a mandatory biasfield correction step is
performed). Requires an ABSOLUTE Path!
Also forcing t1 to be an absolute path will probably break longitudinal segmentation, see
if [[ -n "$t1" ]] && [[ "$t1" != "from-base" ]]; then
echo "WARNING: --t1 was passed but will be overwritten with T1 from base template." | tee -a "$tmpLF"
fiAlso, the t1 input check checks if the t1 file exists.
if [[ "$run_seg_pipeline" == "1" ]] && { [[ -z "$t1" ]] || [[ ! -f "$t1" ]]; }
then
echo "ERROR: T1 image ($t1) could not be found. You must supply an existing T1 input"
echo " (full head) via --t1 <absolute path and name> for generating the segmentation."
echo "NOTE: If running in a container, make sure symlinks are valid!"
exit 1
fiBut this can probably be fixed by moving the conversion block to "after" the input checking and sanitization (search for comment #### START ####)
|
After more reviewing on #727, I am now convinced, that we do not want the functionality presented here. The logic is as follows RULE: As is, this makes relative paths relative to the working directory. That is not the current standard and not intended. Course of Action:
|
|
Closing this, since it seems to require a different solution. |
This PR resolves relative paths in run_fastsurfer.sh before running the pipeline.