kaiko-eva 0.1.1__py3-none-any.whl → 0.1.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eva/core/callbacks/writers/embeddings/base.py +3 -4
- eva/core/data/dataloaders/dataloader.py +2 -2
- eva/core/data/splitting/random.py +6 -5
- eva/core/data/splitting/stratified.py +12 -6
- eva/core/losses/__init__.py +5 -0
- eva/core/losses/cross_entropy.py +27 -0
- eva/core/metrics/__init__.py +0 -4
- eva/core/metrics/defaults/__init__.py +0 -2
- eva/core/models/modules/module.py +9 -9
- eva/core/models/transforms/extract_cls_features.py +17 -9
- eva/core/models/transforms/extract_patch_features.py +23 -11
- eva/core/utils/io/__init__.py +2 -1
- eva/core/utils/io/gz.py +28 -0
- eva/core/utils/multiprocessing.py +46 -1
- eva/core/utils/progress_bar.py +15 -0
- eva/vision/callbacks/loggers/batch/segmentation.py +7 -4
- eva/vision/data/datasets/__init__.py +4 -0
- eva/vision/data/datasets/classification/__init__.py +2 -1
- eva/vision/data/datasets/classification/camelyon16.py +4 -1
- eva/vision/data/datasets/classification/panda.py +17 -1
- eva/vision/data/datasets/classification/wsi.py +4 -1
- eva/vision/data/datasets/segmentation/__init__.py +2 -0
- eva/vision/data/datasets/segmentation/consep.py +2 -2
- eva/vision/data/datasets/segmentation/lits.py +49 -29
- eva/vision/data/datasets/segmentation/lits_balanced.py +93 -0
- eva/vision/data/datasets/segmentation/monusac.py +7 -7
- eva/vision/data/datasets/segmentation/total_segmentator_2d.py +50 -18
- eva/vision/data/datasets/wsi.py +37 -1
- eva/vision/data/wsi/patching/coordinates.py +9 -1
- eva/vision/data/wsi/patching/samplers/_utils.py +2 -8
- eva/vision/data/wsi/patching/samplers/random.py +4 -2
- eva/vision/losses/__init__.py +2 -2
- eva/vision/losses/dice.py +75 -8
- eva/vision/metrics/__init__.py +11 -0
- eva/vision/metrics/defaults/__init__.py +7 -0
- eva/{core → vision}/metrics/defaults/segmentation/__init__.py +1 -1
- eva/{core → vision}/metrics/defaults/segmentation/multiclass.py +2 -1
- eva/vision/metrics/segmentation/BUILD +1 -0
- eva/vision/metrics/segmentation/__init__.py +9 -0
- eva/vision/metrics/segmentation/_utils.py +69 -0
- eva/{core/metrics → vision/metrics/segmentation}/generalized_dice.py +12 -10
- eva/vision/metrics/segmentation/mean_iou.py +57 -0
- eva/vision/models/modules/semantic_segmentation.py +4 -3
- eva/vision/models/networks/backbones/_utils.py +12 -0
- eva/vision/models/networks/backbones/pathology/__init__.py +4 -1
- eva/vision/models/networks/backbones/pathology/histai.py +8 -2
- eva/vision/models/networks/backbones/pathology/mahmood.py +2 -9
- eva/vision/models/networks/backbones/pathology/owkin.py +14 -0
- eva/vision/models/networks/backbones/pathology/paige.py +51 -0
- eva/vision/models/networks/decoders/__init__.py +1 -1
- eva/vision/models/networks/decoders/segmentation/__init__.py +12 -4
- eva/vision/models/networks/decoders/segmentation/base.py +16 -0
- eva/vision/models/networks/decoders/segmentation/{conv2d.py → decoder2d.py} +26 -22
- eva/vision/models/networks/decoders/segmentation/linear.py +2 -2
- eva/vision/models/networks/decoders/segmentation/semantic/__init__.py +12 -0
- eva/vision/models/networks/decoders/segmentation/{common.py → semantic/common.py} +3 -3
- eva/vision/models/networks/decoders/segmentation/semantic/with_image.py +94 -0
- eva/vision/models/networks/decoders/segmentation/typings.py +18 -0
- eva/vision/utils/colormap.py +20 -0
- eva/vision/utils/io/__init__.py +7 -1
- eva/vision/utils/io/nifti.py +19 -4
- {kaiko_eva-0.1.1.dist-info → kaiko_eva-0.1.5.dist-info}/METADATA +8 -39
- {kaiko_eva-0.1.1.dist-info → kaiko_eva-0.1.5.dist-info}/RECORD +66 -52
- {kaiko_eva-0.1.1.dist-info → kaiko_eva-0.1.5.dist-info}/WHEEL +1 -1
- eva/core/metrics/mean_iou.py +0 -120
- eva/vision/models/networks/decoders/decoder.py +0 -7
- {kaiko_eva-0.1.1.dist-info → kaiko_eva-0.1.5.dist-info}/entry_points.txt +0 -0
- {kaiko_eva-0.1.1.dist-info → kaiko_eva-0.1.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
"""Convolutional based semantic segmentation decoder."""
|
|
2
2
|
|
|
3
|
-
from typing import List, Tuple
|
|
3
|
+
from typing import List, Sequence, Tuple
|
|
4
4
|
|
|
5
5
|
import torch
|
|
6
6
|
from torch import nn
|
|
7
7
|
from torch.nn import functional
|
|
8
8
|
|
|
9
|
-
from eva.vision.models.networks.decoders import
|
|
9
|
+
from eva.vision.models.networks.decoders.segmentation import base
|
|
10
|
+
from eva.vision.models.networks.decoders.segmentation.typings import DecoderInputs
|
|
10
11
|
|
|
11
12
|
|
|
12
|
-
class
|
|
13
|
-
"""
|
|
13
|
+
class Decoder2D(base.Decoder):
|
|
14
|
+
"""Segmentation decoder for 2D applications."""
|
|
14
15
|
|
|
15
|
-
def __init__(self, layers: nn.Module) -> None:
|
|
16
|
-
"""Initializes the
|
|
16
|
+
def __init__(self, layers: nn.Module, combine_features: bool = True) -> None:
|
|
17
|
+
"""Initializes the based decoder head.
|
|
17
18
|
|
|
18
19
|
Here the input nn layers will be directly applied to the
|
|
19
20
|
features of shape (batch_size, hidden_size, n_patches_height,
|
|
@@ -21,13 +22,16 @@ class ConvDecoder(decoder.Decoder):
|
|
|
21
22
|
Note the n_patches is also known as grid_size.
|
|
22
23
|
|
|
23
24
|
Args:
|
|
24
|
-
layers: The
|
|
25
|
+
layers: The layers to be used as the decoder head.
|
|
26
|
+
combine_features: Whether to combine the features from different
|
|
27
|
+
feature levels into one tensor before applying the decoder head.
|
|
25
28
|
"""
|
|
26
29
|
super().__init__()
|
|
27
30
|
|
|
28
31
|
self._layers = layers
|
|
32
|
+
self._combine_features = combine_features
|
|
29
33
|
|
|
30
|
-
def _forward_features(self, features: List[torch.Tensor]) -> torch.Tensor:
|
|
34
|
+
def _forward_features(self, features: torch.Tensor | List[torch.Tensor]) -> torch.Tensor:
|
|
31
35
|
"""Forward function for multi-level feature maps to a single one.
|
|
32
36
|
|
|
33
37
|
It will interpolate the features and concat them into a single tensor
|
|
@@ -46,6 +50,8 @@ class ConvDecoder(decoder.Decoder):
|
|
|
46
50
|
A tensor of shape (batch_size, hidden_size, n_patches_height,
|
|
47
51
|
n_patches_width) which is feature map of the decoder head.
|
|
48
52
|
"""
|
|
53
|
+
if isinstance(features, torch.Tensor):
|
|
54
|
+
features = [features]
|
|
49
55
|
if not isinstance(features, list) or features[0].ndim != 4:
|
|
50
56
|
raise ValueError(
|
|
51
57
|
"Input features should be a list of four (4) dimensional inputs of "
|
|
@@ -63,7 +69,9 @@ class ConvDecoder(decoder.Decoder):
|
|
|
63
69
|
]
|
|
64
70
|
return torch.cat(upsampled_features, dim=1)
|
|
65
71
|
|
|
66
|
-
def _forward_head(
|
|
72
|
+
def _forward_head(
|
|
73
|
+
self, patch_embeddings: torch.Tensor | Sequence[torch.Tensor]
|
|
74
|
+
) -> torch.Tensor:
|
|
67
75
|
"""Forward of the decoder head.
|
|
68
76
|
|
|
69
77
|
Args:
|
|
@@ -75,12 +83,12 @@ class ConvDecoder(decoder.Decoder):
|
|
|
75
83
|
"""
|
|
76
84
|
return self._layers(patch_embeddings)
|
|
77
85
|
|
|
78
|
-
def
|
|
86
|
+
def _upscale(
|
|
79
87
|
self,
|
|
80
88
|
logits: torch.Tensor,
|
|
81
89
|
image_size: Tuple[int, int],
|
|
82
90
|
) -> torch.Tensor:
|
|
83
|
-
"""
|
|
91
|
+
"""Upscales the calculated logits to the target image size.
|
|
84
92
|
|
|
85
93
|
Args:
|
|
86
94
|
logits: The decoder outputs of shape (batch_size, n_classes,
|
|
@@ -93,22 +101,18 @@ class ConvDecoder(decoder.Decoder):
|
|
|
93
101
|
"""
|
|
94
102
|
return functional.interpolate(logits, image_size, mode="bilinear")
|
|
95
103
|
|
|
96
|
-
def forward(
|
|
97
|
-
self,
|
|
98
|
-
features: List[torch.Tensor],
|
|
99
|
-
image_size: Tuple[int, int],
|
|
100
|
-
) -> torch.Tensor:
|
|
104
|
+
def forward(self, decoder_inputs: DecoderInputs) -> torch.Tensor:
|
|
101
105
|
"""Maps the patch embeddings to a segmentation mask of the image size.
|
|
102
106
|
|
|
103
107
|
Args:
|
|
104
|
-
|
|
105
|
-
hidden_size, n_patches_height, n_patches_width).
|
|
106
|
-
image_size: The target image size (height, width).
|
|
108
|
+
decoder_inputs: Inputs required by the decoder.
|
|
107
109
|
|
|
108
110
|
Returns:
|
|
109
111
|
Tensor containing scores for all of the classes with shape
|
|
110
112
|
(batch_size, n_classes, image_height, image_width).
|
|
111
113
|
"""
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
features, image_size, _ = DecoderInputs(*decoder_inputs)
|
|
115
|
+
if self._combine_features:
|
|
116
|
+
features = self._forward_features(features)
|
|
117
|
+
logits = self._forward_head(features)
|
|
118
|
+
return self._upscale(logits, image_size)
|
|
@@ -6,10 +6,10 @@ import torch
|
|
|
6
6
|
from torch import nn
|
|
7
7
|
from torch.nn import functional
|
|
8
8
|
|
|
9
|
-
from eva.vision.models.networks.decoders import
|
|
9
|
+
from eva.vision.models.networks.decoders.segmentation import base
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class LinearDecoder(
|
|
12
|
+
class LinearDecoder(base.Decoder):
|
|
13
13
|
"""Linear decoder."""
|
|
14
14
|
|
|
15
15
|
def __init__(self, layers: nn.Module) -> None:
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Semantic Segmentation decoder heads API."""
|
|
2
|
+
|
|
3
|
+
from eva.vision.models.networks.decoders.segmentation.semantic.common import (
|
|
4
|
+
ConvDecoder1x1,
|
|
5
|
+
ConvDecoderMS,
|
|
6
|
+
SingleLinearDecoder,
|
|
7
|
+
)
|
|
8
|
+
from eva.vision.models.networks.decoders.segmentation.semantic.with_image import (
|
|
9
|
+
ConvDecoderWithImage,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = ["ConvDecoder1x1", "ConvDecoderMS", "SingleLinearDecoder", "ConvDecoderWithImage"]
|
|
@@ -7,10 +7,10 @@ output by an encoder into pixel-wise predictions for segmentation tasks.
|
|
|
7
7
|
|
|
8
8
|
from torch import nn
|
|
9
9
|
|
|
10
|
-
from eva.vision.models.networks.decoders.segmentation import
|
|
10
|
+
from eva.vision.models.networks.decoders.segmentation import decoder2d, linear
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class ConvDecoder1x1(
|
|
13
|
+
class ConvDecoder1x1(decoder2d.Decoder2D):
|
|
14
14
|
"""A convolutional decoder with a single 1x1 convolutional layer."""
|
|
15
15
|
|
|
16
16
|
def __init__(self, in_features: int, num_classes: int) -> None:
|
|
@@ -29,7 +29,7 @@ class ConvDecoder1x1(conv2d.ConvDecoder):
|
|
|
29
29
|
)
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
class ConvDecoderMS(
|
|
32
|
+
class ConvDecoderMS(decoder2d.Decoder2D):
|
|
33
33
|
"""A multi-stage convolutional decoder with upsampling and convolutional layers.
|
|
34
34
|
|
|
35
35
|
This decoder applies a series of upsampling and convolutional layers to transform
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""Convolutional semantic segmentation decoders that use input image & feature maps as input."""
|
|
2
|
+
|
|
3
|
+
from typing import List
|
|
4
|
+
|
|
5
|
+
import torch
|
|
6
|
+
from torch import nn
|
|
7
|
+
from torchvision.transforms.functional import rgb_to_grayscale
|
|
8
|
+
from typing_extensions import override
|
|
9
|
+
|
|
10
|
+
from eva.vision.models.networks.decoders.segmentation import decoder2d
|
|
11
|
+
from eva.vision.models.networks.decoders.segmentation.typings import DecoderInputs
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ConvDecoderWithImage(decoder2d.Decoder2D):
|
|
15
|
+
"""A convolutional that in addition to encoded features, also takes the input image as input.
|
|
16
|
+
|
|
17
|
+
In a first stage, the input features are upsampled and passed through a convolutional layer,
|
|
18
|
+
while in the second stage, the input image channels are concatenated with the upsampled features
|
|
19
|
+
and passed through additional convolutional blocks in order to combine the image prior
|
|
20
|
+
information with the encoded features. Lastly, a 1x1 conv operation reduces the number of
|
|
21
|
+
channels to the number of classes.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
_default_hidden_dims = [64, 32, 32]
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
in_features: int,
|
|
29
|
+
num_classes: int,
|
|
30
|
+
greyscale: bool = False,
|
|
31
|
+
hidden_dims: List[int] | None = None,
|
|
32
|
+
) -> None:
|
|
33
|
+
"""Initializes the decoder.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
in_features: The hidden dimension size of the embeddings.
|
|
37
|
+
num_classes: Number of output classes as channels.
|
|
38
|
+
greyscale: Whether to convert input images to greyscale.
|
|
39
|
+
hidden_dims: List of hidden dimensions for the convolutional layers.
|
|
40
|
+
"""
|
|
41
|
+
hidden_dims = hidden_dims or self._default_hidden_dims
|
|
42
|
+
if len(hidden_dims) != 3:
|
|
43
|
+
raise ValueError("Hidden dims must have 3 elements.")
|
|
44
|
+
|
|
45
|
+
super().__init__(
|
|
46
|
+
layers=nn.Sequential(
|
|
47
|
+
nn.Upsample(scale_factor=2),
|
|
48
|
+
Conv2dBnReLU(in_features, hidden_dims[0]),
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
self.greyscale = greyscale
|
|
52
|
+
|
|
53
|
+
additional_hidden_dims = 1 if greyscale else 3
|
|
54
|
+
self.image_block = nn.Sequential(
|
|
55
|
+
Conv2dBnReLU(hidden_dims[0] + additional_hidden_dims, hidden_dims[1]),
|
|
56
|
+
Conv2dBnReLU(hidden_dims[1], hidden_dims[2]),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
self.classifier = nn.Conv2d(hidden_dims[2], num_classes, kernel_size=1)
|
|
60
|
+
|
|
61
|
+
@override
|
|
62
|
+
def forward(self, decoder_inputs: DecoderInputs) -> torch.Tensor:
|
|
63
|
+
if decoder_inputs.images is None:
|
|
64
|
+
raise ValueError("Input images are missing.")
|
|
65
|
+
|
|
66
|
+
logits = super().forward(decoder_inputs)
|
|
67
|
+
in_images = (
|
|
68
|
+
rgb_to_grayscale(decoder_inputs.images) if self.greyscale else decoder_inputs.images
|
|
69
|
+
)
|
|
70
|
+
logits = torch.cat([logits, in_images], dim=1)
|
|
71
|
+
logits = self.image_block(logits)
|
|
72
|
+
|
|
73
|
+
return self.classifier(logits)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class Conv2dBnReLU(nn.Sequential):
|
|
77
|
+
"""A single convolutional layer with batch normalization and ReLU activation."""
|
|
78
|
+
|
|
79
|
+
def __init__(
|
|
80
|
+
self, in_channels: int, out_channels: int, kernel_size: int = 3, padding: int = 1
|
|
81
|
+
) -> None:
|
|
82
|
+
"""Initializes the layer.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
in_channels: Number of input channels.
|
|
86
|
+
out_channels: Number of output channels.
|
|
87
|
+
kernel_size: Size of the convolutional kernel.
|
|
88
|
+
padding: Padding size for the convolutional layer.
|
|
89
|
+
"""
|
|
90
|
+
super().__init__(
|
|
91
|
+
nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size, padding=padding),
|
|
92
|
+
nn.BatchNorm2d(out_channels),
|
|
93
|
+
nn.ReLU(inplace=True),
|
|
94
|
+
)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Type-hints for segmentation decoders."""
|
|
2
|
+
|
|
3
|
+
from typing import List, NamedTuple, Tuple
|
|
4
|
+
|
|
5
|
+
import torch
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DecoderInputs(NamedTuple):
|
|
9
|
+
"""Input scheme for segmentation decoders."""
|
|
10
|
+
|
|
11
|
+
features: List[torch.Tensor]
|
|
12
|
+
"""List of image features generated by the encoder from the original images."""
|
|
13
|
+
|
|
14
|
+
image_size: Tuple[int, int]
|
|
15
|
+
"""Size of the original input images to be used for upsampling."""
|
|
16
|
+
|
|
17
|
+
images: torch.Tensor | None = None
|
|
18
|
+
"""The original input images for which the encoder generated the encoded_images."""
|
eva/vision/utils/colormap.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Color mapping constants."""
|
|
2
2
|
|
|
3
|
+
from typing import List, Tuple
|
|
4
|
+
|
|
3
5
|
COLORS = [
|
|
4
6
|
(0, 0, 0),
|
|
5
7
|
(255, 0, 0), # Red
|
|
@@ -75,3 +77,21 @@ COLORS = [
|
|
|
75
77
|
|
|
76
78
|
COLORMAP = dict(enumerate(COLORS)) | {255: (255, 255, 255)}
|
|
77
79
|
"""Class id to RGB color mapping."""
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def get_colors(num_colors: int) -> List[Tuple[int, int, int]]:
|
|
83
|
+
"""Get a list of RGB colors.
|
|
84
|
+
|
|
85
|
+
If the number of colors is greater than the predefined colors, it will
|
|
86
|
+
repeat the colors until it reaches the requested number
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
num_colors: The number of colors to return.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
A list of RGB colors.
|
|
93
|
+
"""
|
|
94
|
+
colors = COLORS
|
|
95
|
+
while len(colors) < num_colors:
|
|
96
|
+
colors = colors + COLORS[1:]
|
|
97
|
+
return colors
|
eva/vision/utils/io/__init__.py
CHANGED
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
from eva.vision.utils.io.image import read_image, read_image_as_array, read_image_as_tensor
|
|
4
4
|
from eva.vision.utils.io.mat import read_mat, save_mat
|
|
5
|
-
from eva.vision.utils.io.nifti import
|
|
5
|
+
from eva.vision.utils.io.nifti import (
|
|
6
|
+
fetch_nifti_axis_direction_code,
|
|
7
|
+
fetch_nifti_shape,
|
|
8
|
+
read_nifti,
|
|
9
|
+
save_array_as_nifti,
|
|
10
|
+
)
|
|
6
11
|
from eva.vision.utils.io.text import read_csv
|
|
7
12
|
|
|
8
13
|
__all__ = [
|
|
@@ -10,6 +15,7 @@ __all__ = [
|
|
|
10
15
|
"read_image_as_array",
|
|
11
16
|
"read_image_as_tensor",
|
|
12
17
|
"fetch_nifti_shape",
|
|
18
|
+
"fetch_nifti_axis_direction_code",
|
|
13
19
|
"read_nifti",
|
|
14
20
|
"save_array_as_nifti",
|
|
15
21
|
"read_csv",
|
eva/vision/utils/io/nifti.py
CHANGED
|
@@ -5,6 +5,7 @@ from typing import Any, Tuple
|
|
|
5
5
|
import nibabel as nib
|
|
6
6
|
import numpy as np
|
|
7
7
|
import numpy.typing as npt
|
|
8
|
+
from nibabel import orientations
|
|
8
9
|
|
|
9
10
|
from eva.vision.utils.io import _utils
|
|
10
11
|
|
|
@@ -28,13 +29,13 @@ def read_nifti(
|
|
|
28
29
|
ValueError: If the input channel is invalid for the image.
|
|
29
30
|
"""
|
|
30
31
|
_utils.check_file(path)
|
|
31
|
-
image_data = nib.load(path) # type: ignore
|
|
32
|
+
image_data: nib.Nifti1Image = nib.load(path) # type: ignore
|
|
32
33
|
if slice_index is not None:
|
|
33
|
-
image_data = image_data.slicer[:, :, slice_index : slice_index + 1]
|
|
34
|
+
image_data = image_data.slicer[:, :, slice_index : slice_index + 1]
|
|
34
35
|
|
|
35
|
-
image_array = image_data.get_fdata()
|
|
36
|
+
image_array = image_data.get_fdata()
|
|
36
37
|
if use_storage_dtype:
|
|
37
|
-
image_array = image_array.astype(image_data.get_data_dtype())
|
|
38
|
+
image_array = image_array.astype(image_data.get_data_dtype())
|
|
38
39
|
|
|
39
40
|
return image_array
|
|
40
41
|
|
|
@@ -73,3 +74,17 @@ def fetch_nifti_shape(path: str) -> Tuple[int]:
|
|
|
73
74
|
_utils.check_file(path)
|
|
74
75
|
image = nib.load(path) # type: ignore
|
|
75
76
|
return image.header.get_data_shape() # type: ignore
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def fetch_nifti_axis_direction_code(path: str) -> str:
|
|
80
|
+
"""Fetches the NIfTI axis direction code from a file.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
path: The path to the NIfTI file.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
The axis direction codes as string (e.g. "LAS").
|
|
87
|
+
"""
|
|
88
|
+
_utils.check_file(path)
|
|
89
|
+
image_data: nib.Nifti1Image = nib.load(path) # type: ignore
|
|
90
|
+
return "".join(orientations.aff2axcodes(image_data.affine))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: kaiko-eva
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.5
|
|
4
4
|
Summary: Evaluation Framework for oncology foundation models.
|
|
5
5
|
Keywords: machine-learning,evaluation-framework,oncology,foundation-models
|
|
6
6
|
Author-Email: Ioannis Gatopoulos <ioannis@kaiko.ai>, =?utf-8?q?Nicolas_K=C3=A4nzig?= <nicolas@kaiko.ai>, Roman Moser <roman@kaiko.ai>
|
|
@@ -216,14 +216,14 @@ Project-URL: Homepage, https://kaiko-ai.github.io/eva/dev/
|
|
|
216
216
|
Project-URL: Repository, https://github.com/kaiko-ai/eva
|
|
217
217
|
Project-URL: Documentation, https://kaiko-ai.github.io/eva/dev/
|
|
218
218
|
Requires-Python: >=3.10
|
|
219
|
-
Requires-Dist: torch
|
|
220
|
-
Requires-Dist: lightning>=2.2.
|
|
221
|
-
Requires-Dist: jsonargparse[omegaconf]
|
|
219
|
+
Requires-Dist: torch>=2.3.0
|
|
220
|
+
Requires-Dist: lightning>=2.2.0
|
|
221
|
+
Requires-Dist: jsonargparse[omegaconf]>=4.30.0
|
|
222
222
|
Requires-Dist: tensorboard>=2.16.2
|
|
223
223
|
Requires-Dist: loguru>=0.7.2
|
|
224
|
-
Requires-Dist: pandas>=2.
|
|
224
|
+
Requires-Dist: pandas>=2.0.0
|
|
225
225
|
Requires-Dist: transformers>=4.38.2
|
|
226
|
-
Requires-Dist: onnxruntime>=1.
|
|
226
|
+
Requires-Dist: onnxruntime>=1.15.1
|
|
227
227
|
Requires-Dist: onnx>=1.16.0
|
|
228
228
|
Requires-Dist: toolz>=0.12.1
|
|
229
229
|
Requires-Dist: rich>=13.7.1
|
|
@@ -468,41 +468,10 @@ and [tutorials](https://kaiko-ai.github.io/eva/dev/user-guide/advanced/replicate
|
|
|
468
468
|
|
|
469
469
|
## Leaderboards
|
|
470
470
|
|
|
471
|
-
|
|
471
|
+
The following table shows the FMs we have evaluated with _`eva`_. For more detailed information about the evaluation process, please refer to our [documentation](https://kaiko-ai.github.io/eva/main/leaderboards/).
|
|
472
472
|
|
|
473
|
-
|
|
473
|
+

|
|
474
474
|
|
|
475
|
-
<br />
|
|
476
|
-
|
|
477
|
-
<div align="center">
|
|
478
|
-
|
|
479
|
-
| Model | BACH | CRC | MHIST | PCam | Camelyon16 | PANDA | CoNSeP | MoNuSAC |
|
|
480
|
-
|---------|-------|-------|-------|--------|------------|-------|------------|-------|
|
|
481
|
-
| ViT-S/16 _(random)_ <sup>[1]</sup> | 0.411|0.613|0.5|0.752|0.551|0.347|0.489|0.394|
|
|
482
|
-
| ViT-S/16 _(ImageNet)_ <sup>[1]</sup> | 0.675|0.936|0.827|0.861|0.751|0.676|0.54|0.512|
|
|
483
|
-
| DINO<sub>(p=16)</sub> <sup>[2]</sup> | 0.77|0.936|0.751|0.905|0.869|0.737|0.625|0.549|
|
|
484
|
-
| Phikon <sup>[3]</sup> | 0.715|0.942|0.766|0.925|0.879|0.784|0.68|0.554|
|
|
485
|
-
| UNI <sup>[4]</sup> | 0.797|0.95|0.835|0.939|0.933|0.774|0.67|0.575|
|
|
486
|
-
| ViT-S/16 _(kaiko.ai)_ <sup>[5]</sup> | 0.8|0.949|0.831|0.902|0.897|0.77|0.622|0.573|
|
|
487
|
-
| ViT-S/8 _(kaiko.ai)_ <sup>[5]</sup> | 0.825|0.948|0.826|0.887|0.879|0.741|0.677|0.617|
|
|
488
|
-
| ViT-B/16 _(kaiko.ai)_ <sup>[5]</sup> | 0.846|0.959|0.839|0.906|0.891|0.753|0.647|0.572|
|
|
489
|
-
| ViT-B/8 _(kaiko.ai)_ <sup>[5]</sup> | 0.867|0.952|0.814|0.921|0.939|0.761|0.706|0.661|
|
|
490
|
-
| ViT-L/14 _(kaiko.ai)_ <sup>[5]</sup> | 0.862|0.935|0.822|0.907|0.941|0.769|0.686|0.599|
|
|
491
|
-
|
|
492
|
-
_Table I: Linear probing evaluation of FMs on patch-level downstream datasets.<br> We report balanced accuracy
|
|
493
|
-
for classification tasks and generalized Dice score for semgetnation tasks, averaged over 5 runs. Results are
|
|
494
|
-
reported on the "test" split if available and otherwise on the "validation" split._
|
|
495
|
-
|
|
496
|
-
</div>
|
|
497
|
-
|
|
498
|
-
<br />
|
|
499
|
-
|
|
500
|
-
_References_:
|
|
501
|
-
1. _"Emerging properties in self-supervised vision transformers”_, [arXiv](https://arxiv.org/abs/2104.14294)
|
|
502
|
-
2. _"Benchmarking self-supervised learning on diverse pathology datasets”_, [arXiv](https://arxiv.org/abs/2212.04690)
|
|
503
|
-
3. _"Scaling self-supervised learning for histopathology with masked image modeling”_, [medRxiv](https://www.medrxiv.org/content/10.1101/2023.07.21.23292757v1)
|
|
504
|
-
4. _"A General-Purpose Self-Supervised Model for Computational Pathology”_, [arXiv](https://arxiv.org/abs/2308.15474)
|
|
505
|
-
5. _"Towards Training Large-Scale Pathology Foundation Models: from TCGA to Hospital Scale”_, [arXiv](https://arxiv.org/pdf/2404.15217)
|
|
506
475
|
|
|
507
476
|
## Contributing
|
|
508
477
|
|