5
5
6
6
import numpy as np
7
7
from scipy import stats , ndimage , misc
8
+ from scipy .interpolate import interp1d
8
9
from matplotlib .colors import colorConverter
9
10
10
11
import nibabel as nib
@@ -1542,13 +1543,16 @@ def scale_data_colormap(self, fmin, fmid, fmax, transparent, verbose=None):
1542
1543
data ["transparent" ] = transparent
1543
1544
self ._toggle_render (True , views )
1544
1545
1545
- def set_data_time_index (self , time_idx ):
1546
+ def set_data_time_index (self , time_idx , interpolation = 'linear' ):
1546
1547
"""Set the data time index to show
1547
1548
1548
1549
Parameters
1549
1550
----------
1550
- time_idx : int
1551
- time index
1551
+ time_idx : int | float
1552
+ Time index. Floats will cause samples to be interpolated.
1553
+ interpolation : str
1554
+ Interpolation method (``scipy.interpolate.interp1d`` parameter,
1555
+ default 'linear').
1552
1556
"""
1553
1557
if self .n_times is None :
1554
1558
raise RuntimeError ('cannot set time index with no time data' )
@@ -1559,7 +1563,14 @@ def set_data_time_index(self, time_idx):
1559
1563
for hemi in ['lh' , 'rh' ]:
1560
1564
data = self .data_dict [hemi ]
1561
1565
if data is not None :
1562
- plot_data = data ["array" ][:, time_idx ]
1566
+ # interpolation
1567
+ if isinstance (time_idx , float ):
1568
+ times = np .arange (self .n_times )
1569
+ ifunc = interp1d (times , data ['array' ], interpolation , 1 )
1570
+ plot_data = ifunc (time_idx )
1571
+ else :
1572
+ plot_data = data ["array" ][:, time_idx ]
1573
+
1563
1574
if data ["smooth_mat" ] is not None :
1564
1575
plot_data = data ["smooth_mat" ] * plot_data
1565
1576
for surf in data ["surfaces" ]:
@@ -1568,7 +1579,11 @@ def set_data_time_index(self, time_idx):
1568
1579
1569
1580
# Update time label
1570
1581
if data ["time_label" ]:
1571
- time = data ["time" ][time_idx ]
1582
+ if isinstance (time_idx , float ):
1583
+ ifunc = interp1d (times , data ['time' ])
1584
+ time = ifunc (time_idx )
1585
+ else :
1586
+ time = data ["time" ][time_idx ]
1572
1587
self .update_text (data ["time_label" ] % time , "time_label" )
1573
1588
self ._toggle_render (True , views )
1574
1589
@@ -1932,7 +1947,8 @@ def save_imageset(self, prefix, views, filetype='png', colorbar='auto',
1932
1947
1933
1948
def save_image_sequence (self , time_idx , fname_pattern , use_abs_idx = True ,
1934
1949
row = - 1 , col = - 1 , montage = 'single' , orientation = 'h' ,
1935
- border_size = 15 , colorbar = 'auto' ):
1950
+ border_size = 15 , colorbar = 'auto' ,
1951
+ interpolation = 'linear' ):
1936
1952
"""Save a temporal image sequence
1937
1953
1938
1954
The files saved are named "fname_pattern % (pos)" where "pos" is a
@@ -1966,6 +1982,9 @@ def save_image_sequence(self, time_idx, fname_pattern, use_abs_idx=True,
1966
1982
For 'auto', the colorbar is shown in the middle view (default).
1967
1983
For int or list of int, the colorbar is shown in the specified
1968
1984
views. For ``None``, no colorbar is shown.
1985
+ interpolation : str
1986
+ Interpolation method (``scipy.interpolate.interp1d`` parameter,
1987
+ default 'linear').
1969
1988
1970
1989
Returns
1971
1990
-------
@@ -1976,7 +1995,7 @@ def save_image_sequence(self, time_idx, fname_pattern, use_abs_idx=True,
1976
1995
images_written = list ()
1977
1996
rel_pos = 0
1978
1997
for idx in time_idx :
1979
- self .set_data_time_index (idx )
1998
+ self .set_data_time_index (idx , interpolation )
1980
1999
fname = fname_pattern % (idx if use_abs_idx else rel_pos )
1981
2000
if montage == 'single' :
1982
2001
self .save_single_image (fname , row , col )
@@ -2068,28 +2087,27 @@ def save_montage(self, filename, order=['lat', 'ven', 'med'],
2068
2087
cb .visible = colorbars_visibility [cb ]
2069
2088
return out
2070
2089
2071
- def save_movie (self , fname , tstart = None , tstop = None , step = 1 ,
2072
- time_idx = None , montage = 'current' , orientation = 'h' ,
2073
- border_size = 15 , colorbar = 'auto' , framerate = 10 ,
2090
+ def save_movie (self , fname , time_dilation = 4. , tmin = None , tmax = None ,
2091
+ interpolation = 'linear' , montage = 'current' , orientation = 'h' ,
2092
+ border_size = 15 , colorbar = 'auto' , framerate = 25 ,
2074
2093
codec = 'mpeg4' , row = - 1 , col = - 1 ):
2075
2094
"""Save a movie (for data with a time axis)
2076
2095
2077
2096
Parameters
2078
2097
----------
2079
2098
fname : str
2080
2099
Path at which to save the movie.
2081
- tstart : None | float
2100
+ time_dilation : float
2101
+ Factor by which to stretch time (default 4). For example, an epoch
2102
+ from -100 to 600 ms lasts 700 ms. With ``time_dilation=4`` this
2103
+ would result in a 2.8 s long movie.
2104
+ tmin : float
2082
2105
First time point to include (default: all data).
2083
- tstop : None | float
2084
- Time point at which to stop the movie (exclusive; default: all
2085
- data).
2086
- step : int
2087
- Number of data frames to step forward between movie frames
2088
- (default 1).
2089
- time_idx : None | array
2090
- Index that selects time points form the time axis from which to
2091
- make the movie. If time_idx is specified, neither of tstart, tstop
2092
- or tstep should be specified.
2106
+ tmax : float
2107
+ Last time point to include (default: all data).
2108
+ interpolation : str
2109
+ Interpolation method (``scipy.interpolate.interp1d`` parameter,
2110
+ default 'linear').
2093
2111
montage: 'current' | 'single' | list
2094
2112
Views to include in the images: 'current' (default) uses the
2095
2113
currently displayed image; 'single' uses a single view, specified
@@ -2105,7 +2123,7 @@ def save_movie(self, fname, tstart=None, tstop=None, step=1,
2105
2123
For int or list of int, the colorbar is shown in the specified
2106
2124
views. For ``None``, no colorbar is shown.
2107
2125
framerate : float
2108
- Framerate of the movie (frames per second).
2126
+ Framerate of the movie (frames per second, default 25 ).
2109
2127
codec : str
2110
2128
Codec to use (default 'mpeg4').
2111
2129
row : int
@@ -2119,36 +2137,40 @@ def save_movie(self, fname, tstart=None, tstop=None, step=1,
2119
2137
"downlaoded from http://ffmpeg.org/download.html." )
2120
2138
raise RuntimeError (err )
2121
2139
2122
- if tstart is not None :
2123
- start = self .index_for_time (tstart , rounding = 'up' )
2124
- else :
2125
- start = 0
2126
-
2127
- if tstop is not None :
2128
- stop = self .index_for_time (tstop , rounding = 'up' )
2129
- else :
2130
- stop = self .n_times
2131
-
2132
- if all (x is None for x in (tstart , tstop , step )):
2133
- if time_idx is None :
2134
- time_idx = np .arange (self .n_times )
2135
- elif time_idx is None :
2136
- time_idx = np .arange (start , stop , step )
2140
+ if tmin is None :
2141
+ tmin = self ._times [0 ]
2142
+ elif tmin < self ._times [0 ]:
2143
+ raise ValueError ("tmin=%r is smaller than the first time point "
2144
+ "(%r)" % (tmin , self ._times [0 ]))
2145
+
2146
+ if tmax is None :
2147
+ tmax = self ._times [- 1 ]
2148
+ elif tmax >= self ._times [- 1 ]:
2149
+ raise ValueError ("tmax=%r is greater than the latest time point "
2150
+ "(%r)" % (tmax , self ._times [- 1 ]))
2151
+
2152
+ # find indexes at which to create frames
2153
+ tstep = 1. / (framerate * time_dilation )
2154
+ if (tmax - tmin ) % tstep == 0 :
2155
+ tstop = tmax + tstep / 2.
2137
2156
else :
2138
- err = ("Both slice parameters (tstart, tstop, step) and "
2139
- "time_idx can not be specified at the same time." )
2140
- raise TypeError (err )
2157
+ tstop = tmax
2158
+ times = np .arange (tmin , tstop , tstep )
2159
+ interp_func = interp1d (self ._times , np .arange (self .n_times ))
2160
+ time_idx = interp_func (times )
2141
2161
2142
2162
n_times = len (time_idx )
2143
2163
if n_times == 0 :
2144
2164
raise ValueError ("No time points selected" )
2145
2165
2166
+ logger .debug ("Save movie for time points/samples\n %s\n %s"
2167
+ % (times , time_idx ))
2146
2168
tempdir = mkdtemp ()
2147
2169
frame_pattern = 'frame%%0%id.png' % (np .floor (np .log10 (n_times )) + 1 )
2148
2170
fname_pattern = os .path .join (tempdir , frame_pattern )
2149
2171
self .save_image_sequence (time_idx , fname_pattern , False , row ,
2150
2172
col , montage , orientation , border_size ,
2151
- colorbar )
2173
+ colorbar , interpolation )
2152
2174
ffmpeg (fname , fname_pattern , framerate , codec )
2153
2175
2154
2176
def animate (self , views , n_steps = 180. , fname = None , use_cache = False ,
0 commit comments