From d5ee7a9e31189280098ac3af1e17960e85b7ab07 Mon Sep 17 00:00:00 2001 From: Matt McCallum Date: Sat, 2 Jan 2021 15:12:11 -0800 Subject: [PATCH] - Updated JAMs schema to be json schenma compliant - Previously dense observation types are now entered as a single observation in the Annotation observation list, they no longer redefine the observation list itself, rather, just the elements within it. This means that all Annotations now have a list of observations, the elements of which can be dense observations themselves - the import_labs function has been moved from the util module to the core module. In a future PR it should be modified to be a constructor for JObjects - Fixed serialization JAMs for bools, lists and dicts - Updated jsonschema to latest version - necessary for determining namespaces based on a const namespace property - Local namespaces are no longer supported - a necessity to become jsonschema compliant - Version bumped - Tests updated to adhere to new schema for objects with DenseObservations - Removed spurious validation and __schema__ methods / attributes in jams.core module - add_namespace and is_dense is removed from the jams.schema module. All namespaces are now available in the jams.schema.NAMESPACES dictionary - schema for each observation type is now available in the jams.schema.OBSERVATIONS_SCHEMA dictionary --- jams/__init__.py | 15 -- jams/core.py | 244 ++++++++++++------ jams/nsconvert.py | 16 +- jams/schema.py | 171 ++++-------- jams/schemata/jams_schema.json | 85 +++--- jams/schemata/namespaces/beat/beat.json | 48 +++- jams/schemata/namespaces/beat/position.json | 47 +++- jams/schemata/namespaces/chord/chord.json | 31 ++- jams/schemata/namespaces/chord/harte.json | 31 ++- jams/schemata/namespaces/chord/roman.json | 33 ++- jams/schemata/namespaces/key/key_mode.json | 33 ++- jams/schemata/namespaces/lyrics/bow.json | 31 ++- jams/schemata/namespaces/lyrics/lyrics.json | 35 ++- jams/schemata/namespaces/misc/blob.json | 34 ++- jams/schemata/namespaces/misc/scaper.json | 87 ++++--- jams/schemata/namespaces/misc/vector.json | 31 ++- jams/schemata/namespaces/mood/thayer.json | 31 ++- jams/schemata/namespaces/onset/onset.json | 35 ++- jams/schemata/namespaces/pattern/jku.json | 31 ++- jams/schemata/namespaces/pitch/class.json | 38 ++- .../schemata/namespaces/pitch/contour_hz.json | 48 +++- jams/schemata/namespaces/pitch/hz.json | 40 ++- jams/schemata/namespaces/pitch/midi.json | 42 ++- jams/schemata/namespaces/pitch/note_hz.json | 37 ++- jams/schemata/namespaces/pitch/note_midi.json | 36 ++- jams/schemata/namespaces/segment/multi.json | 34 ++- jams/schemata/namespaces/segment/open.json | 36 ++- .../namespaces/segment/salami_function.json | 33 ++- .../namespaces/segment/salami_lower.json | 33 ++- .../namespaces/segment/salami_upper.json | 33 ++- jams/schemata/namespaces/segment/tut.json | 34 ++- jams/schemata/namespaces/tag/cal10k.json | 27 +- jams/schemata/namespaces/tag/cal500.json | 31 ++- jams/schemata/namespaces/tag/gtzan.json | 33 ++- .../namespaces/tag/medleydb_instruments.json | 31 ++- .../namespaces/tag/msd_tagtraum_cd1.json | 28 +- .../namespaces/tag/msd_tagtraum_cd2.json | 28 +- jams/schemata/namespaces/tag/open.json | 35 ++- .../schemata/namespaces/tag/tag_audioset.json | 27 +- .../namespaces/tag/tag_audioset_genre.json | 29 ++- .../tag/tag_audioset_instruments.json | 29 ++- .../namespaces/tag/tag_fma_genre.json | 29 ++- .../namespaces/tag/tag_fma_subgenre.json | 29 ++- .../namespaces/tag/tag_urbansound.json | 27 +- jams/schemata/namespaces/tempo/tempo.json | 28 +- jams/schemata/observations.json | 29 +++ jams/schemata/validate.py | 11 +- jams/sonify.py | 6 +- jams/util.py | 95 ------- jams/version.py | 4 +- tests/fixtures/transcription_est.jams | 62 ++--- tests/fixtures/transcription_ref.jams | 54 ++-- tests/test_convert.py | 34 ++- tests/test_display.py | 3 +- tests/test_eval.py | 10 +- tests/test_jams.py | 33 +++ tests/test_ns.py | 36 ++- tests/test_schema.py | 58 +---- tests/test_sonify.py | 10 +- tests/test_util.py | 34 --- 60 files changed, 1602 insertions(+), 801 deletions(-) create mode 100644 jams/schemata/observations.json diff --git a/jams/__init__.py b/jams/__init__.py index ebcf0a1..1caf65b 100644 --- a/jams/__init__.py +++ b/jams/__init__.py @@ -14,18 +14,3 @@ from .core import * from .nsconvert import convert -from .schema import list_namespaces - - -# Populate the namespace mapping -for _ in util.find_with_extension(resource_filename(__name__, schema.NS_SCHEMA_DIR), - 'json'): - schema.add_namespace(_) - -# Populate local namespaces - -try: - for _ in util.find_with_extension(os.environ['JAMS_SCHEMA_DIR'], 'json'): - schema.add_namespace(_) -except KeyError: - pass diff --git a/jams/core.py b/jams/core.py index 2f0160e..94e4311 100644 --- a/jams/core.py +++ b/jams/core.py @@ -30,6 +30,7 @@ Sandbox JObject Observation + import_lab """ import json @@ -41,6 +42,8 @@ import contextlib import gzip import six +import math +import itertools import numpy as np import pandas as pd @@ -57,7 +60,7 @@ 'JObject', 'Sandbox', 'Annotation', 'Curator', 'AnnotationMetadata', 'FileMetadata', 'AnnotationArray', 'JAMS', - 'Observation'] + 'Observation', 'import_lab'] def deprecated(version, version_removed): @@ -672,6 +675,27 @@ def _display_properties(self): ('data', 'Data'), ('sandbox', 'Sandbox')] + def _combine_observations(self): + """ + Combines all observations in the data to a single pair of arrays, one + containing all times, one containing all values. + + Returns + ------- + times: list(float) + A flat list of all times in all observations. + vals: list(...) + A flat list of all values in all observations. + """ + try: + times = list(itertools.chain(*[obs.time for obs in self.data])) + # If the time was an iterable, it's okay combine all values in the same way. + vals = list(itertools.chain(*[obs.value for obs in self.data])) + except TypeError: + times = [obs.time for obs in self.data] + vals = [obs.value for obs in self.data] + return times, vals + def append(self, time=None, duration=None, value=None, confidence=None): '''Append an observation to the data field @@ -692,9 +716,35 @@ def append(self, time=None, duration=None, value=None, confidence=None): >>> ann = jams.Annotation(namespace='chord') >>> ann.append(time=3, duration=2, value='E#') ''' + # NOTE [matthew.mccallum 01.02.21]: Currently we check if time and duration + # are lists to determine if we need to handle them differently. This type + # specific handling should not be required once we move on to phase 3 of + # the issue here: + # https://github.com/marl/jams/issues/208 + # That is, the different behaviour based on the type of observation should + # be handled in the observation type that is assigned to each annotation, + # rather than this being mixed in with the Annotation itself and it being + # the Annotation's responsibility to know how to handle each observation type. + + try: + # Convert any iterables into lists + time = [float(t) for t in time] + duration = [float(d) for d in duration] + if value is None: + value = [None]*len(time) + else: + value = [v for v in value] + if confidence is None: + confidence = [None]*len(time) + else: + confidence = [c for c in confidence] + + except TypeError: + time = float(time) + duration = float(duration) - self.data.add(Observation(time=float(time), - duration=float(duration), + self.data.add(Observation(time=time, + duration=duration, value=value, confidence=confidence)) @@ -733,55 +783,6 @@ def append_columns(self, columns): columns['value'], columns['confidence'])]) - def validate(self, strict=True): - '''Validate this annotation object against the JAMS schema, - and its data against the namespace schema. - - Parameters - ---------- - strict : bool - If `True`, then schema violations will cause an Exception. - If `False`, then schema violations will issue a warning. - - Returns - ------- - valid : bool - `True` if the object conforms to schema. - `False` if the object fails to conform to schema, - but `strict == False`. - - Raises - ------ - SchemaError - If `strict == True` and the object fails validation - - See Also - -------- - JObject.validate - ''' - - # Get the schema for this annotation - ann_schema = schema.namespace_array(self.namespace) - - valid = True - - try: - schema.VALIDATOR.validate(self.__json_light__(data=False), - schema.JAMS_SCHEMA) - - # validate each record in the frame - data_ser = [serialize_obj(obs) for obs in self.data] - schema.VALIDATOR.validate(data_ser, ann_schema) - - except jsonschema.ValidationError as invalid: - if strict: - raise SchemaError(str(invalid)) - else: - warnings.warn(str(invalid)) - valid = False - - return valid - def trim(self, start_time, end_time, strict=False): ''' Trim the annotation and return as a new `Annotation` object. @@ -1077,15 +1078,18 @@ def to_interval_values(self): List view of value field. ''' - ints, vals = [], [] - for obs in self.data: - ints.append([obs.time, obs.time + obs.duration]) - vals.append(obs.value) + times, vals = self._combine_observations() + try: + durs = list(itertools.chain(*[obs.duration for obs in self.data])) + except TypeError: + durs = [obs.duration for obs in self.data] + + intervals = [(t, t+d) for t, d in zip(times, durs)] - if not ints: + if not len(intervals): return np.empty(shape=(0, 2), dtype=float), [] - return np.array(ints), vals + return np.array(intervals), vals def to_event_values(self): '''Extract observation data in a `mir_eval`-friendly format. @@ -1098,12 +1102,8 @@ def to_event_values(self): labels : list List view of value field. ''' - ints, vals = [], [] - for obs in self.data: - ints.append(obs.time) - vals.append(obs.value) - - return np.array(ints), vals + times, vals = self._combine_observations() + return np.array(times), vals def to_dataframe(self): '''Convert this annotation to a pandas dataframe. @@ -1288,19 +1288,7 @@ def __json_light__(self, data=True): @property def __json_data__(self): r"""JSON-serialize the observation sequence.""" - if schema.is_dense(self.namespace): - dense_records = dict() - for field in Observation._fields: - dense_records[field] = [] - - for obs in self.data: - for key, val in six.iteritems(obs._asdict()): - dense_records[key].append(serialize_obj(val)) - - return dense_records - - else: - return [serialize_obj(_) for _ in self.data] + return [serialize_obj(_) for _ in self.data] @classmethod def _key(cls, obs): @@ -1806,7 +1794,7 @@ def validate(self, strict=True): ''' valid = True try: - schema.VALIDATOR.validate(self.__json_light__, schema.JAMS_SCHEMA) + schema.VALIDATOR.validate(self.__json_light__, self.__schema__) for ann in self.annotations: if isinstance(ann, Annotation): @@ -2087,6 +2075,9 @@ def serialize_obj(obj): ''' + if isinstance(obj, np.bool_): + return bool(obj) + if isinstance(obj, np.integer): return int(obj) @@ -2094,11 +2085,14 @@ def serialize_obj(obj): return float(obj) elif isinstance(obj, np.ndarray): - return obj.tolist() + return [serialize_obj(x) for x in obj.tolist()] elif isinstance(obj, list): return [serialize_obj(x) for x in obj] + elif isinstance(obj, dict): + return {k: serialize_obj(v) for k, v in six.iteritems(obj)} + elif isinstance(obj, Observation): return {k: serialize_obj(v) for k, v in six.iteritems(obj._asdict())} @@ -2166,3 +2160,95 @@ def _get_divid(obj): global __DIVID_COUNT__ __DIVID_COUNT__ += 1 return '{}-{}'.format(id(obj), __DIVID_COUNT__) + + +def import_lab(namespace, filename, infer_duration=True, **parse_options): + r'''Load a .lab file as an Annotation object. + + .lab files are assumed to have the following format: + + ``TIME_START\tTIME_END\tANNOTATION`` + + By default, .lab files are assumed to have columns separated by one + or more white-space characters, and have no header or index column + information. + + If the .lab file contains only two columns, then an empty duration + field is inferred. + + If the .lab file contains more than three columns, each row's + annotation value is assigned the contents of last non-empty column. + + + Parameters + ---------- + namespace : str + The namespace for the new annotation + + filename : str + Path to the .lab file + + infer_duration : bool + If `True`, interval durations are inferred from `(start, end)` columns, + or difference between successive times. + + If `False`, interval durations are assumed to be explicitly coded as + `(start, duration)` columns. If only one time column is given, then + durations are set to 0. + + For instantaneous event annotations (e.g., beats or onsets), this + should be set to `False`. + + parse_options : additional keyword arguments + Passed to ``pandas.DataFrame.read_csv`` + + Returns + ------- + annotation : Annotation + The newly constructed annotation object + + See Also + -------- + pandas.DataFrame.read_csv + ''' + + # Create a new annotation object + annotation = Annotation(namespace) + + parse_options.setdefault('sep', r'\s+') + parse_options.setdefault('engine', 'python') + parse_options.setdefault('header', None) + parse_options.setdefault('index_col', False) + + # This is a hack to handle potentially ragged .lab data + parse_options.setdefault('names', range(20)) + + data = pd.read_csv(filename, **parse_options) + + # Drop all-nan columns + data = data.dropna(how='all', axis=1) + + # Do we need to add a duration column? + # This only applies to event annotations + if len(data.columns) == 2: + # Insert a column of zeros after the timing + data.insert(1, 'duration', 0) + if infer_duration: + data['duration'][:-1] = data.loc[:, 0].diff()[1:].values + + else: + # Convert from time to duration + if infer_duration: + data.loc[:, 1] -= data[0] + + for row in data.itertuples(): + time, duration = row[1:3] + + value = [x for x in row[3:] if x is not None][-1] + + annotation.append(time=time, + duration=duration, + confidence=1.0, + value=value) + + return annotation diff --git a/jams/nsconvert.py b/jams/nsconvert.py index 5a55b30..22fd3f1 100644 --- a/jams/nsconvert.py +++ b/jams/nsconvert.py @@ -145,11 +145,12 @@ def pitch_hz_to_contour(annotation): data = annotation.pop_data() for obs in data: - annotation.append(time=obs.time, duration=obs.duration, + annotation.append(time=obs.time, + duration=obs.duration, confidence=obs.confidence, - value=dict(index=0, - frequency=np.abs(obs.value), - voiced=obs.value > 0)) + value=[dict(index=0, + frequency=np.abs(v), + voiced=v > 0) for v in obs.value]) return annotation @@ -200,9 +201,10 @@ def pitch_midi_to_hz(annotation): data = annotation.pop_data() for obs in data: - annotation.append(time=obs.time, duration=obs.duration, + annotation.append(time=obs.time, + duration=obs.duration, confidence=obs.confidence, - value=440 * (2.0**((obs.value - 69.0)/12.0))) + value=[440 * (2.0**((v - 69.0)/12.0)) for v in obs.value]) return annotation @@ -218,7 +220,7 @@ def pitch_hz_to_midi(annotation): for obs in data: annotation.append(time=obs.time, duration=obs.duration, confidence=obs.confidence, - value=12 * (np.log2(obs.value) - np.log2(440.0)) + 69) + value=[12 * (np.log2(v) - np.log2(440.0)) + 69 for v in obs.value]) return annotation diff --git a/jams/schema.py b/jams/schema.py index 50d0a12..59d93fc 100644 --- a/jams/schema.py +++ b/jams/schema.py @@ -7,12 +7,9 @@ .. autosummary:: :toctree: generated/ - add_namespace - namespace - namespace_array - is_dense values get_dtypes + namespace list_namespaces ''' @@ -27,96 +24,9 @@ import jsonschema from .exceptions import NamespaceError, JamsError +from .util import find_with_extension -__all__ = ['add_namespace', 'namespace', 'is_dense', 'values', 'get_dtypes', 'VALIDATOR'] - -__NAMESPACE__ = dict() - - -def add_namespace(filename): - '''Add a namespace definition to our working set. - - Namespace files consist of partial JSON schemas defining the behavior - of the `value` and `confidence` fields of an Annotation. - - Parameters - ---------- - filename : str - Path to json file defining the namespace object - ''' - with open(filename, mode='r') as fileobj: - __NAMESPACE__.update(json.load(fileobj)) - - -def namespace(ns_key): - '''Construct a validation schema for a given namespace. - - Parameters - ---------- - ns_key : str - Namespace key identifier (eg, 'beat' or 'segment_tut') - - Returns - ------- - schema : dict - JSON schema of `namespace` - ''' - - if ns_key not in __NAMESPACE__: - raise NamespaceError('Unknown namespace: {:s}'.format(ns_key)) - - sch = copy.deepcopy(JAMS_SCHEMA['definitions']['SparseObservation']) - - for key in ['value', 'confidence']: - try: - sch['properties'][key] = __NAMESPACE__[ns_key][key] - except KeyError: - pass - - return sch - - -def namespace_array(ns_key): - '''Construct a validation schema for arrays of a given namespace. - - Parameters - ---------- - ns_key : str - Namespace key identifier - - Returns - ------- - schema : dict - JSON schema of `namespace` observation arrays - ''' - - obs_sch = namespace(ns_key) - obs_sch['title'] = 'Observation' - - sch = copy.deepcopy(JAMS_SCHEMA['definitions']['SparseObservationList']) - sch['items'] = obs_sch - return sch - - -def is_dense(ns_key): - '''Determine whether a namespace has dense formatting. - - Parameters - ---------- - ns_key : str - Namespace key identifier - - Returns - ------- - dense : bool - True if `ns_key` has a dense packing - False otherwise. - ''' - - if ns_key not in __NAMESPACE__: - raise NamespaceError('Unknown namespace: {:s}'.format(ns_key)) - - return __NAMESPACE__[ns_key]['dense'] +__all__ = ['values', 'get_dtypes', 'namespace', 'list_namespaces', 'VALIDATOR'] def values(ns_key): @@ -143,13 +53,13 @@ def values(ns_key): 'metal', 'pop', 'reggae', 'rock'] ''' - if ns_key not in __NAMESPACE__: + if ns_key not in NAMESPACES.keys(): raise NamespaceError('Unknown namespace: {:s}'.format(ns_key)) - if 'enum' not in __NAMESPACE__[ns_key]['value']: + if 'enum' not in NAMESPACES[ns_key]['definitions']['value']: raise NamespaceError('Namespace {:s} is not enumerated'.format(ns_key)) - return copy.copy(__NAMESPACE__[ns_key]['value']['enum']) + return copy.deepcopy(NAMESPACES[ns_key]['definitions']['value']['enum']) def get_dtypes(ns_key): @@ -168,23 +78,32 @@ def get_dtypes(ns_key): ''' # First, get the schema - if ns_key not in __NAMESPACE__: + if ns_key not in NAMESPACES.keys(): raise NamespaceError('Unknown namespace: {:s}'.format(ns_key)) - value_dtype = __get_dtype(__NAMESPACE__[ns_key].get('value', {})) - confidence_dtype = __get_dtype(__NAMESPACE__[ns_key].get('confidence', {})) + value_dtype = __get_dtype(NAMESPACES[ns_key]['definitions'].get('value', {})) + confidence_dtype = __get_dtype(NAMESPACES[ns_key]['definitions'].get('confidence', {})) return value_dtype, confidence_dtype +def namespace(ns_key): + '''Retrieve a schema for a namespace''' + try: + schema = NAMESPACES[ns_key] + except KeyError: + raise NamespaceError('No such namespace: {}'.format(ns_key)) + return schema + + def list_namespaces(): '''Print out a listing of available namespaces''' print('{:30s}\t{:40s}'.format('NAME', 'DESCRIPTION')) print('-' * 78) - for sch in sorted(__NAMESPACE__): - desc = __NAMESPACE__[sch]['description'] + for name, sch in sorted(NAMESPACES.items()): + desc = sch['description'] desc = (desc[:44] + '..') if len(desc) > 46 else desc - print('{:30s}\t{:40s}'.format(sch, desc)) + print('{:30s}\t{:40s}'.format(name, desc)) # Mapping of js primitives to numpy types @@ -229,24 +148,48 @@ def __get_dtype(typespec): return np.object_ -def __load_jams_schema(): +def __load_schema(schema_file): '''Load the schema file from the package.''' - schema_file = os.path.join(SCHEMA_DIR, 'jams_schema.json') + schema = None + with open(schema_file, mode='r') as fdesc: + schema = json.load(fdesc) + + if schema is None: + raise JamsError('Unable to load schema: {}'.format(schema_file)) + + return schema + - jams_schema = None - with open(resource_filename(__name__, schema_file), mode='r') as fdesc: - jams_schema = json.load(fdesc) +def __load_namespaces(): + '''Loads all schema stored in the namespace directory''' - if jams_schema is None: - raise JamsError('Unable to load JAMS schema') + namespaces = {} + top_schemas = [os.path.basename(next(iter(ns_file.values())))[:-1] for ns_file in JAMS_SCHEMA['definitions']['Annotation']['oneOf']] - return jams_schema + for ns in find_with_extension(NS_SCHEMA_DIR, 'json'): + if os.path.basename(ns) in top_schemas: + schema = __load_schema(ns) + namespaces[schema['definitions']['name']['const']] = schema + + return namespaces -# Populate the schemata -SCHEMA_DIR = 'schemata' +# Declare schema resources +SCHEMA_DIR = resource_filename(__name__, 'schemata') NS_SCHEMA_DIR = os.path.join(SCHEMA_DIR, 'namespaces') -JAMS_SCHEMA = __load_jams_schema() -VALIDATOR = jsonschema.Draft4Validator(JAMS_SCHEMA) +# Load all schema +JAMS_SCHEMA = __load_schema(os.path.join(SCHEMA_DIR, 'jams_schema.json')) +OBSERVATIONS_SCHEMA = __load_schema(os.path.join(SCHEMA_DIR, 'observations.json')) +NAMESPACES = __load_namespaces() + +# Construct validator +JAMS_RESOLVER = jsonschema.RefResolver( + base_uri = "file://" + os.path.abspath(os.path.join(SCHEMA_DIR, 'jams_schema.json')), + referrer = JAMS_SCHEMA + ) +VALIDATOR = jsonschema.Draft7Validator( + JAMS_SCHEMA, + resolver = JAMS_RESOLVER +) diff --git a/jams/schemata/jams_schema.json b/jams/schemata/jams_schema.json index 033d9cf..cd38c2d 100644 --- a/jams/schemata/jams_schema.json +++ b/jams/schemata/jams_schema.json @@ -51,40 +51,6 @@ } }, - "SparseObservation": { - "type": "object", - "title": "SparseObservation", - "description": "An observation that spans an interval of time", - "properties": { - "value": { }, - "confidence": { }, - "time": {"type": "number", "minimum": 0.0}, - "duration": {"type": "number", "minimum": 0.0} - }, - "required": ["value", "time", "duration", "confidence"] - }, - - "DenseObservation": { - "type": "object", - "title": "DenseObservation", - "description": "A dense series of observations", - "properties": { - "value": {"type": "array"}, - "confidence": {"type": "array" }, - "time": {"type": "array", "items": { "type": "number", "minimum": 0.0 }}, - "duration": {"type": "array", "items": { "type": "number", "minimum": 0.0 }} - }, - "required": ["value", "time", "duration", "confidence"] - }, - - "SparseObservationList": { - "type": "array", - "title": "Sparse Observation List", - "id": "#sparse-observation-list", - "description": "A list of sparse observation objects", - "items": { "$ref": "#/definitions/SparseObservation" } - }, - "Annotation": { "id": "#annotation", "type": "object", @@ -95,8 +61,11 @@ "data": { "title": "Data", "description": "An array of observations", - "oneOf": [ { "$ref": "#/definitions/DenseObservation" }, - { "$ref": "#/definitions/SparseObservationList" } ] + "type": "array", + "items": { + "oneOf": [ { "$ref": "observations.json#/definitions/DenseObservation" }, + { "$ref": "observations.json#/definitions/SparseObservation" } ] + } }, "namespace": {"type": "string"}, "sandbox": { "type": "object"}, @@ -109,7 +78,49 @@ {"type": "null"} ] } }, - "required": ["annotation_metadata", "data", "namespace"] + "required": ["annotation_metadata", "data", "namespace"], + "oneOf" : [ + { "$ref" : "namespaces/beat/beat.json#" }, + { "$ref" : "namespaces/beat/position.json#" }, + { "$ref" : "namespaces/chord/chord.json#" }, + { "$ref" : "namespaces/chord/harte.json#" }, + { "$ref" : "namespaces/chord/roman.json#" }, + { "$ref" : "namespaces/key/key_mode.json#" }, + { "$ref" : "namespaces/lyrics/bow.json#" }, + { "$ref" : "namespaces/lyrics/lyrics.json#" }, + { "$ref" : "namespaces/misc/blob.json#" }, + { "$ref" : "namespaces/misc/scaper.json#" }, + { "$ref" : "namespaces/misc/vector.json#" }, + { "$ref" : "namespaces/mood/thayer.json#" }, + { "$ref" : "namespaces/onset/onset.json#" }, + { "$ref" : "namespaces/pattern/jku.json#" }, + { "$ref" : "namespaces/pitch/class.json#" }, + { "$ref" : "namespaces/pitch/contour_hz.json#" }, + { "$ref" : "namespaces/pitch/hz.json#" }, + { "$ref" : "namespaces/pitch/midi.json#" }, + { "$ref" : "namespaces/pitch/note_hz.json#" }, + { "$ref" : "namespaces/pitch/note_midi.json#" }, + { "$ref" : "namespaces/segment/multi.json#" }, + { "$ref" : "namespaces/segment/open.json#" }, + { "$ref" : "namespaces/segment/salami_function.json#" }, + { "$ref" : "namespaces/segment/salami_lower.json#" }, + { "$ref" : "namespaces/segment/salami_upper.json#" }, + { "$ref" : "namespaces/segment/tut.json#" }, + { "$ref" : "namespaces/tag/cal10k.json#" }, + { "$ref" : "namespaces/tag/cal500.json#" }, + { "$ref" : "namespaces/tag/gtzan.json#" }, + { "$ref" : "namespaces/tag/medleydb_instruments.json#" }, + { "$ref" : "namespaces/tag/msd_tagtraum_cd1.json#" }, + { "$ref" : "namespaces/tag/msd_tagtraum_cd2.json#" }, + { "$ref" : "namespaces/tag/open.json#" }, + { "$ref" : "namespaces/tag/tag_audioset_genre.json#" }, + { "$ref" : "namespaces/tag/tag_audioset_instruments.json#" }, + { "$ref" : "namespaces/tag/tag_audioset.json#" }, + { "$ref" : "namespaces/tag/tag_fma_genre.json#" }, + { "$ref" : "namespaces/tag/tag_fma_subgenre.json#" }, + { "$ref" : "namespaces/tag/tag_urbansound.json#" }, + { "$ref" : "namespaces/tempo/tempo.json#" } + ] } }, diff --git a/jams/schemata/namespaces/beat/beat.json b/jams/schemata/namespaces/beat/beat.json index 1eea2c2..e9bd44e 100644 --- a/jams/schemata/namespaces/beat/beat.json +++ b/jams/schemata/namespaces/beat/beat.json @@ -1,15 +1,37 @@ -{"beat": { - "value": { - "oneOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] +{ + "definitions": { + "value": { + "oneOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "confidence": { + + }, + "name": { + "const": "beat" + } }, - "dense": false, - "description": "Beat event markers with optional metrical position" + + "description": "Beat event markers with optional metrical position", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/beat/position.json b/jams/schemata/namespaces/beat/position.json index 397e279..58e0450 100644 --- a/jams/schemata/namespaces/beat/position.json +++ b/jams/schemata/namespaces/beat/position.json @@ -1,16 +1,37 @@ -{"beat_position": { - "value": { - "type": "object", - "properties": { - "position": {"type": "number", "minimum": 1}, - "measure": {"type": "integer", "minimum": 0}, - "num_beats": { "type": "integer", "minimum": 1}, - "beat_units": { "enum": [1, 2, 4, 8, 16, 32, 64, 128, 256]} +{ + "definitions": { + "value": { + "type": "object", + "properties": { + "position": {"type": "number", "minimum": 1}, + "measure": {"type": "integer", "minimum": 0}, + "num_beats": { "type": "integer", "minimum": 1}, + "beat_units": { "enum": [1, 2, 4, 8, 16, 32, 64, 128, 256]} + }, + "required": ["position", "measure", "num_beats", "beat_units"] }, - "required": ["position", "measure", "num_beats", "beat_units"] + "confidence": { + + }, + "name": { + "const": "beat_position" + } }, - "dense": false, - "description": "Tuples of (position, measure, beats per measure, beat units)" - } -} + "description": "Tuples of (position, measure, beats per measure, beat units)", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } + } +} \ No newline at end of file diff --git a/jams/schemata/namespaces/chord/chord.json b/jams/schemata/namespaces/chord/chord.json index b04a904..44d81a5 100644 --- a/jams/schemata/namespaces/chord/chord.json +++ b/jams/schemata/namespaces/chord/chord.json @@ -1,10 +1,31 @@ -{"chord": - { +{ + "definitions": { "value": { "type": "string", "pattern": "^((N|X)|(([A-G](b*|#*))((:(maj|min|dim|aug|1|5|sus2|sus4|maj6|min6|7|maj7|min7|dim7|hdim7|minmaj7|aug7|9|maj9|min9|11|maj11|min11|13|maj13|min13)(\\((\\*?((b*|#*)([1-9]|1[0-3]?))(,\\*?((b*|#*)([1-9]|1[0-3]?)))*)\\))?)|(:\\((\\*?((b*|#*)([1-9]|1[0-3]?))(,\\*?((b*|#*)([1-9]|1[0-3]?)))*)\\)))?((/((b*|#*)([1-9]|1[0-3]?)))?)?))$" }, - "dense": false, - "description": "Expanded chord set. Includes: X, sus2, 1, 5, and 13" + "confidence": { + + }, + "name": { + "const": "chord" + } + }, + + "description": "Expanded chord set. Includes: X, sus2, 1, 5, and 13", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/chord/harte.json b/jams/schemata/namespaces/chord/harte.json index d46b54d..bffbcd8 100644 --- a/jams/schemata/namespaces/chord/harte.json +++ b/jams/schemata/namespaces/chord/harte.json @@ -1,10 +1,31 @@ -{"chord_harte": - { +{ + "definitions": { "value": { "type": "string", "pattern": "^((N)|(([A-G][b#]*)((:(maj|min|dim|aug|maj7|min7|7|dim7|hdim7|minmaj7|maj6|min6|9|maj9|min9|sus4)(\\((\\*?([b#]*([1-9]|1[0-3]?))(,\\*?([b#]*([1-9]|1[0-3]?)))*)\\))?)|(:\\((\\*?([b#]*([1-9]|1[0-3]?))(,\\*?([b#]*([1-9]|1[0-3]?)))*)\\)))?((/([b#]*([1-9]|1[0-3]?)))?)?))$" }, - "dense": false, - "description": "Chord annotations following Harte et al., 2005." + "confidence": { + + }, + "name": { + "const": "chord_harte" + } + }, + + "description": "Chord annotations following Harte et al., 2005.", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/chord/roman.json b/jams/schemata/namespaces/chord/roman.json index 60a9fca..2710b45 100644 --- a/jams/schemata/namespaces/chord/roman.json +++ b/jams/schemata/namespaces/chord/roman.json @@ -1,10 +1,10 @@ -{"chord_roman": - { +{ + "definitions": { "value": { "type": "object", "properties": { "tonic": { "type": "string", - "pattern": "^[A-G][b#]?$" }, + "pattern": "^[A-G][b#]?$" }, "chord": { "type": "string", "pattern": "^([b#]?(i|I|ii|II|iii|III|iv|IV|v|V|vi|VI|vii|VII))[osdhx+]?[0-9]?[0-9]?(/([b#]?(i|I|ii|II|iii|III|iv|IV|v|V|vi|VI|vii|VII)))?$" @@ -12,7 +12,28 @@ }, "required": ["tonic", "chord"] }, - "dense": false, - "description": "Roman numeral chords: (tonic, chord)" + "confidence": { + + }, + "name": { + "const": "chord_roman" + } + }, + + "description": "Roman numeral chords: (tonic, chord)", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/key/key_mode.json b/jams/schemata/namespaces/key/key_mode.json index 4d16356..d324352 100644 --- a/jams/schemata/namespaces/key/key_mode.json +++ b/jams/schemata/namespaces/key/key_mode.json @@ -1,11 +1,32 @@ -{"key_mode": - { - "value": { +{ + "definitions": { + "value": { "type": "string", "pattern": "^N|([A-G][b#]?)(:(major|minor|ionian|dorian|phrygian|lydian|mixolydian|aeolian|locrian))?$" }, - "dense": false, - "description": "Key and optional mode (major/minor or Greek modes)" + "confidence": { + + }, + "name": { + "const": "key_mode" + } + }, + + "description": "Key and optional mode (major/minor or Greek modes)", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/lyrics/bow.json b/jams/schemata/namespaces/lyrics/bow.json index 8d6c218..da18bb1 100644 --- a/jams/schemata/namespaces/lyrics/bow.json +++ b/jams/schemata/namespaces/lyrics/bow.json @@ -1,5 +1,5 @@ -{"lyrics_bow": - { +{ + "definitions": { "value": { "type": "array", "items": { @@ -15,7 +15,28 @@ ] } }, - "dense": false, - "description": "Bag of words or n-grams" + "confidence": { + + }, + "name": { + "const": "lyrics_bow" + } + }, + + "description": "Bag of words or n-grams", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/lyrics/lyrics.json b/jams/schemata/namespaces/lyrics/lyrics.json index 4904142..43b69be 100644 --- a/jams/schemata/namespaces/lyrics/lyrics.json +++ b/jams/schemata/namespaces/lyrics/lyrics.json @@ -1,7 +1,30 @@ -{"lyrics": - { - "value": { "type": "string" }, - "dense": false, - "description": "Open strings for lyrics annotations" +{ + "definitions": { + "value": { + "type": "string" + }, + "confidence": { + + }, + "name": { + "const": "lyrics" + } + }, + + "description": "Open strings for lyrics annotations", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/misc/blob.json b/jams/schemata/namespaces/misc/blob.json index 54f902d..707c6c6 100644 --- a/jams/schemata/namespaces/misc/blob.json +++ b/jams/schemata/namespaces/misc/blob.json @@ -1,6 +1,30 @@ -{"blob": - { - "dense": false, - "description": "Binary object (blob)" +{ + "definitions": { + "value": { + + }, + "confidence": { + + }, + "name": { + "const": "blob" + } + }, + + "description": "Binary object (blob)", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/misc/scaper.json b/jams/schemata/namespaces/misc/scaper.json index 7745bd5..51e8adc 100644 --- a/jams/schemata/namespaces/misc/scaper.json +++ b/jams/schemata/namespaces/misc/scaper.json @@ -1,38 +1,59 @@ -{"scaper": - { +{ + "definitions": { "value": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "source_file": { - "type": "string" - }, - "source_time": { - "type": "number", "minimum": 0 - }, - "event_time": { - "type": "number", "minimum": 0 - }, - "event_duration": { - "type": "number", "minimum": 0, "exclusiveMinimum": true - }, - "snr": { - "type": "number" - }, - "time_stretch": { - "type": ["number", "null"], "minimum": 0, "exclusiveMinimum": true - }, - "pitch_shift": { - "type": ["number", "null"] - }, - "role": { - "enum": ["background", "foreground"] + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "source_file": { + "type": "string" + }, + "source_time": { + "type": "number", "minimum": 0 + }, + "event_time": { + "type": "number", "minimum": 0 + }, + "event_duration": { + "type": "number", "exclusiveMinimum": 0 + }, + "snr": { + "type": "number" + }, + "time_stretch": { + "type": ["number", "null"], "exclusiveMinimum": 0 + }, + "pitch_shift": { + "type": ["number", "null"] + }, + "role": { + "enum": ["background", "foreground"] + } } - } }, - "dense": false, - "description": "Sound event following the scaper format." + "confidence": { + + }, + "name": { + "const": "scaper" + } + }, + + "description": "Sound event following the scaper format.", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } } \ No newline at end of file diff --git a/jams/schemata/namespaces/misc/vector.json b/jams/schemata/namespaces/misc/vector.json index cfec947..9835262 100644 --- a/jams/schemata/namespaces/misc/vector.json +++ b/jams/schemata/namespaces/misc/vector.json @@ -1,11 +1,32 @@ -{"vector": - { +{ + "definitions": { "value": { "type": "array", "items": {"type": "number"}, "minItems": 1 }, - "dense": false, - "description": "Numerical vector annotations" + "confidence": { + + }, + "name": { + "const": "vector" + } + }, + + "description": "Numerical vector annotations", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/mood/thayer.json b/jams/schemata/namespaces/mood/thayer.json index 992d4ee..94a6015 100644 --- a/jams/schemata/namespaces/mood/thayer.json +++ b/jams/schemata/namespaces/mood/thayer.json @@ -1,12 +1,33 @@ -{"mood_thayer": - { +{ + "definitions": { "value": { "type": "array", "items": {"type": "number"}, "minItems": 2, "maxItems": 2 }, - "dense": false, - "description": "Thayer mood model: (valence, arousal)" + "confidence": { + + }, + "name": { + "const": "mood_thayer" + } + }, + + "description": "Thayer mood model: (valence, arousal)", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/onset/onset.json b/jams/schemata/namespaces/onset/onset.json index c35d2dc..210d553 100644 --- a/jams/schemata/namespaces/onset/onset.json +++ b/jams/schemata/namespaces/onset/onset.json @@ -1,7 +1,30 @@ -{"onset": - { - "value": { }, - "dense": false, - "description": "Onset event markers" +{ + "definitions": { + "value": { + + }, + "confidence": { + + }, + "name": { + "const": "onset" + } + }, + + "description": "Onset event markers", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/pattern/jku.json b/jams/schemata/namespaces/pattern/jku.json index 1cfe777..c20e185 100644 --- a/jams/schemata/namespaces/pattern/jku.json +++ b/jams/schemata/namespaces/pattern/jku.json @@ -1,5 +1,5 @@ -{"pattern_jku": - { +{ + "definitions": { "value": { "type": "object", "properties": { @@ -17,7 +17,28 @@ }, "required": ["midi_pitch", "morph_pitch", "staff", "pattern_id", "occurrence_id"] }, - "dense": false, - "description": "Pattern (MIDI pitch), including staff height, voice number, occurrence id, and pattern id" + "confidence": { + + }, + "name": { + "const": "pattern_jku" + } + }, + + "description": "Pattern (MIDI pitch), including staff height, voice number, occurrence id, and pattern id", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/pitch/class.json b/jams/schemata/namespaces/pitch/class.json index 82bd127..b16abd6 100644 --- a/jams/schemata/namespaces/pitch/class.json +++ b/jams/schemata/namespaces/pitch/class.json @@ -1,6 +1,6 @@ -{"pitch_class": - { - "value": { +{ + "definitions": { + "value": { "type": "object", "properties": { "tonic": { "type": "string", "pattern": "^[A-G][b#]?$" }, @@ -8,8 +8,34 @@ }, "required": ["tonic", "pitch"] }, - "dense": true, - "description": "Pitch class in (tonic, pitch class) format" + "confidence": { + + }, + "name": { + "const": "pitch_class" + } + }, + + "description": "Pitch class in (tonic, pitch class) format", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of DenseObservation types", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation type in observations.json", + "items": { + "properties": { + "value": { + "type": "array", + "items": {"$ref": "#/definitions/value" } + }, + "confidence": { + "type": "array", + "items": {"$ref": "#/definitions/confidence" } + } + } + } + } } } - diff --git a/jams/schemata/namespaces/pitch/contour_hz.json b/jams/schemata/namespaces/pitch/contour_hz.json index 36dc9d4..c6e09ff 100644 --- a/jams/schemata/namespaces/pitch/contour_hz.json +++ b/jams/schemata/namespaces/pitch/contour_hz.json @@ -1,13 +1,41 @@ -{"pitch_contour": - { - "value": { "type": "object" }, - "dense": true, - "properties": { - "index": {"type": "integer"}, - "frequency": {"type": "number", "minimum": 0}, - "voiced": {"type": "boolean"} +{ + "definitions": { + "value": { + "type": "object", + "properties": { + "index": {"type": "integer"}, + "frequency": {"type": "number", "minimum": 0}, + "voiced": {"type": "boolean"} + } }, - "description": "Pitch contours: (index, frequency, voicing)" + "confidence": { + + }, + "name": { + "const": "pitch_contour" + } + }, + + "description": "Pitch contours: (index, frequency, voicing)", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of DenseObservation types", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation type in observations.json", + "items": { + "properties": { + "value": { + "type": "array", + "items": {"$ref": "#/definitions/value" } + }, + "confidence": { + "type": "array", + "items": {"$ref": "#/definitions/confidence" } + } + } + } + } } } - diff --git a/jams/schemata/namespaces/pitch/hz.json b/jams/schemata/namespaces/pitch/hz.json index 888537e..d27229d 100644 --- a/jams/schemata/namespaces/pitch/hz.json +++ b/jams/schemata/namespaces/pitch/hz.json @@ -1,8 +1,36 @@ -{"pitch_hz": - { - "value": { "type": "number" }, - "dense": true, - "description": "[DEPRECATED] Pitch in Hz" +{ + "definitions": { + "value": { + "type": "number" + }, + "confidence": { + + }, + "name": { + "const": "pitch_hz" + } + }, + + "description": "[DEPRECATED] Pitch in Hz", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of DenseObservation types", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation type in observations.json", + "items": { + "properties": { + "value": { + "type": "array", + "items": {"$ref": "#/definitions/value" } + }, + "confidence": { + "type": "array", + "items": {"$ref": "#/definitions/confidence" } + } + } + } + } } } - diff --git a/jams/schemata/namespaces/pitch/midi.json b/jams/schemata/namespaces/pitch/midi.json index 2092d80..716a5a3 100644 --- a/jams/schemata/namespaces/pitch/midi.json +++ b/jams/schemata/namespaces/pitch/midi.json @@ -1,8 +1,36 @@ -{"pitch_midi": - { - "value": { "type": "number" }, - "dense": true, - "description": "[DEPRECATED] Pitch in (fractional) MIDI note numbers" - } -} +{ + "definitions": { + "value": { + "type": "number" + }, + "confidence": { + + }, + "name": { + "const": "pitch_midi" + } + }, + "description": "[DEPRECATED] Pitch in (fractional) MIDI note numbers", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of DenseObservation types", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation type in observations.json", + "items": { + "properties": { + "value": { + "type": "array", + "items": {"$ref": "#/definitions/value" } + }, + "confidence": { + "type": "array", + "items": {"$ref": "#/definitions/confidence" } + } + } + } + } + } +} \ No newline at end of file diff --git a/jams/schemata/namespaces/pitch/note_hz.json b/jams/schemata/namespaces/pitch/note_hz.json index 14b3e6f..40fac77 100644 --- a/jams/schemata/namespaces/pitch/note_hz.json +++ b/jams/schemata/namespaces/pitch/note_hz.json @@ -1,8 +1,31 @@ -{"note_hz": - { - "value": { "type": "number", "minimum": 0}, - "dense": false, - "description": "Note pitches in Hz" - } -} +{ + "definitions": { + "value": { + "type": "number", + "minimum": 0 + }, + "confidence": { + + }, + "name": { + "const": "note_hz" + } + }, + "description": "Note pitches in Hz", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } + } +} \ No newline at end of file diff --git a/jams/schemata/namespaces/pitch/note_midi.json b/jams/schemata/namespaces/pitch/note_midi.json index adae5b2..70f3fd9 100644 --- a/jams/schemata/namespaces/pitch/note_midi.json +++ b/jams/schemata/namespaces/pitch/note_midi.json @@ -1,8 +1,30 @@ -{"note_midi": - { - "value": { "type": "number" }, - "dense": false, - "description": "Note pitches in (fractional) MIDI note numbers" - } -} +{ + "definitions": { + "value": { + "type": "number" + }, + "confidence": { + + }, + "name": { + "const": "note_midi" + } + }, + "description": "Note pitches in (fractional) MIDI note numbers", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } + } +} \ No newline at end of file diff --git a/jams/schemata/namespaces/segment/multi.json b/jams/schemata/namespaces/segment/multi.json index be663be..95a3c45 100644 --- a/jams/schemata/namespaces/segment/multi.json +++ b/jams/schemata/namespaces/segment/multi.json @@ -1,6 +1,6 @@ -{"multi_segment": - { - "value": { +{ + "definitions": { + "value": { "type": "object", "properties": { "label": {"type": "string" }, @@ -8,8 +8,28 @@ }, "required": ["label", "level"] }, - "dense": false, - "description": "Multi-level segmentation: (label, level)" - } -} + "confidence": { + + }, + "name": { + "const": "multi_segment" + } + }, + "description": "Multi-level segmentation: (label, level)", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } + } +} \ No newline at end of file diff --git a/jams/schemata/namespaces/segment/open.json b/jams/schemata/namespaces/segment/open.json index 294d907..e263019 100644 --- a/jams/schemata/namespaces/segment/open.json +++ b/jams/schemata/namespaces/segment/open.json @@ -1,8 +1,30 @@ -{"segment_open": - { - "value": { "type": "string" }, - "dense": false, - "description": "Open vocabulary segment labels" - } -} +{ + "definitions": { + "value": { + "type": "string" + }, + "confidence": { + + }, + "name": { + "const": "segment_open" + } + }, + "description": "Open vocabulary segment labels", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } + } +} \ No newline at end of file diff --git a/jams/schemata/namespaces/segment/salami_function.json b/jams/schemata/namespaces/segment/salami_function.json index 603e05e..fe1bbc8 100644 --- a/jams/schemata/namespaces/segment/salami_function.json +++ b/jams/schemata/namespaces/segment/salami_function.json @@ -1,6 +1,6 @@ -{"segment_salami_function": - { - "value": { +{ + "definitions": { + "value": { "enum": [ "applause", "backing", @@ -54,7 +54,28 @@ "voice_female" ] }, - "dense": false, - "description": "SALAMI functional label segmentation" + "confidence": { + + }, + "name": { + "const": "segment_salami_function" + } + }, + + "description": "SALAMI functional label segmentation", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/segment/salami_lower.json b/jams/schemata/namespaces/segment/salami_lower.json index b787861..000b18f 100644 --- a/jams/schemata/namespaces/segment/salami_lower.json +++ b/jams/schemata/namespaces/segment/salami_lower.json @@ -1,10 +1,31 @@ -{"segment_salami_lower": - { - "value": { +{ + "definitions": { + "value": { "type": "string", "pattern": "^[a-z][a-z]?'*$|^[Ss]ilence$" }, - "dense": false, - "description": "SALAMI lowercase segmentations" + "confidence": { + + }, + "name": { + "const": "segment_salami_lower" + } + }, + + "description": "SALAMI lowercase segmentations", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/segment/salami_upper.json b/jams/schemata/namespaces/segment/salami_upper.json index 94653aa..86a2373 100644 --- a/jams/schemata/namespaces/segment/salami_upper.json +++ b/jams/schemata/namespaces/segment/salami_upper.json @@ -1,10 +1,31 @@ -{"segment_salami_upper": - { - "value": { +{ + "definitions": { + "value": { "type": "string", "pattern": "^[A-Z]'*$|^[Ss]ilence$" }, - "dense": false, - "description": "SALAMI uppercase segmentations" + "confidence": { + + }, + "name": { + "const": "segment_salami_upper" + } + }, + + "description": "SALAMI uppercase segmentations", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/segment/tut.json b/jams/schemata/namespaces/segment/tut.json index 39fe4ad..89b5052 100644 --- a/jams/schemata/namespaces/segment/tut.json +++ b/jams/schemata/namespaces/segment/tut.json @@ -1,6 +1,6 @@ -{"segment_tut": - { - "value": { +{ + "definitions": { + "value": { "enum": [ "Break", "Bridge", @@ -74,8 +74,28 @@ "verseV" ] }, - "dense": false, - "description": "TUT Beatles segment labels" - } -} + "confidence": { + + }, + "name": { + "const": "segment_tut" + } + }, + "description": "TUT Beatles segment labels", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } + } +} \ No newline at end of file diff --git a/jams/schemata/namespaces/tag/cal10k.json b/jams/schemata/namespaces/tag/cal10k.json index 856e1f3..04c72b1 100644 --- a/jams/schemata/namespaces/tag/cal10k.json +++ b/jams/schemata/namespaces/tag/cal10k.json @@ -1,7 +1,5 @@ { - "tag_cal10k": { - "dense": false, - "description": "CAL10K tags", + "definitions": { "value": { "enum": [ "a ballad tempo", @@ -1058,6 +1056,29 @@ "wind section", "world music influences" ] + }, + "confidence": { + + }, + "name": { + "const": "tag_cal10k" + } + }, + + "description": "CAL10K tags", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } } } } \ No newline at end of file diff --git a/jams/schemata/namespaces/tag/cal500.json b/jams/schemata/namespaces/tag/cal500.json index 2563d69..1e48cd3 100644 --- a/jams/schemata/namespaces/tag/cal500.json +++ b/jams/schemata/namespaces/tag/cal500.json @@ -1,7 +1,5 @@ { - "tag_cal500": { - "dense": false, - "description": "CAL500 tags", + "definitions": { "value": { "enum": [ "Emotion-Angry_/_Aggressive", @@ -178,7 +176,30 @@ "Instrument_-_Piano-Solo", "Instrument_-_Saxophone-Solo", "Instrument_-_Trumpet-Solo" - ] + ] + }, + "confidence": { + + }, + "name": { + "const": "tag_cal500" + } + }, + + "description": "CAL500 tags", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/tag/gtzan.json b/jams/schemata/namespaces/tag/gtzan.json index 2964907..8f7b196 100644 --- a/jams/schemata/namespaces/tag/gtzan.json +++ b/jams/schemata/namespaces/tag/gtzan.json @@ -1,6 +1,6 @@ -{"tag_gtzan": - { - "value": { +{ + "definitions": { + "value": { "enum": [ "blues", "classical", @@ -14,7 +14,28 @@ "rock" ] }, - "dense": false, - "description": "GTZAN 10-class genre annotation" + "confidence": { + + }, + "name": { + "const": "tag_gtzan" + } + }, + + "description": "GTZAN 10-class genre annotation", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/tag/medleydb_instruments.json b/jams/schemata/namespaces/tag/medleydb_instruments.json index b3762d7..c2827d7 100644 --- a/jams/schemata/namespaces/tag/medleydb_instruments.json +++ b/jams/schemata/namespaces/tag/medleydb_instruments.json @@ -1,5 +1,5 @@ -{"tag_medleydb_instruments": - { +{ + "definitions": { "value": { "enum": [ "accordion", @@ -85,7 +85,28 @@ "zhongruan" ] }, - "dense": false, - "description": "MedleyDB instrument source annotations" + "confidence": { + + }, + "name": { + "const": "tag_medleydb_instruments" + } + }, + + "description": "MedleyDB instrument source annotations", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/tag/msd_tagtraum_cd1.json b/jams/schemata/namespaces/tag/msd_tagtraum_cd1.json index bf941ee..6f4615a 100644 --- a/jams/schemata/namespaces/tag/msd_tagtraum_cd1.json +++ b/jams/schemata/namespaces/tag/msd_tagtraum_cd1.json @@ -1,5 +1,5 @@ -{"tag_msd_tagtraum_cd1": - { +{ + "definitions": { "value": { "enum": [ "reggae", @@ -21,7 +21,25 @@ "oneOf": [ {"type": "number", "minimum": 0.0, "maximum": 1.0}, {"type": "null"} ] }, - "dense": false, - "description": "MSD tagtraum cd1 13-class genre annotation" + "name": { + "const": "tag_msd_tagtraum_cd1" + } + }, + + "description": "MSD tagtraum cd1 13-class genre annotation", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/tag/msd_tagtraum_cd2.json b/jams/schemata/namespaces/tag/msd_tagtraum_cd2.json index cb7bc7e..ef08182 100644 --- a/jams/schemata/namespaces/tag/msd_tagtraum_cd2.json +++ b/jams/schemata/namespaces/tag/msd_tagtraum_cd2.json @@ -1,5 +1,5 @@ -{"tag_msd_tagtraum_cd2": - { +{ + "definitions": { "value": { "enum": [ "reggae", @@ -23,7 +23,25 @@ "oneOf": [ {"type": "number", "minimum": 0.0, "maximum": 1.0}, {"type": "null"} ] }, - "dense": false, - "description": "MSD tagtraum cd2 15-class genre annotation" + "name": { + "const": "tag_msd_tagtraum_cd2" + } + }, + + "description": "MSD tagtraum cd2 15-class genre annotation", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/tag/open.json b/jams/schemata/namespaces/tag/open.json index 8d5e576..92b41d2 100644 --- a/jams/schemata/namespaces/tag/open.json +++ b/jams/schemata/namespaces/tag/open.json @@ -1,7 +1,30 @@ -{"tag_open": - { - "value": { "type": "string" }, - "dense": false, - "description": "Open tag vocabularies allow all strings" +{ + "definitions": { + "value": { + "type": "string" + }, + "confidence": { + + }, + "name": { + "const": "tag_open" + } + }, + + "description": "Open tag vocabularies allow all strings", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/tag/tag_audioset.json b/jams/schemata/namespaces/tag/tag_audioset.json index 704f995..274220a 100644 --- a/jams/schemata/namespaces/tag/tag_audioset.json +++ b/jams/schemata/namespaces/tag/tag_audioset.json @@ -1,7 +1,5 @@ { - "tag_audioset": { - "description": "AudioSet categories", - "dense": false, + "definitions": { "value": { "enum": [ "A capella", @@ -637,6 +635,29 @@ "Zipper (clothing)", "Zither" ] + }, + "confidence": { + + }, + "name": { + "const": "tag_audioset" + } + }, + + "description": "AudioSet categories", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } } } } \ No newline at end of file diff --git a/jams/schemata/namespaces/tag/tag_audioset_genre.json b/jams/schemata/namespaces/tag/tag_audioset_genre.json index 152e362..3755c50 100644 --- a/jams/schemata/namespaces/tag/tag_audioset_genre.json +++ b/jams/schemata/namespaces/tag/tag_audioset_genre.json @@ -1,6 +1,5 @@ { - "tag_audioset_genre": { - "description": "AudioSet musical genres", + "definitions": { "value": { "enum": [ "A capella", @@ -70,6 +69,28 @@ "Vocal music" ] }, - "dense": false + "confidence": { + + }, + "name": { + "const": "tag_audioset_genre" + } + }, + + "description": "AudioSet musical genres", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/tag/tag_audioset_instruments.json b/jams/schemata/namespaces/tag/tag_audioset_instruments.json index d643db5..df37758 100644 --- a/jams/schemata/namespaces/tag/tag_audioset_instruments.json +++ b/jams/schemata/namespaces/tag/tag_audioset_instruments.json @@ -1,6 +1,5 @@ { - "tag_audioset_instruments": { - "dense": false, + "definitions": { "value": { "enum": [ "Accordion", @@ -96,6 +95,28 @@ "Zither" ] }, - "description": "AudioSet musical instruments" + "confidence": { + + }, + "name": { + "const": "tag_audioset_instruments" + } + }, + + "description": "AudioSet musical instruments", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/tag/tag_fma_genre.json b/jams/schemata/namespaces/tag/tag_fma_genre.json index e6e058e..19acfba 100644 --- a/jams/schemata/namespaces/tag/tag_fma_genre.json +++ b/jams/schemata/namespaces/tag/tag_fma_genre.json @@ -1,6 +1,5 @@ { - "tag_fma_genre": { - "description": "Free Music Archive genres", + "definitions": { "value": { "enum": [ "Blues", @@ -21,6 +20,28 @@ "Spoken" ] }, - "dense": false + "confidence": { + + }, + "name": { + "const": "tag_fma_genre" + } + }, + + "description": "Free Music Archive genres", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/tag/tag_fma_subgenre.json b/jams/schemata/namespaces/tag/tag_fma_subgenre.json index 8508ca1..58c6930 100644 --- a/jams/schemata/namespaces/tag/tag_fma_subgenre.json +++ b/jams/schemata/namespaces/tag/tag_fma_subgenre.json @@ -1,6 +1,5 @@ { - "tag_fma_subgenre": { - "description": "Free Music Archive genres and sub-genres", + "definitions": { "value": { "enum": [ "20th Century Classical", @@ -168,6 +167,28 @@ "Wonky" ] }, - "dense": false + "confidence": { + + }, + "name": { + "const": "tag_fma_subgenre" + } + }, + + "description": "Free Music Archive genres and sub-genres", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/namespaces/tag/tag_urbansound.json b/jams/schemata/namespaces/tag/tag_urbansound.json index bffed10..9435002 100644 --- a/jams/schemata/namespaces/tag/tag_urbansound.json +++ b/jams/schemata/namespaces/tag/tag_urbansound.json @@ -1,6 +1,5 @@ { - "tag_urbansound": { - "description": "Urban sound classes as per UrbanSound, UrbanSound8K and URBAN-SED datasets", + "definitions": { "value": { "enum": [ "air_conditioner", @@ -15,6 +14,28 @@ "street_music" ] }, - "dense": false + "confidence": { + + }, + "name": { + "const": "tag_urbansound" + } + }, + + "description": "Urban sound classes as per UrbanSound, UrbanSound8K and URBAN-SED datasets", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } } \ No newline at end of file diff --git a/jams/schemata/namespaces/tempo/tempo.json b/jams/schemata/namespaces/tempo/tempo.json index bc48053..4beeeba 100644 --- a/jams/schemata/namespaces/tempo/tempo.json +++ b/jams/schemata/namespaces/tempo/tempo.json @@ -1,5 +1,5 @@ -{"tempo": - { +{ + "definitions": { "value": { "type": "number", "minimum": 0 @@ -9,7 +9,25 @@ "minimum": 0, "maximum": 1.0 }, - "dense": false, - "description": "Tempo measurements, in beats per minute (BPM)" + "name": { + "const": "tempo" + } + }, + + "description": "Tempo measurements, in beats per minute (BPM)", + + "properties": { + "namespace": { "$ref": "#/definitions/name" }, + "data": { + "type": "array", + "description": "A list of sparse observation objects", + "$comment": "Because this needs to reference namespace dependent types, oneOf relationships cannot be indexed, and it must be matched to the namespace name constant, we must redefine the observation type here to match an observation in observations.json", + "items": { + "properties": { + "value": { "$ref": "#/definitions/value" }, + "confidence": { "$ref": "#/definitions/confidence" } + } + } + } } -} +} \ No newline at end of file diff --git a/jams/schemata/observations.json b/jams/schemata/observations.json new file mode 100644 index 0000000..6c1cb51 --- /dev/null +++ b/jams/schemata/observations.json @@ -0,0 +1,29 @@ +{ + "definitions": { + "SparseObservation": { + "type": "object", + "title": "SparseObservation", + "description": "An observation that spans an interval of time", + "properties": { + "value": { }, + "confidence": { }, + "time": {"type": "number", "minimum": 0.0}, + "duration": {"type": "number", "minimum": 0.0} + }, + "required": ["value", "time", "duration", "confidence"] + }, + + "DenseObservation": { + "type": "object", + "title": "DenseObservation", + "description": "A dense series of observations", + "properties": { + "value": {"type": "array"}, + "confidence": {"type": "array"}, + "time": {"type": "array", "items": { "type": "number", "minimum": 0.0 }}, + "duration": {"type": "array", "items": { "type": "number", "minimum": 0.0 }} + }, + "required": ["value", "time", "duration", "confidence"] + } + } +} \ No newline at end of file diff --git a/jams/schemata/validate.py b/jams/schemata/validate.py index 8230869..15ba6a7 100755 --- a/jams/schemata/validate.py +++ b/jams/schemata/validate.py @@ -33,10 +33,19 @@ def validate(schema_file=None, jams_files=None): schema = load_json(schema_file) + base_uri = "file://" + os.path.abspath(schema_file) + + schema = load_json(os.path.abspath(rel_uri)) + + resolver = jsonschema.RefResolver( + base_uri = base_uri, + referrer = schema + ) + for jams_file in jams_files: try: jams = load_json(jams_file) - jsonschema.validate(jams, schema) + jsonschema.validate(jams, schema, resolver=resolver) print '{:s} was successfully validated'.format(jams_file) except jsonschema.ValidationError as exc: print '{:s} was NOT successfully validated'.format(jams_file) diff --git a/jams/sonify.py b/jams/sonify.py index 3491957..ee8ed4e 100644 --- a/jams/sonify.py +++ b/jams/sonify.py @@ -133,9 +133,9 @@ def pitch_contour(annotation, sr=22050, length=None, **kwargs): freqs = defaultdict(list) for obs in annotation: - times[obs.value['index']].append(obs.time) - freqs[obs.value['index']].append(obs.value['frequency'] * - (-1)**(~obs.value['voiced'])) + for t, v in zip(obs.time, obs.value): + times[v['index']].append(t) + freqs[v['index']].append(v['frequency'] * (-1)**(~v['voiced'])) y_out = 0.0 for ix in times: diff --git a/jams/util.py b/jams/util.py index 483809f..e3baaeb 100644 --- a/jams/util.py +++ b/jams/util.py @@ -7,7 +7,6 @@ .. autosummary:: :toctree: generated/ - import_lab expand_filepaths smkdirs filebase @@ -18,100 +17,6 @@ import glob import pandas as pd -from . import core - - -def import_lab(namespace, filename, infer_duration=True, **parse_options): - r'''Load a .lab file as an Annotation object. - - .lab files are assumed to have the following format: - - ``TIME_START\tTIME_END\tANNOTATION`` - - By default, .lab files are assumed to have columns separated by one - or more white-space characters, and have no header or index column - information. - - If the .lab file contains only two columns, then an empty duration - field is inferred. - - If the .lab file contains more than three columns, each row's - annotation value is assigned the contents of last non-empty column. - - - Parameters - ---------- - namespace : str - The namespace for the new annotation - - filename : str - Path to the .lab file - - infer_duration : bool - If `True`, interval durations are inferred from `(start, end)` columns, - or difference between successive times. - - If `False`, interval durations are assumed to be explicitly coded as - `(start, duration)` columns. If only one time column is given, then - durations are set to 0. - - For instantaneous event annotations (e.g., beats or onsets), this - should be set to `False`. - - parse_options : additional keyword arguments - Passed to ``pandas.DataFrame.read_csv`` - - Returns - ------- - annotation : Annotation - The newly constructed annotation object - - See Also - -------- - pandas.DataFrame.read_csv - ''' - - # Create a new annotation object - annotation = core.Annotation(namespace) - - parse_options.setdefault('sep', r'\s+') - parse_options.setdefault('engine', 'python') - parse_options.setdefault('header', None) - parse_options.setdefault('index_col', False) - - # This is a hack to handle potentially ragged .lab data - parse_options.setdefault('names', range(20)) - - data = pd.read_csv(filename, **parse_options) - - # Drop all-nan columns - data = data.dropna(how='all', axis=1) - - # Do we need to add a duration column? - # This only applies to event annotations - if len(data.columns) == 2: - # Insert a column of zeros after the timing - data.insert(1, 'duration', 0) - if infer_duration: - data['duration'][:-1] = data.loc[:, 0].diff()[1:].values - - else: - # Convert from time to duration - if infer_duration: - data.loc[:, 1] -= data[0] - - for row in data.itertuples(): - time, duration = row[1:3] - - value = [x for x in row[3:] if x is not None][-1] - - annotation.append(time=time, - duration=duration, - confidence=1.0, - value=value) - - return annotation - def expand_filepaths(base_dir, rel_paths): """Expand a list of relative paths to a give base directory. diff --git a/jams/version.py b/jams/version.py index b832128..47370f7 100644 --- a/jams/version.py +++ b/jams/version.py @@ -2,5 +2,5 @@ # -*- coding: utf-8 -*- """Version info""" -short_version = '0.3' -version = '0.3.4' +short_version = '0.4' +version = '0.4.0' diff --git a/tests/fixtures/transcription_est.jams b/tests/fixtures/transcription_est.jams index 29bf953..f037d14 100644 --- a/tests/fixtures/transcription_est.jams +++ b/tests/fixtures/transcription_est.jams @@ -19,36 +19,38 @@ "validation": "", "data_source": "Manually generated for test purposes" }, - "data": { - "duration": [ - 0.17, - 0.05, - 0.1, - 0.05, - 0.09 - ], - "confidence": [ - 1.0, - 1.0, - 1.0, - 1.0, - 1.0 - ], - "value": [ - 225.0, - 246.94200000000001, - 500.0, - 293.66500000000002, - 293.66500000000002 - ], - "time": [ - 0.12, - 0.3, - 0.5, - 0.55, - 0.56 - ] - } + "data": [ + { + "duration": [ + 0.17, + 0.05, + 0.1, + 0.05, + 0.09 + ], + "confidence": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0 + ], + "value": [ + 225.0, + 246.94200000000001, + 500.0, + 293.66500000000002, + 293.66500000000002 + ], + "time": [ + 0.12, + 0.3, + 0.5, + 0.55, + 0.56 + ] + } + ] } ], "file_metadata": { diff --git a/tests/fixtures/transcription_ref.jams b/tests/fixtures/transcription_ref.jams index 13001b7..c00528f 100644 --- a/tests/fixtures/transcription_ref.jams +++ b/tests/fixtures/transcription_ref.jams @@ -19,32 +19,34 @@ "validation": "", "data_source": "Manually generated for test purposes" }, - "data": { - "duration": [ - 0.2, - 0.1, - 0.1, - 0.1 - ], - "confidence": [ - 1.0, - 1.0, - 1.0, - 1.0 - ], - "value": [ - 220.0, - 246.94200000000001, - 277.18299999999999, - 293.66500000000002 - ], - "time": [ - 0.1, - 0.3, - 0.5, - 0.55 - ] - } + "data": [ + { + "duration": [ + 0.2, + 0.1, + 0.1, + 0.1 + ], + "confidence": [ + 1.0, + 1.0, + 1.0, + 1.0 + ], + "value": [ + 220.0, + 246.94200000000001, + 277.18299999999999, + 293.66500000000002 + ], + "time": [ + 0.1, + 0.3, + 0.5, + 0.55 + ] + } + ] } ], "file_metadata": { diff --git a/tests/test_convert.py b/tests/test_convert.py index adf0e13..0ef231c 100644 --- a/tests/test_convert.py +++ b/tests/test_convert.py @@ -28,7 +28,7 @@ def test_bad_sources(target): jams.convert(ann, target) -@pytest.mark.parametrize('namespace', list(jams.schema.__NAMESPACE__.keys())) +@pytest.mark.parametrize('namespace', list(jams.schema.NAMESPACES.keys())) def test_noop(namespace): ann = jams.Annotation(namespace=namespace) @@ -45,8 +45,7 @@ def test_pitch_hz_to_contour(): times = np.linspace(0, 1, num=len(values)) - for t, v in zip(times, values): - ann.append(time=t, value=v, duration=0) + ann.append(time=times, value=values, duration=[0]*len(values)) ann2 = jams.convert(ann, 'pitch_contour') ann.validate() @@ -54,16 +53,16 @@ def test_pitch_hz_to_contour(): assert ann2.namespace == 'pitch_contour' # Check index values - assert ann2.data[0].value['index'] == 0 - assert ann2.data[-1].value['index'] == 0 + assert ann2.data[0].value[0]['index'] == 0 + assert ann2.data[0].value[-1]['index'] == 0 # Check frequency - assert np.abs(ann2.data[0].value['frequency'] == np.abs(values[0])) - assert np.abs(ann2.data[-1].value['frequency'] == np.abs(values[-1])) + assert np.abs(ann2.data[0].value[0]['frequency'] == np.abs(values[0])) + assert np.abs(ann2.data[0].value[-1]['frequency'] == np.abs(values[-1])) # Check voicings - assert not ann2.data[0].value['voiced'] - assert ann2.data[-1].value['voiced'] + assert not ann2.data[0].value[0]['voiced'] + assert ann2.data[0].value[-1]['voiced'] def test_pitch_midi_to_contour(): @@ -73,8 +72,7 @@ def test_pitch_midi_to_contour(): times = np.linspace(0, 1, num=len(values)) - for t, v in zip(times, values): - ann.append(time=t, value=v, duration=0) + ann.append(time=times, value=values, duration=[0]*len(times)) ann2 = jams.convert(ann, 'pitch_contour') ann.validate() @@ -82,17 +80,17 @@ def test_pitch_midi_to_contour(): assert ann2.namespace == 'pitch_contour' # Check index values - assert ann2.data[0].value['index'] == 0 - assert ann2.data[-1].value['index'] == 0 + assert ann2.data[0].value[0]['index'] == 0 + assert ann2.data[0].value[-1]['index'] == 0 # Check voicings - assert ann2.data[-1].value['voiced'] + assert ann2.data[0].value[-1]['voiced'] def test_pitch_midi_to_hz(): ann = jams.Annotation(namespace='pitch_midi') - ann.append(time=0, duration=1, value=69, confidence=0.5) + ann.append(time=[0], duration=[1], value=[69], confidence=[0.5]) ann2 = jams.convert(ann, 'pitch_hz') ann.validate() ann2.validate() @@ -100,7 +98,7 @@ def test_pitch_midi_to_hz(): # Check the namespace assert ann2.namespace == 'pitch_hz' # midi 69 = 440.0 Hz - assert ann2.data[0].value == 440.0 + assert ann2.data[0].value[0] == 440.0 # Check all else is equal assert len(ann.data) == len(ann2.data) @@ -114,7 +112,7 @@ def test_pitch_midi_to_hz(): def test_pitch_hz_to_midi(): ann = jams.Annotation(namespace='pitch_hz') - ann.append(time=0, duration=1, value=440.0, confidence=0.5) + ann.append(time=[0], duration=[1], value=[440.0], confidence=[0.5]) ann2 = jams.convert(ann, 'pitch_midi') ann.validate() ann2.validate() @@ -122,7 +120,7 @@ def test_pitch_hz_to_midi(): # Check the namespace assert ann2.namespace == 'pitch_midi' # midi 69 = 440.0 Hz - assert ann2.data[0].value == 69 + assert ann2.data[0].value[0] == 69 # Check all else is equal assert len(ann.data) == len(ann2.data) diff --git a/tests/test_display.py b/tests/test_display.py index fcbfd8d..8670fec 100644 --- a/tests/test_display.py +++ b/tests/test_display.py @@ -50,8 +50,7 @@ def test_display_pitch_contour(): values = np.arange(100, 200) times = np.linspace(0, 2, num=len(values)) - for t, v in zip(times, values): - ann.append(time=t, value=v, duration=0) + ann.append(time=times, value=values, duration=[0]*len(times)) jams.display.display(ann) diff --git a/tests/test_eval.py b/tests/test_eval.py index 1542f28..49b9861 100644 --- a/tests/test_eval.py +++ b/tests/test_eval.py @@ -23,8 +23,12 @@ def create_annotation(values, namespace='beat', offset=0.0, duration=1, if np.isscalar(confidence): confidence = [confidence] * len(time) - for t, d, v, c in zip(time, duration, values, confidence): - ann.append(time=t, duration=d, value=v, confidence=c) + # The pitch_hz namespace considers all values to be one observation + if namespace=='pitch_hz': + ann.append(time=time, duration=duration, value=values, confidence=confidence) + else: + for t, d, v, c in zip(time, duration, values, confidence): + ann.append(time=t, duration=d, value=v, confidence=c) return ann @@ -213,7 +217,7 @@ def est_transcript(): def est_badtranscript(): est_jam = jams.load('tests/fixtures/transcription_est.jams', validate=False) ann = est_jam.annotations['pitch_hz', 0] - ann.append(time=2., duration=1., value=None, confidence=1) + ann.append(time=[2.], duration=[1.], value=[None], confidence=[1]) return ann diff --git a/tests/test_jams.py b/tests/test_jams.py index 3f952c8..1ec9d16 100644 --- a/tests/test_jams.py +++ b/tests/test_jams.py @@ -1236,3 +1236,36 @@ def test_annotation_to_samples_fail_shape(): values = ann.to_samples([[0.2, 0.4, 0.75, 1.25, 1.75, 1.4]]) + +@pytest.mark.parametrize('ns, lab, ints, y, infer_duration', + [('beat', + "1.0 1\n3.0 2", + np.array([[1.0, 3.0], [3.0, 3.0]]), + [1, 2], + True), + ('beat', + "1.0 1\n3.0 2", + np.array([[1.0, 1.0], [3.0, 3.0]]), + [1, 2], + False), + ('chord_harte', + "1.0 2.0 a\n2.0 4.0 b", + np.array([[1.0, 2.0], [2.0, 4.0]]), + ['a', 'b'], + True), + ('chord', + "1.0 1.0 c\n2.0 2.0 d", + np.array([[1.0, 2.0], [2.0, 4.0]]), + ['c', 'd'], + False)]) +def test_import_lab(ns, lab, ints, y, infer_duration): + ann = jams.core.import_lab(ns, six.StringIO(lab), + infer_duration=infer_duration) + + assert len(ints) == len(ann.data) + assert len(y) == len(ann.data) + + for yi, ival, obs in zip(y, ints, ann): + assert obs.time == ival[0] + assert obs.duration == ival[1] - ival[0] + assert obs.value == yi diff --git a/tests/test_ns.py b/tests/test_ns.py index 49f7c96..3f15374 100644 --- a/tests/test_ns.py +++ b/tests/test_ns.py @@ -212,8 +212,7 @@ def test_ns_pitch_hz_valid(): confidences = np.linspace(0, 1., seq_len) confidences[seq_len//2] = None # throw in a None confidence value - for (t, d, v, c) in zip(times, durations, values, confidences): - ann.append(time=t, duration=d, value=v, confidence=c) + ann.append(time=times, duration=durations, value=values, confidence=confidences) ann.validate() @@ -223,7 +222,7 @@ def test_ns_pitch_hz_valid(): def test_ns_pitch_hz_invalid(value): ann = Annotation(namespace='pitch_hz') - ann.append(time=0, duration=0, value=value, confidence=0.5) + ann.append(time=[0], duration=[0], value=[value], confidence=[0.5]) ann.validate() @@ -264,8 +263,7 @@ def test_ns_pitch_midi_valid(): confidences = np.linspace(0, 1., seq_len) confidences[seq_len//2] = None # throw in a None confidence value - for (t, d, v, c) in zip(times, durations, values, confidences): - ann.append(time=t, duration=d, value=v, confidence=c) + ann.append(time=times, duration=durations, value=values, confidence=confidences) ann.validate() @@ -275,7 +273,7 @@ def test_ns_pitch_midi_valid(): def test_ns_pitch_midi_invalid(value): ann = Annotation(namespace='pitch_midi') - ann.append(time=0, duration=0, value=value, confidence=0.5) + ann.append(time=[0], duration=[0], value=[value], confidence=[0.5]) ann.validate() @@ -292,17 +290,17 @@ def test_ns_contour_valid(): ids = np.arange(len(values)) // 4 voicing = np.random.randn(len(ids)) > 0 - confidences = np.linspace(0, 1., seq_len) + confidences = np.linspace(0, 1., seq_len).tolist() confidences[seq_len//2] = None # throw in a None confidence value - for (t, d, v, c, i, b) in zip(times, durations, values, - confidences, ids, voicing): - ann.append(time=t, duration=d, - value={'pitch': v, 'id': i, 'voiced': b}, confidence=c) + values = [{'frequency': v, 'index': i, 'voiced': b} for v, i, b in zip(values, ids, voicing)] - ann.validate() + ann.append(time=times, duration=durations, + value=values, confidence=confidences) + ann.validate() +@xfail(raises=SchemaError) def test_ns_contour_invalid(): srand() @@ -319,10 +317,10 @@ def test_ns_contour_invalid(): confidences = np.linspace(0, 1., seq_len) confidences[seq_len//2] = None # throw in a None confidence value - for (t, d, v, c, i, b) in zip(times, durations, values, - confidences, ids, voicing): - ann.append(time=t, duration=d, - value={'pitch': v, 'id': i, 'voiced': b}, confidence=c) + values = [{'frequency': v, 'index': i, 'voiced': b} for v, i, b in zip(values, ids, voicing)] + + ann.append(time=times, duration=durations, + value=values, confidence=confidences) ann.validate() @@ -435,7 +433,7 @@ def test_ns_chord_roman_missing(key): def test_ns_pitch_class_valid(value): ann = Annotation(namespace='pitch_class') - ann.append(time=0, duration=1.0, value=value) + ann.append(time=[0], duration=[1.0], value=[value]) ann.validate() @@ -452,7 +450,7 @@ def test_ns_pitch_class_invalid(key, value): data = dict(tonic='E', pitch=7) data[key] = value ann = Annotation(namespace='pitch_class') - ann.append(time=0, duration=1.0, value=data) + ann.append(time=[0], duration=[1.0], value=[data]) ann.validate() @@ -462,7 +460,7 @@ def test_ns_pitch_class_missing(key): data = dict(tonic='E', pitch=7) del data[key] ann = Annotation(namespace='pitch_class') - ann.append(time=0, duration=1.0, value=data) + ann.append(time=[0], duration=[1.0], value=[data]) ann.validate() diff --git a/tests/test_schema.py b/tests/test_schema.py index c77996e..a1e591e 100644 --- a/tests/test_schema.py +++ b/tests/test_schema.py @@ -18,57 +18,15 @@ def test_schema_namespace(ns_key): # Get the schema schema = jams.schema.namespace(ns_key) + obs_schema = jams.schema.OBSERVATIONS_SCHEMA["definitions"] - # Make sure it has the correct properties - valid_keys = set(['time', 'duration', 'value', 'confidence']) - for key in schema['properties']: - assert key in valid_keys + # Check that its fields match one of the observation types + matched = False + for _, obs in obs_schema.items(): + obs_properties = obs['properties'] + matched |= all( key in obs_properties for key in schema['properties']['data']['items']['properties'].keys() ) - for key in ['time', 'duration']: - assert key in schema['properties'] - - -@pytest.mark.parametrize('ns, dense', - [('pitch_hz', True), - ('beat', False), - pytest.mark.xfail(('DNE', False), - raises=NamespaceError)]) -def test_schema_is_dense(ns, dense): - assert dense == jams.schema.is_dense(ns) - - -@pytest.fixture -def local_namespace(): - - os.environ['JAMS_SCHEMA_DIR'] = os.path.join('tests', 'fixtures', 'schema') - reload_module(jams) - - # This one should pass - yield 'testing_tag_upper', True - - # Cleanup - del os.environ['JAMS_SCHEMA_DIR'] - reload_module(jams) - - -def test_schema_local(local_namespace): - - ns_key, exists = local_namespace - - # Get the schema - if exists: - schema = jams.schema.namespace(ns_key) - - # Make sure it has the correct properties - valid_keys = set(['time', 'duration', 'value', 'confidence']) - for key in schema['properties']: - assert key in valid_keys - - for key in ['time', 'duration']: - assert key in schema['properties'] - else: - with pytest.raises(NamespaceError): - schema = jams.schema.namespace(ns_key) + assert matched def test_schema_values_pass(): @@ -92,7 +50,7 @@ def test_schema_values_notenum(): def test_schema_dtypes(): - for n in jams.schema.__NAMESPACE__: + for n, _ in jams.schema.NAMESPACES.items(): jams.schema.get_dtypes(n) diff --git a/tests/test_sonify.py b/tests/test_sonify.py index 56a7a4f..22e0d9a 100644 --- a/tests/test_sonify.py +++ b/tests/test_sonify.py @@ -74,10 +74,12 @@ def ann_contour(): rate = 5 vibrato = 220 + 20 * np.sin(2 * np.pi * times * rate) - for t, v in zip(times, vibrato): - ann.append(time=t, duration=fs, value={'frequency': v, - 'index': 0, - 'voiced': (t < 3 or t > 4)}) + values = [{'frequency': v, 'index': 0, 'voiced': (t < 3 or t > 4)} for t, v in zip(times, vibrato)] + ann.append( + time=times, + duration=[fs]*len(times), + value=values + ) return ann diff --git a/tests/test_util.py b/tests/test_util.py index 7d47b88..520ea3b 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -18,40 +18,6 @@ def srand(seed=628318530): pass -@pytest.mark.parametrize('ns, lab, ints, y, infer_duration', - [('beat', - "1.0 1\n3.0 2", - np.array([[1.0, 3.0], [3.0, 3.0]]), - [1, 2], - True), - ('beat', - "1.0 1\n3.0 2", - np.array([[1.0, 1.0], [3.0, 3.0]]), - [1, 2], - False), - ('chord_harte', - "1.0 2.0 a\n2.0 4.0 b", - np.array([[1.0, 2.0], [2.0, 4.0]]), - ['a', 'b'], - True), - ('chord', - "1.0 1.0 c\n2.0 2.0 d", - np.array([[1.0, 2.0], [2.0, 4.0]]), - ['c', 'd'], - False)]) -def test_import_lab(ns, lab, ints, y, infer_duration): - ann = util.import_lab(ns, six.StringIO(lab), - infer_duration=infer_duration) - - assert len(ints) == len(ann.data) - assert len(y) == len(ann.data) - - for yi, ival, obs in zip(y, ints, ann): - assert obs.time == ival[0] - assert obs.duration == ival[1] - ival[0] - assert obs.value == yi - - @pytest.mark.parametrize('query, prefix, sep, target', [('al.beta.gamma', 'al', '.', 'beta.gamma'), ('al/beta/gamma', 'al', '/', 'beta/gamma'),