estenhl commited on
Commit
44facea
·
1 Parent(s): 3160d9f

Working on docker containers

Browse files
README.md CHANGED
@@ -1,9 +1,24 @@
1
  ## Build docker container for preprocessing
 
 
 
2
  docker build \
3
  -f docker/preprocess.Dockerfile \
4
  -t pyment/preprocessing:1.0.0 \
5
- --build-arg CHECKPOINTS_FOLDER=<path_to_fastsurfer_checkpoints>
6
  .
 
7
 
8
  ## Run docker container for preprocessing
9
- docker run --rm -v <path_to_input>:/input -v <path_to_ouput>:/output -v <path_to_licenses>:/licenses --gpus all pyment/preprocessing:1.0.0
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ## Build docker container for preprocessing
2
+ Note that for now, building the container requires a folder called <checkpoints> that contains the FastSurfer segmentation checkpoints
3
+
4
+ ```
5
  docker build \
6
  -f docker/preprocess.Dockerfile \
7
  -t pyment/preprocessing:1.0.0 \
 
8
  .
9
+ ```
10
 
11
  ## Run docker container for preprocessing
12
+ Running the container for preprocessing requires three volumes:
13
+ - Inputs: A folder containing input data. All nifti-files detected in this folder or one of its subfolders will be processed
14
+ - Outputs: A folder where the preprocessed images will be written.
15
+ - Licenses: A folder containing the freesurfer license
16
+ ```
17
+ docker run --rm \
18
+ --user $(id -u):$(id -g) \
19
+ --volume <path_to_input>:/input \
20
+ --volume <path_to_ouput>:/output \
21
+ --volume <path_to_licenses>:/licenses \
22
+ --gpus all \
23
+ pyment/preprocessing:1.0.0
24
+ ```
docker/preprocess.Dockerfile CHANGED
@@ -31,4 +31,4 @@ COPY scripts/preprocess.sh /scripts/preprocess.sh
31
  CMD ["/bin/sh", "/scripts/preprocess.sh", \
32
  "--license", "/licenses/freesurfer.txt", \
33
  "--python", "/envs/fastsurfer/bin/python", \
34
- "/input", "/output"]
 
31
  CMD ["/bin/sh", "/scripts/preprocess.sh", \
32
  "--license", "/licenses/freesurfer.txt", \
33
  "--python", "/envs/fastsurfer/bin/python", \
34
+ "/input", "/output/fastsurfer"]
poetry.lock CHANGED
The diff for this file is too large to render. See raw diff
 
pyment/__init__.py CHANGED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import tomllib
3
+
4
+ def _get_version():
5
+ """Get version from pyproject.toml"""
6
+ pyproject_path = os.path.join(
7
+ os.path.dirname(__file__), os.pardir, 'pyproject.toml'
8
+ )
9
+
10
+ with open(pyproject_path, 'rb') as f:
11
+ data = tomllib.load(f)
12
+
13
+ return data['project']['version']
14
+
15
+ __version__ = _get_version()
pyment/models/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from .sfcn import SFCN, MultiTaskSFCN
2
+
3
+ __all__ = ['SFCN', 'MultiTaskSFCN']
pyment/models/sfcn/__init__.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ from .sfcn import SFCN
2
+ from .sfcn_multi import MultiTaskSFCN
3
+
4
+ __all__ = ['SFCN', 'MultiTaskSFCN']
pyment/models/sfcn/sfcn.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from abc import abstractmethod
2
+ from typing import Any, Callable, Tuple
3
+
4
+ import tensorflow as tf
5
+ from tensorflow.keras.layers import (
6
+ Activation, BatchNormalization, Conv3D, Dropout, GlobalAveragePooling3D,
7
+ GlobalMaxPooling3D, Input, MaxPooling3D, Reshape
8
+ )
9
+ from tensorflow.keras.models import Model
10
+ from tensorflow.keras.regularizers import Regularizer
11
+
12
+
13
+
14
+ class SFCN(Model):
15
+ FILTERS = [32, 64, 128, 256, 256, 64]
16
+
17
+ @abstractmethod
18
+ def construct_prediction_head(
19
+ bottleneck: tf.Tensor,
20
+ name: str
21
+ ) -> tf.Tensor:
22
+ pass
23
+
24
+ def __init__(self, *,
25
+ input_shape: Tuple[int] = (224, 192, 224),
26
+ include_top: bool = True,
27
+ pooling: str = 'avg',
28
+ dropout: float = 0.,
29
+ regularizer: Regularizer = None,
30
+ activation: Any = 'relu',
31
+ name: str = 'SFCN'
32
+ ):
33
+ self.inputs = Input(input_shape, name=f'{name}_inputs')
34
+ x = Reshape(input_shape + (1,), name=f'{name}_expand-dims')(
35
+ self.inputs
36
+ )
37
+
38
+ for i in range(len(self.FILTERS) - 1):
39
+ x = Conv3D(
40
+ self.FILTERS[i],
41
+ (3, 3, 3),
42
+ padding='SAME',
43
+ activation=None,
44
+ kernel_regularizer=regularizer,
45
+ name=f'{name}_block-{i}_conv'
46
+ )(x)
47
+ x = BatchNormalization(name=f'{name}_block-{i}_norm')(x)
48
+ x = Activation(activation, name=f'{name}_block-{i}_activation')(x)
49
+ x = MaxPooling3D((2, 2, 2), name=f'{name}_block-{i}_pool')(x)
50
+
51
+ x = Conv3D(
52
+ self.FILTERS[-1],
53
+ (1, 1, 1),
54
+ padding='SAME',
55
+ activation=None,
56
+ name=f'{name}_top_conv'
57
+ )(x)
58
+ x = BatchNormalization(name=f'{name}_top_norm')(x)
59
+ x = Activation(activation, name=f'{name}_top_activation')(x)
60
+
61
+ if pooling == 'avg':
62
+ pooling = GlobalAveragePooling3D
63
+ elif pooling == 'max':
64
+ pooling = GlobalMaxPooling3D
65
+ else:
66
+ raise ValueError(f'Unknown pooling layer {pooling}')
67
+
68
+ x = pooling(name=f'{name}_top_pool')(x)
69
+
70
+ self.bottleneck = x
71
+
72
+ if include_top:
73
+ x = Dropout(dropout, name=f'{name}_dropout')(x)
74
+ x = self.construct_prediction_head(x, name=f'{name}_predictions')
75
+
76
+ super().__init__(self.inputs, x)
pyment/models/sfcn/sfcn_multi.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from tensorflow import concat, Tensor
2
+ from tensorflow.keras.layers import Activation, BatchNormalization, Dense
3
+
4
+ from .sfcn import SFCN
5
+
6
+
7
+ class MultiTaskSFCN(SFCN):
8
+ @classmethod
9
+ def construct_prediction_head(
10
+ cls,
11
+ bottleneck: Tensor,
12
+ name: str
13
+ ) -> Tensor:
14
+ x = bottleneck
15
+ depths = []
16
+
17
+ for i in range(len(depths)):
18
+ x = Dense(depths[i], activation=None,
19
+ name=f'{name}_dense-{i+1}_dense')(x)
20
+ x = BatchNormalization(name=f'{name}_dense-{i+1}_norm')(x)
21
+ x = Activation('relu', name=f'{name}_dense-{i+1}_activation')(x)
22
+
23
+ heads = [
24
+ Dense(1, activation=None, name=f'{name}_predictions_age'),
25
+ Dense(1, activation='sigmoid', name=f'{name}_predictions_sex'),
26
+ Dense(1, activation='sigmoid',
27
+ name=f'{name}_predictions_handedness'),
28
+ Dense(1, activation=None, name=f'{name}_predictions_bmi'),
29
+ Dense(1, activation=None,
30
+ name=f'{name}_predictions_fluid_intelligence'),
31
+ Dense(1, activation=None, name=f'{name}_predictions_neuroticism')
32
+ ]
33
+ heads = [head(x) for head in heads]
34
+
35
+ return concat(heads, axis=-1)
36
+
37
+ def __init__(self, *args,
38
+ pooling: str = 'max',
39
+ name: str = 'SFCNMulti',
40
+ **kwargs
41
+ ):
42
+ super().__init__(*args, pooling=pooling, name=name, **kwargs)
pyproject.toml CHANGED
@@ -12,6 +12,15 @@ license-files = [
12
  readme = "README.md"
13
  requires-python = ">=3.10.2"
14
 
 
 
 
 
 
 
 
 
 
15
  [build-system]
16
  requires = ["poetry-core>=2.0.0,<3.0.0"]
17
  build-backend = "poetry.core.masonry.api"
 
12
  readme = "README.md"
13
  requires-python = ">=3.10.2"
14
 
15
+ [tool.poetry]
16
+ packages = [{include = "pyment"}]
17
+
18
+ [tool.poetry.dependencies]
19
+ python = "^3.10.2"
20
+ tensorflow = "^2.15.0"
21
+ numpy = "^1.24.0"
22
+ protobuf = "^4.25.0"
23
+
24
  [build-system]
25
  requires = ["poetry-core>=2.0.0,<3.0.0"]
26
  build-backend = "poetry.core.masonry.api"
scripts/predict_from_fastsurfer_folder.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+
3
+ from pyment.models import MultiTaskSFCN
4
+
5
+ def predict_from_fastsurfer_folder(folder: str, output: str, weights: str):
6
+ model = MultiTaskSFCN()
7
+
8
+ if __name__ == '__main__':
9
+ parser = argparse.ArgumentParser(
10
+ 'Generates predictions from SFCN multi and a given weights file for '
11
+ 'all images in a fastsurfer folder'
12
+ )
13
+
14
+ parser.add_argument('folder', help='Path to fastsurfer folder')
15
+ parser.add_argument(
16
+ 'output', help='Path where CSV with predictions are written'
17
+ )
18
+ parser.add_argument('-w', '--weights', help='Path to weights file')
19
+
20
+ args = parser.parse_args()
21
+
22
+ predict_from_fastsurfer_folder(
23
+ folder=args.folder,
24
+ output=args.output,
25
+ weights=args.weights
26
+ )
27
+
sfcn-multi.index ADDED
Binary file (8.49 kB). View file