diff --git a/sigmf/sigmffile.py b/sigmf/sigmffile.py index 1203c53..b936fff 100644 --- a/sigmf/sigmffile.py +++ b/sigmf/sigmffile.py @@ -6,6 +6,7 @@ """SigMFFile Object""" +from typing import Union import codecs import io import json @@ -31,7 +32,7 @@ class SigMFMetafile: VALID_KEYS = {} def __init__(self): - self.version = None + self._version = None self.schema = None self._metadata = None self.shape = None @@ -146,14 +147,38 @@ class SigMFFile(SigMFMetafile): CAPTURE_KEY = "captures" ANNOTATION_KEY = "annotations" VALID_GLOBAL_KEYS = [ - AUTHOR_KEY, COLLECTION_KEY, DATASET_KEY, DATATYPE_KEY, DATA_DOI_KEY, DESCRIPTION_KEY, EXTENSIONS_KEY, - GEOLOCATION_KEY, HASH_KEY, HW_KEY, LICENSE_KEY, META_DOI_KEY, METADATA_ONLY_KEY, NUM_CHANNELS_KEY, RECORDER_KEY, - SAMPLE_RATE_KEY, START_OFFSET_KEY, TRAILING_BYTES_KEY, VERSION_KEY + AUTHOR_KEY, + COLLECTION_KEY, + DATASET_KEY, + DATATYPE_KEY, + DATA_DOI_KEY, + DESCRIPTION_KEY, + EXTENSIONS_KEY, + GEOLOCATION_KEY, + HASH_KEY, + HW_KEY, + LICENSE_KEY, + META_DOI_KEY, + METADATA_ONLY_KEY, + NUM_CHANNELS_KEY, + RECORDER_KEY, + SAMPLE_RATE_KEY, + START_OFFSET_KEY, + TRAILING_BYTES_KEY, + VERSION_KEY, ] VALID_CAPTURE_KEYS = [DATETIME_KEY, FREQUENCY_KEY, HEADER_BYTES_KEY, GLOBAL_INDEX_KEY, START_INDEX_KEY] VALID_ANNOTATION_KEYS = [ - COMMENT_KEY, FHI_KEY, FLO_KEY, GENERATOR_KEY, LABEL_KEY, LAT_KEY, LENGTH_INDEX_KEY, LON_KEY, START_INDEX_KEY, - UUID_KEY + COMMENT_KEY, + FHI_KEY, + FLO_KEY, + GENERATOR_KEY, + LABEL_KEY, + LAT_KEY, + LENGTH_INDEX_KEY, + LON_KEY, + START_INDEX_KEY, + UUID_KEY, ] VALID_KEYS = {GLOBAL_KEY: VALID_GLOBAL_KEYS, CAPTURE_KEY: VALID_CAPTURE_KEYS, ANNOTATION_KEY: VALID_ANNOTATION_KEYS} @@ -262,6 +287,100 @@ def _is_conforming_dataset(self): # if we get here, the file exists and is conforming return True + @property + def datatype(self) -> str: + """Fetches the datatype.""" + return self.get_global_field("core:datatype") + + @property + def sample_rate(self) -> float: + """Fetches the sample_rate in Hz.""" + return float(self.get_global_field("core:sample_rate")) + + @property + def version(self) -> str: + """Fetches the version.""" + return self.get_global_field("core:version") + + @version.setter + def version(self, v): + self.set_global_field("core:version", v) + + @property + def author(self) -> Union[str, None]: + """Fetches the author.""" + return self.get_global_field("core:author") + + @property + def collection(self) -> Union[str, None]: + """Fetches the collection.""" + return self.get_global_field("core:collection") + + @property + def dataset(self) -> Union[str, None]: + """Fetches the dataset.""" + return self.get_global_field("core:dataset") + + @property + def data_doi(self) -> Union[str, None]: + """Fetches the author.""" + return self.get_global_field("core:data_doi") + + @property + def description(self) -> Union[str, None]: + """Fetches the description.""" + return self.get_global_field("core:description") + + @property + def hw(self) -> Union[str, None]: + """Fetches the author.""" + return self.get_global_field("core:hw") + + @property + def license(self) -> Union[str, None]: + """Fetches the license.""" + return self.get_global_field("core:license") + + @property + def metadata_only(self) -> Union[bool, None]: + """Fetches the metadata_only.""" + return self.get_global_field("core:metadata_only") + + @property + def meta_doi(self) -> Union[str, None]: + """Fetches the author.""" + return self.get_global_field("core:meta_doi") + + @property + def num_channels(self) -> Union[int, None]: + """Fetches the num_channels.""" + return self.get_global_field("core:num_channels", 1) + + @property + def offset(self) -> Union[int, None]: + """Fetches the offset.""" + return self.get_global_field("core:offset", 0) + + @property + def recorder(self) -> Union[str, None]: + """Fetches the recorder.""" + return self.get_global_field("core:recorder") + + @property + def sha512(self) -> Union[str, None]: + """Fetches the sha512.""" + return self.get_global_field("core:sha512") + + @property + def trailing_bytes(self) -> Union[int, None]: + """Fetches the trailing bytes.""" + return self.get_global_field("core:trailing_bytes") + + @property + def geolocation(self): + """Fetches the geolocation.""" + return self.get_global_field("core:geolocation") + def get_schema(self): """ Return a schema object valid for the current metadata @@ -768,7 +887,9 @@ class SigMFCollection(SigMFMetafile): ] VALID_KEYS = {COLLECTION_KEY: VALID_COLLECTION_KEYS} - def __init__(self, metafiles: list = None, metadata: dict = None, base_path=None, skip_checksums: bool = False) -> None: + def __init__( + self, metafiles: list = None, metadata: dict = None, base_path=None, skip_checksums: bool = False + ) -> None: """ Create a SigMF Collection object. @@ -1046,6 +1167,7 @@ def fromarchive(archive_path, dir=None, skip_checksum=False): access SigMF archives without extracting them. """ from .archivereader import SigMFArchiveReader + return SigMFArchiveReader(archive_path, skip_checksum=skip_checksum).sigmffile @@ -1119,8 +1241,10 @@ def get_sigmf_filenames(filename): # suffix, because the filename might contain '.' characters which are part # of the filename rather than an extension. sigmf_suffixes = [ - SIGMF_DATASET_EXT, SIGMF_METADATA_EXT, - SIGMF_ARCHIVE_EXT, SIGMF_COLLECTION_EXT, + SIGMF_DATASET_EXT, + SIGMF_METADATA_EXT, + SIGMF_ARCHIVE_EXT, + SIGMF_COLLECTION_EXT, ] if stem_path.suffix in sigmf_suffixes: with_suffix_path = stem_path