Package mvpa :: Package datasets :: Module channel
[hide private]
[frames] | no frames]

Source Code for Module mvpa.datasets.channel

  1  # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- 
  2  # vi: set ft=python sts=4 ts=4 sw=4 et: 
  3  ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## 
  4  # 
  5  #   See COPYING file distributed along with the PyMVPA package for the 
  6  #   copyright and license terms. 
  7  # 
  8  ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## 
  9  """Dataset handling data structured in channels.""" 
 10   
 11  __docformat__ = 'restructuredtext' 
 12   
 13   
 14  import numpy as N 
 15   
 16  from mvpa.datasets.mapped import MappedDataset 
 17  from mvpa.mappers.mask import MaskMapper 
 18  from mvpa.base.dochelpers import enhancedDocString 
 19   
 20  import mvpa.support.copy as copy 
 21   
 22  from mvpa.base import externals 
 23   
 24  if externals.exists('scipy'): 
 25      from scipy import signal 
 26   
 27   
28 -class ChannelDataset(MappedDataset):
29 """Dataset handling data structured into channels. 30 31 Channels are assumes to contain several timepoints, thus this Dataset 32 stores some additional properties (reference time `t0`, temporal 33 distance of two timepoints `dt` and `channelids` (names)). 34 """
35 - def __init__(self, samples=None, dsattr=None, 36 t0=None, dt=None, channelids=None, **kwargs):
37 """Initialize ChannelDataset. 38 39 :Parameters: 40 samples: ndarray 41 Three-dimensional array: (samples x channels x timepoints). 42 t0: float 43 Reference time of the first timepoint. Can be used to preserve 44 information about the onset of some stimulation. Preferably in 45 seconds. 46 dt: float 47 Temporal distance between two timepoints. Has to be given in 48 seconds. Otherwise `samplingrate` property will not return 49 `Hz`. 50 channelids: list 51 List of channel names. 52 """ 53 # if dsattr is none, set it to an empty dict 54 if dsattr is None: 55 dsattr = {} 56 57 # check samples 58 if not samples is None and len(samples.shape) != 3: 59 raise ValueError, \ 60 "ChannelDataset takes 3D array as samples." 61 62 # charge dataset properties 63 # but only if some value 64 if (not dt is None) or not dsattr.has_key('ch_dt'): 65 dsattr['ch_dt'] = dt 66 if (not channelids is None) or not dsattr.has_key('ch_ids'): 67 dsattr['ch_ids'] = channelids 68 if (not t0 is None) or not dsattr.has_key('ch_t0'): 69 dsattr['ch_t0'] = t0 70 71 # come up with mapper if fresh samples were provided 72 if not samples is None: 73 mapper = MaskMapper(N.ones(samples.shape[1:], dtype='bool')) 74 else: 75 # Doesn't make difference at the moment, but might come 'handy'? 76 mapper = dsattr.get('mapper', None) 77 78 # init dataset 79 MappedDataset.__init__(self, 80 samples=samples, 81 mapper=mapper, 82 dsattr=dsattr, 83 **(kwargs))
84 85 86 __doc__ = enhancedDocString('ChannelDataset', locals(), MappedDataset) 87 88
89 - def substractBaseline(self, t=None):
90 """Substract mean baseline signal from the each timepoint. 91 92 The baseline is determined by computing the mean over all timepoints 93 specified by `t`. 94 95 The samples of the dataset are modified in-place and nothing is 96 returned. 97 98 :Parameter: 99 t: int | float | None 100 If an integer, `t` denotes the number of timepoints in the from the 101 start of each sample to be used to compute the baseline signal. 102 If a floating point value, `t` is the duration of the baseline 103 window from the start of each sample in whatever unit 104 corresponding to the datasets `samplingrate`. Finally, if `None` 105 the `t0` property of the dataset is used to determine `t` as it 106 would have been specified as duration. 107 """ 108 # if no baseline length is given, use t0 109 if t is None: 110 t = N.abs(self.t0) 111 112 # determine length of baseline in samples 113 if isinstance(t, float): 114 t = N.round(t * self.samplingrate) 115 116 # get original data 117 data = self.O 118 119 # compute baseline 120 # XXX: shouldn't this be done per chunk? 121 baseline = N.mean(data[:, :, :t], axis=2) 122 # remove baseline 123 data -= baseline[..., N.newaxis] 124 125 # put data back into dataset 126 self.samples[:] = self.mapForward(data)
127 128 129 if externals.exists('scipy'):
130 - def resample(self, nt=None, sr=None, dt=None, window='ham', 131 inplace=True, **kwargs):
132 """Convenience method to resample data sample channel-wise. 133 134 Resampling target can be specified by number of timepoint 135 or temporal distance or sampling rate. 136 137 Please note that this method only operates on 138 `ChannelDataset` and always returns such. 139 140 :Parameters: 141 nt: int 142 Number of timepoints to resample to. 143 dt: float 144 Temporal distance of samples after resampling. 145 sr: float 146 Target sampling rate. 147 inplace : bool 148 If inplace=False, it would create and return a new dataset 149 with new samples 150 **kwargs: 151 All additional arguments are passed to resample() from 152 scipy.signal 153 154 :Return: 155 ChannelDataset 156 """ 157 if nt is None and sr is None and dt is None: 158 raise ValueError, \ 159 "Required argument missing. Either needs ntimepoints, sr or dt." 160 161 # get data in original shape 162 orig_data = self.O 163 164 if len(orig_data.shape) != 3: 165 raise ValueError, "resample() only works with data from ChannelDataset." 166 167 orig_nt = orig_data.shape[2] 168 orig_length = self.dt * orig_nt 169 170 if nt is None: 171 # translate dt or sr into nt 172 if not dt is None: 173 nt = orig_nt * float(self.dt) / dt 174 elif not sr is None: 175 nt = orig_nt * float(sr) / self.samplingrate 176 else: 177 raise RuntimeError, 'This should not happen!' 178 else: 179 raise RuntimeError, 'This should not happen!' 180 181 182 nt = N.round(nt) 183 184 # downsample data 185 data = signal.resample(orig_data, nt, axis=2, window=window, **kwargs) 186 new_dt = float(orig_length) / nt 187 188 dsattr = self._dsattr 189 190 # would be needed for not inplace generation 191 if inplace: 192 dsattr['ch_dt'] = new_dt 193 # XXX We could have resampled range(nsamples) and 194 # rounded it. and adjust then mapper's mask 195 # accordingly instead of creating a new one. 196 # It would give us opportunity to assess what 197 # resampling did... 198 mapper = MaskMapper(N.ones(data.shape[1:], dtype='bool')) 199 # reassign a new mapper. 200 dsattr['mapper'] = mapper 201 self.samples = mapper.forward(data) 202 return self 203 else: 204 # we have to pass dsattr inside to don't loose 205 # some additional attributes such as 206 # labels_map 207 dsattr = copy.deepcopy(dsattr) 208 return ChannelDataset(data=self._data, 209 dsattr=dsattr, 210 samples=data, 211 t0=self.t0, 212 dt=new_dt, 213 channelids=self.channelids, 214 copy_data=True, 215 copy_dsattr=False)
216 217 channelids = property(fget=lambda self: self._dsattr['ch_ids'], 218 doc='List of channel IDs') 219 t0 = property(fget=lambda self: self._dsattr['ch_t0'], 220 doc='Temporal position of first sample in the ' \ 221 'timeseries (in seconds) -- possibly relative ' \ 222 'to stimulus onset.') 223 dt = property(fget=lambda self: self._dsattr['ch_dt'], 224 doc='Time difference between two samples ' \ 225 '(in seconds).') 226 samplingrate = property(fget=lambda self: 1.0 / self._dsattr['ch_dt'], 227 doc='Yeah, sampling rate.')
228