1414# limitations under the License.
1515"""A specific mesh or 3D array."""
1616
17- from typing import List , Dict , Union , Set , TYPE_CHECKING
17+ from typing import Iterable , List , Dict , Union , Set , TYPE_CHECKING
1818from dataclasses import dataclass
1919from time import sleep
2020import json
@@ -633,6 +633,7 @@ def __init__(
633633 label : int = None ,
634634 fragment : str = None ,
635635 threshold : float = None ,
636+ time_index : int = None ,
636637 ):
637638 """
638639 A prescribed Volume to fetch specified label and fragment.
@@ -647,6 +648,8 @@ def __init__(
647648 If a volume is fragmented, get a specified one.
648649 threshold : float, default None
649650 Provide a float value to threshold the image.
651+ time_index: int = None,
652+ If parent volume is a timeseries Nifti, filter a time index without fetching the full image.
650653 """
651654 name = parent_volume .name
652655 if label :
@@ -655,6 +658,8 @@ def __init__(
655658 name += f" - fragment: { fragment } "
656659 if threshold :
657660 name += f" - threshold: { threshold } "
661+ if time_index :
662+ name += f" - time index: { time_index } "
658663 Volume .__init__ (
659664 self ,
660665 space_spec = parent_volume ._space_spec ,
@@ -664,6 +669,7 @@ def __init__(
664669 self .fragment = fragment
665670 self .label = label
666671 self .threshold = threshold
672+ self .time_index = time_index
667673
668674 def fetch (
669675 self ,
@@ -680,7 +686,8 @@ def fetch(
680686 kwargs ["label" ] = self .label
681687
682688 result = super ().fetch (format = format , ** kwargs )
683-
689+ if self .time_index is not None :
690+ result = result .slicer [:, :, :, self .time_index ]
684691 if self .threshold is not None :
685692 assert self .label is None
686693 if not isinstance (result , Nifti1Image ):
@@ -710,6 +717,29 @@ def get_boundingbox(
710717 )
711718
712719
720+ class TimeSeriesVolume (Volume ):
721+ def __init__ (
722+ self ,
723+ time_index : np .ndarray ,
724+ ** kwargs ,
725+ ):
726+ Volume .__init__ (self , ** kwargs )
727+ self .time_index = time_index
728+
729+ def __iter__ (self ) -> Iterable [FilteredVolume ]:
730+ yield from (
731+ FilteredVolume (parent_volume = self , time_index = t )
732+ for t in self .time_index
733+ )
734+
735+ def get_index (self , time_index : int ):
736+ return FilteredVolume (parent_volume = self , time_index = time_index )
737+
738+ def fetch (self , format : str = None , time_index : int = None , ** kwargs ):
739+ img = super ().fetch (format , ** kwargs )
740+ return img .slicer [:, :, :, time_index ] if time_index else img
741+
742+
713743class ReducedVolume (Volume ):
714744 def __init__ (
715745 self ,
@@ -832,14 +862,17 @@ def from_file(filename: str, space: str, name: str) -> Volume:
832862 )
833863
834864
835- def from_nifti (nifti : Nifti1Image , space : str , name : str ) -> Volume :
865+ def from_nifti (nifti : Nifti1Image , space : str , name : str , time_index : np . ndarray = None ) -> Union [ Volume , TimeSeriesVolume ] :
836866 """Builds a nifti volume from a Nifti image."""
837867 spaceobj = get_registry ("Space" ).get (space )
838- return Volume (
868+ kwargs = dict (
839869 space_spec = {"@id" : spaceobj .id },
840870 providers = [_providers .NiftiProvider ((np .asanyarray (nifti .dataobj ), nifti .affine ))],
841871 name = name
842872 )
873+ if time_index is None :
874+ return Volume (** kwargs )
875+ return TimeSeriesVolume (time_index = time_index , ** kwargs )
843876
844877
845878def from_array (
0 commit comments