From: Thomas Fillon Date: Wed, 9 Oct 2013 13:29:41 +0000 (+0200) Subject: Change AnalyzerResult 'data' to 'dataObject' and add functions to access directly... X-Git-Tag: 0.5.0~42^2 X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=227984fe3bb78c3e97d0ee5be3671a4fa629ca9b;p=timeside.git Change AnalyzerResult 'data' to 'dataObject' and add functions to access directly to data, time and duration from an analyzerResult --- diff --git a/tests/test_AnalyzerResult.py b/tests/test_AnalyzerResult.py index d1dd63e..53952bc 100755 --- a/tests/test_AnalyzerResult.py +++ b/tests/test_AnalyzerResult.py @@ -26,55 +26,55 @@ class TestAnalyzerResult(TestCase): def testOnFloat(self): "float result" - self.result.data.value = 1.2 + self.result.dataObject.value = 1.2 def testOnInt(self): "integer result" - self.result.data.value = 1 + self.result.dataObject.value = 1 def testOnList(self): "list result" - self.result.data.value = [1., 2.] + self.result.dataObject.value = [1., 2.] def testOnString(self): "string result" - self.result.data.value = "hello" + self.result.dataObject.value = "hello" def testOnListOfString(self): "list of strings result" - self.result.data.value = ["hello", "hola"] + self.result.dataObject.value = ["hello", "hola"] def testOnListOfList(self): "list of lists result" - self.result.data.value = [[0, 1], [0, 1, 2]] + self.result.dataObject.value = [[0, 1], [0, 1, 2]] def testOnNumpyVectorOfFloat(self): "numpy vector of float" - self.result.data.value = ones(2, dtype='float') * pi + self.result.dataObject.value = ones(2, dtype='float') * pi def testOnNumpy2DArrayOfFloat64(self): "numpy 2d array of float64" - self.result.data.value = ones([2, 3], dtype='float64') * pi + self.result.dataObject.value = ones([2, 3], dtype='float64') * pi def testOnNumpy3DArrayOfInt32(self): "numpy 3d array of int32" - self.result.data.value = ones([2, 3, 2], dtype='int32') + self.result.dataObject.value = ones([2, 3, 2], dtype='int32') def testOnNumpyArrayOfStrings(self): "numpy array of strings" - self.result.data.value = array(['hello', 'hola']) + self.result.dataObject.value = array(['hello', 'hola']) def testOnEmptyList(self): "empty list" - self.result.data.value = [] + self.result.dataObject.value = [] def testOnNone(self): "None" - self.result.data.value = None + self.result.dataObject.value = None def testOnUnicode(self): "None" - self.result.data.value = None + self.result.dataObject.value = None def tearDown(self): pass @@ -113,7 +113,7 @@ def create_good_method_func(numpy_data_type): def method(self): "numpy %s" % str(numpy_data_type)[7:-1] import numpy - self.result.data.value = numpy_data_type(pi) + self.result.dataObject.value = numpy_data_type(pi) return method @@ -125,7 +125,7 @@ def create_bad_method_func(numpy_data_type): data = getattr(numpy, numpy_data_type)(pi) except ValueError: data = getattr(numpy, numpy_data_type)() - self.assertRaises(TypeError, self.result.data.__setattr__, 'value', data) + self.assertRaises(TypeError, self.result.dataObject.__setattr__, 'value', data) return method for numpy_data_type in good_numpy_data_types: diff --git a/tests/test_analyzer_dc.py b/tests/test_analyzer_dc.py index ae2ec27..3fd683d 100755 --- a/tests/test_analyzer_dc.py +++ b/tests/test_analyzer_dc.py @@ -25,7 +25,7 @@ class TestAnalyzerDC(TestCase): (decoder | self.analyzer).run() results = self.analyzer.results() for key in self.expected.keys(): - self.assertEquals(results[key].data.value, self.expected[key]) + self.assertEquals(results[key].dataObject.value, self.expected[key]) if __name__ == '__main__': unittest.main(testRunner=TestRunner()) diff --git a/tests/test_analyzer_level.py b/tests/test_analyzer_level.py index b298880..5ae9b73 100755 --- a/tests/test_analyzer_level.py +++ b/tests/test_analyzer_level.py @@ -33,7 +33,7 @@ class TestAnalyzerLevel(TestCase): (decoder | self.analyzer).run() results = self.analyzer.results() for key in self.expected.keys(): - self.assertEquals(results[key].data.value, self.expected[key]) + self.assertEquals(results[key].dataObject.value, self.expected[key]) #print results #print results.to_yaml() #print results.to_json() diff --git a/timeside/analyzer/aubio_melenergy.py b/timeside/analyzer/aubio_melenergy.py index 68945e7..6c8d162 100644 --- a/timeside/analyzer/aubio_melenergy.py +++ b/timeside/analyzer/aubio_melenergy.py @@ -76,7 +76,7 @@ class AubioMelEnergy(Analyzer): melenergy.idMetadata.unit='' # Set Data - melenergy.data.value = self.melenergy_results + melenergy.dataObject.value = self.melenergy_results self._results.add(melenergy) diff --git a/timeside/analyzer/aubio_mfcc.py b/timeside/analyzer/aubio_mfcc.py index 987d8b5..ca2df21 100644 --- a/timeside/analyzer/aubio_mfcc.py +++ b/timeside/analyzer/aubio_mfcc.py @@ -76,5 +76,5 @@ class AubioMfcc(Analyzer): mfcc.idMetadata.unit = "" mfcc.parameters = parameters - mfcc.data.value = self.mfcc_results + mfcc.dataObject.value = self.mfcc_results self._results.add(mfcc) diff --git a/timeside/analyzer/aubio_pitch.py b/timeside/analyzer/aubio_pitch.py index face938..fb34138 100644 --- a/timeside/analyzer/aubio_pitch.py +++ b/timeside/analyzer/aubio_pitch.py @@ -76,7 +76,7 @@ class AubioPitch(Analyzer): # parameters : None # TODO check with Piem "default" and "freq" in setup # Set Data - pitch.data.value = numpy.array(self.pitches) + pitch.dataObject.value = numpy.array(self.pitches) self._results.add(pitch) diff --git a/timeside/analyzer/aubio_specdesc.py b/timeside/analyzer/aubio_specdesc.py index c7594eb..865d2d8 100644 --- a/timeside/analyzer/aubio_specdesc.py +++ b/timeside/analyzer/aubio_specdesc.py @@ -81,7 +81,7 @@ class AubioSpecdesc(Analyzer): res_specdesc.idMetadata.unit = unit - res_specdesc.data.value = self.specdesc_results[method] + res_specdesc.dataObject.value = self.specdesc_results[method] self._results.add(res_specdesc) diff --git a/timeside/analyzer/aubio_temporal.py b/timeside/analyzer/aubio_temporal.py index 24ca77e..9f109ad 100644 --- a/timeside/analyzer/aubio_temporal.py +++ b/timeside/analyzer/aubio_temporal.py @@ -84,8 +84,8 @@ class AubioTemporal(Analyzer): # Set Data , dataMode='label', timeMode='event' # Event = list of (time, labelId) - onsets.data.label = numpy.ones(len(self.onsets)) - onsets.data.time = self.onsets + onsets.dataObject.label = numpy.ones(len(self.onsets)) + onsets.dataObject.time = self.onsets onsets.labelMetadata.label = {1: 'Onset'} @@ -104,10 +104,10 @@ class AubioTemporal(Analyzer): # Event = list of (time, value) # TODO : add time if len(self.onsets) > 1: - onsetrate.data.value = 60. / numpy.diff(self.onsets) - onsetrate.data.time = self.onsets[:-1] + onsetrate.dataObject.value = 60. / numpy.diff(self.onsets) + onsetrate.dataObject.time = self.onsets[:-1] else: - onsetrate.data.value = [] + onsetrate.dataObject.value = [] self._results.add(onsetrate) @@ -125,11 +125,11 @@ class AubioTemporal(Analyzer): if len(self.beats) > 1: duration = numpy.diff(self.beats) duration = numpy.append(duration,duration[-1]) - beats.data.time = self.beats - beats.data.duration = duration - beats.data.label = numpy.ones(len(self.beats)) + beats.dataObject.time = self.beats + beats.dataObject.duration = duration + beats.dataObject.label = numpy.ones(len(self.beats)) else: - beats.data.label = [] + beats.dataObject.label = [] beats.labelMetadata.label = {1: 'Beat'} @@ -149,11 +149,11 @@ class AubioTemporal(Analyzer): periods = 60. / numpy.diff(self.beats) periods = numpy.append(periods, periods[-1]) - bpm.data.time = self.beats - bpm.data.duration = duration - bpm.data.value = periods + bpm.dataObject.time = self.beats + bpm.dataObject.duration = duration + bpm.dataObject.value = periods else: - bpm.data.value = [] + bpm.dataObject.value = [] self._results.add(bpm) diff --git a/timeside/analyzer/core.py b/timeside/analyzer/core.py index 2fc9497..1d55914 100644 --- a/timeside/analyzer/core.py +++ b/timeside/analyzer/core.py @@ -233,6 +233,7 @@ class AudioMetadata(MetadataObject): _default_value = OrderedDict([('uri', ''), ('start', 0), ('duration', None), + ('IS_SEGMENT', None), ('channels', None), ('channelsManagement', '')]) @@ -289,14 +290,15 @@ class FrameMetadata(MetadataObject): ('stepsize', None)]) -class AnalyzerData(MetadataObject): +class DataObject(MetadataObject): ''' Metadata object to handle Frame related Metadata Attributes ---------- - data : numpy array + value : numpy array + label : numpy array of int time : numpy array of float duration : numpy array of float @@ -338,7 +340,7 @@ class AnalyzerData(MetadataObject): elif name == 'dataType': return - super(AnalyzerData, self).__setattr__(name, value) + super(DataObject, self).__setattr__(name, value) def __eq__(self, other): try: @@ -429,7 +431,7 @@ class AnalyzerResult(MetadataObject): A new MetadataObject with the following attributes : - dataMode - timeMode - - data : :class:`AnalyzerData` + - data : :class:`DataObject` - idMetadata : :class:`IdMetadata` - audioMetadata : :class:`AudioMetadata` - frameMetadata : :class:`FrameMetadata` @@ -442,7 +444,7 @@ class AnalyzerResult(MetadataObject): _default_value = OrderedDict([('dataMode', None), ('timeMode', None), ('idMetadata', None), - ('data', None), + ('dataObject', None), ('audioMetadata', None), ('frameMetadata', None), ('labelMetadata', None), @@ -460,7 +462,7 @@ class AnalyzerResult(MetadataObject): def __setattr__(self, name, value): setFuncDict = {'idMetadata': IdMetadata, - 'data': AnalyzerData, + 'dataObject': DataObject, 'audioMetadata': AudioMetadata, 'frameMetadata': FrameMetadata, 'labelMetadata': LabelMetadata, @@ -482,13 +484,13 @@ class AnalyzerResult(MetadataObject): raise TypeError('Wrong argument') elif name == 'dataMode': if self[name] is not None: - raise AttributeError("The value of attribute ''timeMode'' \\\ + raise AttributeError("The value of attribute ''dataMode'' \\\ can not change after setup") if value == 'value': del self.labelMetadata - del self.data.label + del self.dataObject.label elif value == 'label': - del self.data.value + del self.dataObject.value elif value is None: pass else: @@ -500,12 +502,12 @@ class AnalyzerResult(MetadataObject): can not change after setup") if value == 'framewise': - del self.data.time - del self.data.duration + del self.dataObject.time + del self.dataObject.duration pass elif value == 'global': - del self.data.time - del self.data.duration + del self.dataObject.time + del self.dataObject.duration del self.frameMetadata pass @@ -513,7 +515,7 @@ class AnalyzerResult(MetadataObject): del self.frameMetadata elif value == 'event': del self.frameMetadata - del self.data.duration + del self.dataObject.duration pass elif value is None: @@ -527,7 +529,7 @@ class AnalyzerResult(MetadataObject): return dict([(key, self[key].as_dict()) for key in self.keys() if hasattr(self[key], 'as_dict')] + [('dataMode', self.dataMode), ('timeMode', self.timeMode)]) - + # TODO : check if it can be simplified now def to_xml(self): import xml.etree.ElementTree as ET root = ET.Element('result') @@ -561,6 +563,34 @@ class AnalyzerResult(MetadataObject): return result + def data(self): + return {key: self.dataObject[key] for key in ['value', 'label'] if key in self.dataObject.keys()} + + def time(self): + if self.timeMode == 'global': + return self.audioMetadata.start + elif self.timeMode == 'framewise': + return (self.audioMetadata.start + + self.frameMetadata.stepsize * numpy.arange(0,len(self))) + else: + return self.dataObject.time + pass + + def duration(self): + if self.timeMode == 'global': + return self.audioMetadata.duration + elif self.timeMode == 'framewise': + return self.frameMetadata.blockwise * numpy.ones(len(self)) + elif self.timeMode == 'event': + return numpy.zeros(len(self)) + elif self.timeMode == 'segment': + return self.dataObject.duration + + def __len__(self): + if self.dataMode == 'value': + return len(self.dataObject.value) + else: + return len(self.dataObject.label) # @property @@ -589,7 +619,7 @@ class AnalyzerResultContainer(dict): >>> (d|a).run() #doctest: +ELLIPSIS >>> a.new_result() #doctest: +ELLIPSIS - AnalyzerResult(dataMode=None, timeMode=None, idMetadata=IdMetadata(id='', name='', unit='', description='', date='...', version='...', author='TimeSide'), data=AnalyzerData(value=None, label=array([], dtype=int64), time=array([], dtype=float64), duration=array([], dtype=float64)), audioMetadata=AudioMetadata(uri='file:///.../tests/samples/sweep.wav', start=1.0, duration=7.0, channels=None, channelsManagement=''), frameMetadata=FrameMetadata(samplerate=None, blocksize=None, stepsize=None), labelMetadata=LabelMetadata(label=None, description=None, labelType='mono'), parameters={}) + AnalyzerResult(dataMode=None, timeMode=None, idMetadata=IdMetadata(id='', name='', unit='', description='', date='...', version='...', author='TimeSide'), data=DataObject(value=None, label=array([], dtype=int64), time=array([], dtype=float64), duration=array([], dtype=float64)), audioMetadata=AudioMetadata(uri='file:///.../tests/samples/sweep.wav', start=1.0, duration=7.0, channels=None, channelsManagement=''), frameMetadata=FrameMetadata(samplerate=None, blocksize=None, stepsize=None), labelMetadata=LabelMetadata(label=None, description=None, labelType='mono'), parameters={}) >>> resContainer = coreA.AnalyzerResultContainer() ''' @@ -636,7 +666,7 @@ class AnalyzerResultContainer(dict): root = ET.Element('timeside') for result in self.values(): - if result: + if result is not None: root.append(ET.fromstring(result.to_xml())) return ET.tostring(root, encoding="utf-8", method="xml") @@ -745,7 +775,7 @@ class AnalyzerResultContainer(dict): group.attrs['dataMode'] = res['dataMode'] group.attrs['timeMode'] = res['timeMode'] for key in res.keys(): - if key not in ['dataMode', 'timeMode', 'data']: + if key not in ['dataMode', 'timeMode', 'dataObject']: subgroup = group.create_group(key) # Write attributes @@ -755,7 +785,7 @@ class AnalyzerResultContainer(dict): subgroup.attrs[name] = res[key][name] # Write Datasets - key = 'data' + key = 'dataObject' subgroup = group.create_group(key) for dsetName in res[key].keys(): if res[key][dsetName] is not None: @@ -788,7 +818,7 @@ class AnalyzerResultContainer(dict): for name, value in subgroup.attrs.items(): result[subgroup_name][name] = value - if subgroup_name == 'data': + if subgroup_name == 'dataObject': for dsetName, dset in subgroup.items(): # Load value from the hdf5 dataset and store in data # FIXME : the following conditional statement is to prevent @@ -874,42 +904,22 @@ class Analyzer(Processor): from datetime import datetime result = AnalyzerResult(dataMode=dataMode, timeMode=timeMode) + # Automatically write known metadata - result.idMetadata = IdMetadata( - date=datetime.now().replace(microsecond=0).isoformat(' '), - version=TimeSideVersion, - author='TimeSide') - result.audioMetadata = AudioMetadata(uri=self.mediainfo()['uri'], - start=self.mediainfo()['start'], - duration=self.mediainfo()['duration']) - - result.data = AnalyzerData() - - if dataMode == 'value': - pass - elif dataMode == 'label': - result.labelMetadata = LabelMetadata() - else: - # raise ArgError('') - pass + result.idMetadata.date = datetime.now().replace( + microsecond=0).isoformat(' ') + result.idMetadata.version = TimeSideVersion + result.idMetadata.author = 'TimeSide' + + result.audioMetadata.uri = self.mediainfo()['uri'] + result.audioMetadata.start = self.mediainfo()['start'] + result.audioMetadata.duration = self.mediainfo()['duration'] + result.audioMetadata.IS_SEGMENT = self.mediainfo()['IS_SEGMENT'] if timeMode == 'framewise': - result.frameMetadata = FrameMetadata( - samplerate=self.result_samplerate, - blocksize=self.result_blocksize, - stepsize=self.result_stepsize) - elif timeMode == 'global': - # None : handle by data - pass - elif timeMode == 'segment': - # None : handle by data - pass - elif timeMode == 'event': - # None : handle by data, duration = 0 - pass - else: - # raise ArgError('') - pass + result.frameMetadata.samplerate = self.result_samplerate + result.frameMetadata.blocksize = self.result_blocksize + result.frameMetadata.stepsize = self.result_stepsize return result diff --git a/timeside/analyzer/dc.py b/timeside/analyzer/dc.py index da8fe5e..319931d 100644 --- a/timeside/analyzer/dc.py +++ b/timeside/analyzer/dc.py @@ -54,5 +54,5 @@ class MeanDCShift(Analyzer): dc_result.idMetadata.name = "Mean DC shift" dc_result.idMetadata.unit = "%" # Set Data - dc_result.data.value = numpy.round(numpy.mean(100*self.values),3) + dc_result.dataObject.value = numpy.round(numpy.mean(100*self.values),3) self._results.add(dc_result) \ No newline at end of file diff --git a/timeside/analyzer/level.py b/timeside/analyzer/level.py index bf406ab..85d9407 100644 --- a/timeside/analyzer/level.py +++ b/timeside/analyzer/level.py @@ -68,7 +68,7 @@ class Level(Analyzer): max_level.idMetadata.name = "Max level" max_level.idMetadata.unit = "dBFS" - max_level.data.value = numpy.round(20*numpy.log10(self.max_value), 3) + max_level.dataObject.value = numpy.round(20*numpy.log10(self.max_value), 3) self._results.add(max_level) # RMS level @@ -77,7 +77,7 @@ class Level(Analyzer): rms_level.idMetadata.name="RMS level" rms_level.idMetadata.unit="dBFS" - rms_level.data.value = numpy.round(20*numpy.log10( + rms_level.dataObject.value = numpy.round(20*numpy.log10( numpy.sqrt(numpy.mean(self.mean_values))), 3) self._results.add(rms_level) diff --git a/timeside/analyzer/yaafe.py b/timeside/analyzer/yaafe.py index e2fbaf8..a212ef3 100644 --- a/timeside/analyzer/yaafe.py +++ b/timeside/analyzer/yaafe.py @@ -96,9 +96,9 @@ class Yaafe(Analyzer): result.idMetadata.name = name result.idMetadata.unit = '' # Read Yaafe Results - result.data.value = self.yaafe_engine.readOutput(featName) + result.dataObject.value = self.yaafe_engine.readOutput(featName) # Store results in Container - if len(result.data.value): + if len(result.dataObject.value): self._results.add(result)