From ff7f45b078880660398c7f8961e444f54bbf2a2d Mon Sep 17 00:00:00 2001 From: Glen Mabey Date: Fri, 31 Jan 2025 15:41:59 -0700 Subject: [PATCH 1/4] removed the apparently-unnecessary anyOf blocks --- sigmf-schema.json | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/sigmf-schema.json b/sigmf-schema.json index ff2bc44..56493a0 100644 --- a/sigmf-schema.json +++ b/sigmf-schema.json @@ -132,10 +132,7 @@ "additionalItems": false, "items": { "type": "object", - "anyOf": [ - { "required": ["name", "version", "optional"], - "type": "object", "properties": { "name": { "description": "The name of the SigMF extension namespace.", @@ -152,8 +149,6 @@ } }, "additionalProperties": false - } - ] } } }, @@ -166,10 +161,7 @@ "additionalItems": false, "items": { "type": "object", - "anyOf": [ - { "required": ["core:sample_start"], - "type": "object", "properties": { "core:sample_start": { "default": 0, @@ -231,8 +223,6 @@ } }, "additionalProperties": true - } - ] } }, "annotations": { @@ -243,10 +233,7 @@ "items": { "type": "object", "title": "Annotation", - "anyOf": [ - { "required": ["core:sample_start"], - "type": "object", "properties": { "core:sample_start": { "default": 0, @@ -292,8 +279,6 @@ } }, "additionalProperties": true - } - ] } } }, From 42d0c6008c5659e69d4b5f97604c2cbb67065dd0 Mon Sep 17 00:00:00 2001 From: Glen Mabey Date: Wed, 5 Feb 2025 13:31:43 -0700 Subject: [PATCH 2/4] should fix doc generation script --- docs-generator.py | 12 ++++++------ extensions/antenna-schema.json | 6 ------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/docs-generator.py b/docs-generator.py index 45f5d93..23d5ef3 100644 --- a/docs-generator.py +++ b/docs-generator.py @@ -123,16 +123,16 @@ def gen_fields(doc, d): doc.append("\n\n") doc.append(NoEscape("\\rowcolors{1}{}{lightblue}")) with doc.create(Tabular("lllp{3.8in}")) as table: - gen_table(table, data["properties"]["captures"]["items"]["anyOf"][0]) - gen_fields(doc, data["properties"]["captures"]["items"]["anyOf"][0]) + gen_table(table, data["properties"]["captures"]["items"]) + gen_fields(doc, data["properties"]["captures"]["items"]) with doc.create(Subsection("Annotations Array")): doc.append(NoEscape(add_code_tags(data["properties"]["annotations"]["description"]))) doc.append("\n\n") doc.append(NoEscape("\\rowcolors{1}{}{lightblue}")) with doc.create(Tabular("lllp{3.8in}")) as table: - gen_table(table, data["properties"]["annotations"]["items"]["anyOf"][0]) - gen_fields(doc, data["properties"]["annotations"]["items"]["anyOf"][0]) + gen_table(table, data["properties"]["annotations"]["items"]) + gen_fields(doc, data["properties"]["annotations"]["items"]) with doc.create(Subsection("SigMF Collection Format")): doc.append(NoEscape(add_code_tags(data_collection["properties"]["collection"]["description"]))) @@ -158,8 +158,8 @@ def gen_fields(doc, d): doc.append("\n\n") doc.append(NoEscape("\\rowcolors{1}{}{lightblue}")) with doc.create(Tabular("lllp{3.8in}")) as table: - gen_table(table, data_antenna["properties"]["annotations"]["items"]["anyOf"][0]) - gen_fields(doc, data_antenna["properties"]["annotations"]["items"]["anyOf"][0]) + gen_table(table, data_antenna["properties"]["annotations"]["items"]) + gen_fields(doc, data_antenna["properties"]["annotations"]["items"]) doc.append(NoEscape("\\nn")) doc.append(NoEscape(add_code_tags(data_antenna["properties"]["collection"]["description"]))) diff --git a/extensions/antenna-schema.json b/extensions/antenna-schema.json index 8899576..3430894 100644 --- a/extensions/antenna-schema.json +++ b/extensions/antenna-schema.json @@ -83,10 +83,6 @@ "type": "array", "items": { "type": "object", - "anyOf": [ - { - "description": "The annotations value is an array of annotation segment objects that describe anything regarding the signal data not part of the Captures and Global objects. It MUST be sorted by the value of each Annotation Segment's `core:sample_start` key, ascending.", - "type": "object", "properties": { "antenna:azimuth_angle": { "description": "Angle of main beam in azimuthal plane from North, in degrees.", @@ -101,8 +97,6 @@ "type": "string" } } - } - ] } }, "collection": { From 53f851bcd295d4b5b85aa618ef90fd52c872e5d7 Mon Sep 17 00:00:00 2001 From: Glen Mabey Date: Wed, 5 Feb 2025 13:52:52 -0700 Subject: [PATCH 3/4] jq-ification --- extensions/antenna-schema.json | 32 ++-- sigmf-schema.json | 300 +++++++++++++++++++-------------- 2 files changed, 187 insertions(+), 145 deletions(-) diff --git a/extensions/antenna-schema.json b/extensions/antenna-schema.json index 3430894..6f5c4ec 100644 --- a/extensions/antenna-schema.json +++ b/extensions/antenna-schema.json @@ -8,7 +8,9 @@ "global": { "description": "The following names are specified in the `antenna` namespace and should be used in the `global` object:", "type": "object", - "required": ["antenna:model"], + "required": [ + "antenna:model" + ], "properties": { "antenna:model": { "description": "Antenna make and model number. E.g. ARA CSB-16, L-com HG3512UP-NF.", @@ -83,20 +85,20 @@ "type": "array", "items": { "type": "object", - "properties": { - "antenna:azimuth_angle": { - "description": "Angle of main beam in azimuthal plane from North, in degrees.", - "type": "number" - }, - "antenna:elevation_angle": { - "description": "Angle of main beam in elevation plane from horizontal, in degrees.", - "type": "number" - }, - "antenna:polarization": { - "description": "E.g. \"vertical\", \"horizontal\", \"slant-45\", \"left-hand circular\", \"right-hand circular\".", - "type": "string" - } - } + "properties": { + "antenna:azimuth_angle": { + "description": "Angle of main beam in azimuthal plane from North, in degrees.", + "type": "number" + }, + "antenna:elevation_angle": { + "description": "Angle of main beam in elevation plane from horizontal, in degrees.", + "type": "number" + }, + "antenna:polarization": { + "description": "E.g. \"vertical\", \"horizontal\", \"slant-45\", \"left-hand circular\", \"right-hand circular\".", + "type": "string" + } + } } }, "collection": { diff --git a/sigmf-schema.json b/sigmf-schema.json index 56493a0..50bfa90 100644 --- a/sigmf-schema.json +++ b/sigmf-schema.json @@ -4,16 +4,26 @@ "title": "Schema for SigMF Meta Files", "description": "SigMF specifies a way to describe sets of recorded digital signal samples with metadata written in JSON. SigMF can be used to describe general information about a collection of samples, the characteristics of the system that generated the samples, features of signals themselves, and the relationship between different recordings.", "type": "object", - "required": ["global", "captures", "annotations"], + "required": [ + "global", + "captures", + "annotations" + ], "properties": { "global": { "description": "The `global` object consists of key/value pairs that provide information applicable to the entire Dataset. It contains the information that is minimally necessary to open and parse the Dataset file, as well as general information about the Recording itself.", - "required": ["core:datatype", "core:version"], + "required": [ + "core:datatype", + "core:version" + ], "type": "object", "properties": { "core:datatype": { "description": "The SigMF Dataset format of the stored samples in the Dataset file.", - "examples": ["cf32_le", "ri16_le"], + "examples": [ + "cf32_le", + "ri16_le" + ], "default": "cf32_le", "pattern": "^(c|r)(f32|f64|i32|i16|u32|u16|i8|u8)(_le|_be)?", "type": "string" @@ -21,12 +31,15 @@ "core:sample_rate": { "description": "The sample rate of the signal in samples per second.", "minimum": 1, - "maximum": 1e12, + "maximum": 1000000000000, "type": "number" }, "core:author": { "description": "A text identifier for the author potentially including name, handle, email, and/or other ID like Amateur Call Sign", - "examples": ["Bruce Wayne bruce@waynetech.com", "Bruce (K3X)"], + "examples": [ + "Bruce Wayne bruce@waynetech.com", + "Bruce (K3X)" + ], "type": "string" }, "core:collection": { @@ -52,7 +65,9 @@ }, "core:license": { "description": "A URL for the license document under which the Recording is offered. (RFC 3986)", - "examples": ["https://creativecommons.org/licenses/by-sa/4.0/"], + "examples": [ + "https://creativecommons.org/licenses/by-sa/4.0/" + ], "format": "uri", "type": "string" }, @@ -76,7 +91,7 @@ "default": 0, "minimum": 0, "!comment": "The maximum value for this property is equal to 2^63 - 1, making it easy to fit into a signed 64-bit integer.", - "maximum": 9223372036854775807, + "maximum": 9223372036854776000, "type": "integer" }, "core:recorder": { @@ -92,7 +107,7 @@ "description": "The number of bytes to ignore at the end of a Dataset, used ONLY with Non-Conforming Datasets. This field is used with Non-Conforming Datasets to indicate some number of bytes that trail the sample data in the NCD file that should be ignored for processing. This can be used to ignore footer data in non-SigMF filetypes. ", "type": "integer", "minimum": 0, - "maximum": 9223372036854775807 + "maximum": 9223372036854776000 }, "core:version": { "description": "The version of the SigMF specification used to create the Metadata file, in the format X.Y.Z.", @@ -102,11 +117,16 @@ "core:geolocation": { "description": "The location of the Recording system (note, using the Captures scope `geolocation` field is preferred). See the `geolocation` field within the Captures metadata for details. While using the Captures scope `geolocation` is preferred, fixed recording systems may still provide position information within the Global object so it is RECOMMENDED that applications check and use this field if the Captures `geolocation` field is not present.", "type": "object", - "required": ["type", "coordinates"], + "required": [ + "type", + "coordinates" + ], "properties": { "type": { "type": "string", - "enum": ["Point"] + "enum": [ + "Point" + ] }, "coordinates": { "type": "array", @@ -132,23 +152,29 @@ "additionalItems": false, "items": { "type": "object", - "required": ["name", "version", "optional"], - "properties": { - "name": { - "description": "The name of the SigMF extension namespace.", - "type": "string" - }, - "version": { - "description": "The version of the extension namespace specification used.", - "examples": ["1.2.0"], - "type": "string" - }, - "optional": { - "description": "If this field is `true`, the extension is REQUIRED to parse this Recording.", - "type": "boolean" - } - }, - "additionalProperties": false + "required": [ + "name", + "version", + "optional" + ], + "properties": { + "name": { + "description": "The name of the SigMF extension namespace.", + "type": "string" + }, + "version": { + "description": "The version of the extension namespace specification used.", + "examples": [ + "1.2.0" + ], + "type": "string" + }, + "optional": { + "description": "If this field is `true`, the extension is REQUIRED to parse this Recording.", + "type": "boolean" + } + }, + "additionalProperties": false } } }, @@ -161,68 +187,80 @@ "additionalItems": false, "items": { "type": "object", - "required": ["core:sample_start"], + "required": [ + "core:sample_start" + ], + "properties": { + "core:sample_start": { + "default": 0, + "description": "Index of first sample of this chunk. This field specifies the sample index where this Segment takes effect relative to the recorded Dataset file. If the Dataset is a SigMF Dataset file, this field can be immediately mapped to physical disk location since conforming Datasets only contain sample data. ", + "minimum": 0, + "maximum": 9223372036854776000, + "type": "integer" + }, + "core:datetime": { + "description": "An ISO-8601 string indicating the timestamp of the sample index specified by sample_start. This key/value pair MUST be an ISO-8601 string, as defined by [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt), where the only allowed `time-offset` is `Z`, indicating the UTC/Zulu timezone. The ABNF description is: \\begin{verbatim} date-fullyear = 4DIGIT \n date-month = 2DIGIT ; 01-12 \n date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on month/year \n\n time-hour = 2DIGIT ; 00-23 \n time-minute = 2DIGIT ; 00-59 \n time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second rules \n\n time-secfrac = \".\" 1*DIGIT \n time-offset = \"Z\" \n\n partial-time = time-hour \":\" time-minute \":\" time-second [time-secfrac] \n full-date = date-fullyear \"-\" date-month \"-\" date-mday \n full-time = partial-time time-offset \n\n date-time = full-date \"T\" full-time \\end{verbatim} Thus, timestamps take the form of `YYYY-MM-DDTHH:MM:SS.SSSZ`, where any number of digits for fractional seconds is permitted. ", + "examples": [ + "1955-11-05T14:00:00.000Z" + ], + "pattern": "^([\\+-]?\\d{4}(?!\\d{2}\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?", + "type": "string" + }, + "core:frequency": { + "description": "The center frequency of the signal in Hz.", + "type": "number", + "minimum": -1000000000000, + "maximum": 1000000000000, + "examples": [ + 915000000, + 2400000000 + ] + }, + "core:global_index": { + "description": "The index of the sample referenced by `sample_start` relative to an original sample stream. The entirety of which may not have been captured in a recorded Dataset. If omitted, this value SHOULD be treated as equal to `sample_start`. For example, some hardware devices are capable of 'counting' samples at the point of data conversion. This sample count is commonly used to indicate a discontinuity in the datastream between the hardware device and processing. For example, in the below Captures array, there are two Segments describing samples in a SigMF Dataset file. The first Segment begins at the start of the Dataset file. The second segment begins at sample index 500 relative to the recorded samples (and since this is a conforming SigMF Dataset, is physically located on-disk at location `sample_start * sizeof(sample)`), but the `global_index` reports this was actually sample number 1000 in the original datastream, indicating that 500 samples were lost before they could be recorded. \\begin{verbatim} ...\n \"captures\": [ \n { \n \"core:sample_start\": 0, \n \"core:global_index\": 0 \n }, \n { \n \"core:sample_start\": 500, \n \"core:global_index\": 1000 \n }\n ],\n ... \\end{verbatim} ", + "type": "integer", + "minimum": 0, + "maximum": 9223372036854776000 + }, + "core:header_bytes": { + "description": "The number of bytes preceding a chunk of samples that are not sample data, used for NCDs. This field specifies a number of bytes that are not valid sample data that are physically located at the start of where the chunk of samples referenced by this Segment would otherwise begin. If omitted, this value SHOULD be treated as equal zero. If included, the Dataset is by definition a Non-Conforming Dataset. For example, the below Metadata for a Non-Conforming Dataset contains two segments describing chunks of 8-bit complex samples (2 bytes per sample) recorded to disk with 4-byte headers that are not valid for processing. Thus, to map these two chunks of samples into memory, a reader application would map the `500 samples` (equal to `1000 bytes`) in the first Segment, starting at a file offset of `4 bytes`, and then the remainder of the file through EOF starting at a file offset of `1008 bytes` (equal to the size of the previous Segment of samples plus two headers). \\begin{samepage}\\begin{verbatim} { \n \"global\": { \n \"core:datatype\": \"cu8\", \n \"core:version\": \"1.2.0\", \n \"core:dataset\": \"non-conforming-dataset-01.dat\" \n }, \n \"captures\": [ \n { \n \"core:sample_start\": 0, \n \"core:header_bytes\": 4, \n }, \n { \n \"core:sample_start\": 500, \n \"core:header_bytes\": 4, \n }\n ],\n \"annotations\": []\n } \\end{verbatim}\\end{samepage}", + "type": "integer", + "minimum": 0, + "maximum": 9223372036854776000 + }, + "core:geolocation": { + "description": "The location of the recording system at the start of this Captures segment, as a single RFC 7946 GeoJSON `point` Object. For moving emitters, this provides a rudimentary means to manage location through different captures segments. While `core:geolocation` is also allowed in the Global object for backwards compatibility reasons, adding it to Captures is preferred. Per the GeoJSON specification, the point coordinates use the WGS84 coordinate reference system and are `longitude`, `latitude` (REQUIRED, in decimal degrees), and `altitude` (OPTIONAL, in meters above the WGS84 ellipsoid) - in that order. An example including the altitude field is shown below: \\begin{verbatim} \"captures\": {\n ...\n \"core:geolocation\": {\n \"type\": \"Point\",\n \"coordinates\": [-107.6183682, 34.0787916, 2120.0]\n }\n ...\n } \\end{verbatim} GeoJSON permits the use of *Foreign Members* in GeoJSON documents per RFC 7946 Section 6.1. Because the SigMF requirement for the `geolocation` field is to be a valid GeoJSON `point` Object, users MAY include *Foreign Member* fields here for user-defined purposes (position valid indication, GNSS SV counts, dillution of precision, accuracy, etc). It is strongly RECOMMENDED that all fields be documented in a SigMF Extension document. *Note:* Objects named `geometry` or `properties` are prohibited Foreign Members as specified in RFC 7946 Section 7.1.", + "type": "object", + "required": [ + "type", + "coordinates" + ], "properties": { - "core:sample_start": { - "default": 0, - "description": "Index of first sample of this chunk. This field specifies the sample index where this Segment takes effect relative to the recorded Dataset file. If the Dataset is a SigMF Dataset file, this field can be immediately mapped to physical disk location since conforming Datasets only contain sample data. ", - "minimum": 0, - "maximum": 9223372036854775807, - "type": "integer" + "type": { + "type": "string", + "enum": [ + "Point" + ] }, - "core:datetime": { - "description": "An ISO-8601 string indicating the timestamp of the sample index specified by sample_start. This key/value pair MUST be an ISO-8601 string, as defined by [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt), where the only allowed `time-offset` is `Z`, indicating the UTC/Zulu timezone. The ABNF description is: \\begin{verbatim} date-fullyear = 4DIGIT \n date-month = 2DIGIT ; 01-12 \n date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on month/year \n\n time-hour = 2DIGIT ; 00-23 \n time-minute = 2DIGIT ; 00-59 \n time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second rules \n\n time-secfrac = \".\" 1*DIGIT \n time-offset = \"Z\" \n\n partial-time = time-hour \":\" time-minute \":\" time-second [time-secfrac] \n full-date = date-fullyear \"-\" date-month \"-\" date-mday \n full-time = partial-time time-offset \n\n date-time = full-date \"T\" full-time \\end{verbatim} Thus, timestamps take the form of `YYYY-MM-DDTHH:MM:SS.SSSZ`, where any number of digits for fractional seconds is permitted. ", - "examples": ["1955-11-05T14:00:00.000Z"], - "pattern": "^([\\+-]?\\d{4}(?!\\d{2}\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?", - "type": "string" - }, - "core:frequency": { - "description": "The center frequency of the signal in Hz.", - "type": "number", - "minimum": -1e12, - "maximum": 1e12, - "examples": [915e6, 2.4e9] - }, - "core:global_index": { - "description": "The index of the sample referenced by `sample_start` relative to an original sample stream. The entirety of which may not have been captured in a recorded Dataset. If omitted, this value SHOULD be treated as equal to `sample_start`. For example, some hardware devices are capable of 'counting' samples at the point of data conversion. This sample count is commonly used to indicate a discontinuity in the datastream between the hardware device and processing. For example, in the below Captures array, there are two Segments describing samples in a SigMF Dataset file. The first Segment begins at the start of the Dataset file. The second segment begins at sample index 500 relative to the recorded samples (and since this is a conforming SigMF Dataset, is physically located on-disk at location `sample_start * sizeof(sample)`), but the `global_index` reports this was actually sample number 1000 in the original datastream, indicating that 500 samples were lost before they could be recorded. \\begin{verbatim} ...\n \"captures\": [ \n { \n \"core:sample_start\": 0, \n \"core:global_index\": 0 \n }, \n { \n \"core:sample_start\": 500, \n \"core:global_index\": 1000 \n }\n ],\n ... \\end{verbatim} ", - "type": "integer", - "minimum": 0, - "maximum": 9223372036854775807 - }, - "core:header_bytes": { - "description": "The number of bytes preceding a chunk of samples that are not sample data, used for NCDs. This field specifies a number of bytes that are not valid sample data that are physically located at the start of where the chunk of samples referenced by this Segment would otherwise begin. If omitted, this value SHOULD be treated as equal zero. If included, the Dataset is by definition a Non-Conforming Dataset. For example, the below Metadata for a Non-Conforming Dataset contains two segments describing chunks of 8-bit complex samples (2 bytes per sample) recorded to disk with 4-byte headers that are not valid for processing. Thus, to map these two chunks of samples into memory, a reader application would map the `500 samples` (equal to `1000 bytes`) in the first Segment, starting at a file offset of `4 bytes`, and then the remainder of the file through EOF starting at a file offset of `1008 bytes` (equal to the size of the previous Segment of samples plus two headers). \\begin{samepage}\\begin{verbatim} { \n \"global\": { \n \"core:datatype\": \"cu8\", \n \"core:version\": \"1.2.0\", \n \"core:dataset\": \"non-conforming-dataset-01.dat\" \n }, \n \"captures\": [ \n { \n \"core:sample_start\": 0, \n \"core:header_bytes\": 4, \n }, \n { \n \"core:sample_start\": 500, \n \"core:header_bytes\": 4, \n }\n ],\n \"annotations\": []\n } \\end{verbatim}\\end{samepage}", - "type": "integer", - "minimum": 0, - "maximum": 9223372036854775807 + "coordinates": { + "type": "array", + "minItems": 2, + "maxItems": 3, + "items": { + "type": "number" + } }, - "core:geolocation": { - "description": "The location of the recording system at the start of this Captures segment, as a single RFC 7946 GeoJSON `point` Object. For moving emitters, this provides a rudimentary means to manage location through different captures segments. While `core:geolocation` is also allowed in the Global object for backwards compatibility reasons, adding it to Captures is preferred. Per the GeoJSON specification, the point coordinates use the WGS84 coordinate reference system and are `longitude`, `latitude` (REQUIRED, in decimal degrees), and `altitude` (OPTIONAL, in meters above the WGS84 ellipsoid) - in that order. An example including the altitude field is shown below: \\begin{verbatim} \"captures\": {\n ...\n \"core:geolocation\": {\n \"type\": \"Point\",\n \"coordinates\": [-107.6183682, 34.0787916, 2120.0]\n }\n ...\n } \\end{verbatim} GeoJSON permits the use of *Foreign Members* in GeoJSON documents per RFC 7946 Section 6.1. Because the SigMF requirement for the `geolocation` field is to be a valid GeoJSON `point` Object, users MAY include *Foreign Member* fields here for user-defined purposes (position valid indication, GNSS SV counts, dillution of precision, accuracy, etc). It is strongly RECOMMENDED that all fields be documented in a SigMF Extension document. *Note:* Objects named `geometry` or `properties` are prohibited Foreign Members as specified in RFC 7946 Section 7.1.", - "type": "object", - "required": ["type", "coordinates"], - "properties": { - "type": { - "type": "string", - "enum": ["Point"] - }, - "coordinates": { - "type": "array", - "minItems": 2, - "maxItems": 3, - "items": { - "type": "number" - } - }, - "bbox": { - "type": "array", - "minItems": 4, - "items": { - "type": "number" - } - } + "bbox": { + "type": "array", + "minItems": 4, + "items": { + "type": "number" } } - }, - "additionalProperties": true + } + } + }, + "additionalProperties": true } }, "annotations": { @@ -233,52 +271,54 @@ "items": { "type": "object", "title": "Annotation", - "required": ["core:sample_start"], - "properties": { - "core:sample_start": { - "default": 0, - "description": "The sample index at which this Segment takes effect.", - "minimum": 0, - "maximum": 9223372036854775807, - "type": "integer" - }, - "core:sample_count": { - "description": "The number of samples that this Segment applies to.", - "type": "integer", - "minimum": 0, - "maximum": 9223372036854775807 - }, - "core:freq_lower_edge": { - "description": "The frequency (Hz) of the lower edge of the feature described by this annotation. The `freq_lower_edge` and `freq_upper_edge` fields SHOULD be at RF if the feature is at a known RF frequency. If there is no known center frequency (as defined by the `frequency` field in the relevant Capture Segment Object), or the center frequency is at baseband, the `freq_lower_edge` and `freq_upper_edge` fields SHOULD be relative to baseband. It is REQUIRED that both `freq_lower_edge` and `freq_upper_edge` be provided, or neither; the use of just one field is not allowed. ", - "type": "number", - "minimum": -1e12, - "maximum": 1e12 - }, - "core:freq_upper_edge": { - "description": "The frequency (Hz) of the upper edge of the feature described by this annotation.", - "type": "number", - "minimum": -1e12, - "maximum": 1e12 - }, - "core:label": { - "description": "A short form human/machine-readable label for the annotation. The `label` field MAY be used for any purpose, but it is RECOMMENDED that it be limited to no more than 20 characters as a common use is a short form GUI indicator. Similarly, it is RECOMMENDED that any user interface making use of this field be capable of displaying up to 20 characters. ", - "type": "string" - }, - "core:comment": { - "description": "A human-readable comment, intended to be used for longer comments (it is recommended to use `label` for shorter text).", - "type": "string" - }, - "core:generator": { - "description": "Human-readable name of the entity that created this annotation.", - "type": "string" - }, - "core:uuid": { - "description": "RFC-4122 unique identifier.", - "format": "uuid", - "type": "string" - } - }, - "additionalProperties": true + "required": [ + "core:sample_start" + ], + "properties": { + "core:sample_start": { + "default": 0, + "description": "The sample index at which this Segment takes effect.", + "minimum": 0, + "maximum": 9223372036854776000, + "type": "integer" + }, + "core:sample_count": { + "description": "The number of samples that this Segment applies to.", + "type": "integer", + "minimum": 0, + "maximum": 9223372036854776000 + }, + "core:freq_lower_edge": { + "description": "The frequency (Hz) of the lower edge of the feature described by this annotation. The `freq_lower_edge` and `freq_upper_edge` fields SHOULD be at RF if the feature is at a known RF frequency. If there is no known center frequency (as defined by the `frequency` field in the relevant Capture Segment Object), or the center frequency is at baseband, the `freq_lower_edge` and `freq_upper_edge` fields SHOULD be relative to baseband. It is REQUIRED that both `freq_lower_edge` and `freq_upper_edge` be provided, or neither; the use of just one field is not allowed. ", + "type": "number", + "minimum": -1000000000000, + "maximum": 1000000000000 + }, + "core:freq_upper_edge": { + "description": "The frequency (Hz) of the upper edge of the feature described by this annotation.", + "type": "number", + "minimum": -1000000000000, + "maximum": 1000000000000 + }, + "core:label": { + "description": "A short form human/machine-readable label for the annotation. The `label` field MAY be used for any purpose, but it is RECOMMENDED that it be limited to no more than 20 characters as a common use is a short form GUI indicator. Similarly, it is RECOMMENDED that any user interface making use of this field be capable of displaying up to 20 characters. ", + "type": "string" + }, + "core:comment": { + "description": "A human-readable comment, intended to be used for longer comments (it is recommended to use `label` for shorter text).", + "type": "string" + }, + "core:generator": { + "description": "Human-readable name of the entity that created this annotation.", + "type": "string" + }, + "core:uuid": { + "description": "RFC-4122 unique identifier.", + "format": "uuid", + "type": "string" + } + }, + "additionalProperties": true } } }, From f9d603ea03048ea678117ef794ef68658d39c5a5 Mon Sep 17 00:00:00 2001 From: Glen Mabey Date: Wed, 5 Feb 2025 16:15:55 -0700 Subject: [PATCH 4/4] reverts maximum value to 2**63-1 --- sigmf-schema.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sigmf-schema.json b/sigmf-schema.json index 50bfa90..9167db3 100644 --- a/sigmf-schema.json +++ b/sigmf-schema.json @@ -91,7 +91,7 @@ "default": 0, "minimum": 0, "!comment": "The maximum value for this property is equal to 2^63 - 1, making it easy to fit into a signed 64-bit integer.", - "maximum": 9223372036854776000, + "maximum": 9223372036854775807, "type": "integer" }, "core:recorder": { @@ -107,7 +107,7 @@ "description": "The number of bytes to ignore at the end of a Dataset, used ONLY with Non-Conforming Datasets. This field is used with Non-Conforming Datasets to indicate some number of bytes that trail the sample data in the NCD file that should be ignored for processing. This can be used to ignore footer data in non-SigMF filetypes. ", "type": "integer", "minimum": 0, - "maximum": 9223372036854776000 + "maximum": 9223372036854775807 }, "core:version": { "description": "The version of the SigMF specification used to create the Metadata file, in the format X.Y.Z.", @@ -195,7 +195,7 @@ "default": 0, "description": "Index of first sample of this chunk. This field specifies the sample index where this Segment takes effect relative to the recorded Dataset file. If the Dataset is a SigMF Dataset file, this field can be immediately mapped to physical disk location since conforming Datasets only contain sample data. ", "minimum": 0, - "maximum": 9223372036854776000, + "maximum": 9223372036854775807, "type": "integer" }, "core:datetime": { @@ -220,13 +220,13 @@ "description": "The index of the sample referenced by `sample_start` relative to an original sample stream. The entirety of which may not have been captured in a recorded Dataset. If omitted, this value SHOULD be treated as equal to `sample_start`. For example, some hardware devices are capable of 'counting' samples at the point of data conversion. This sample count is commonly used to indicate a discontinuity in the datastream between the hardware device and processing. For example, in the below Captures array, there are two Segments describing samples in a SigMF Dataset file. The first Segment begins at the start of the Dataset file. The second segment begins at sample index 500 relative to the recorded samples (and since this is a conforming SigMF Dataset, is physically located on-disk at location `sample_start * sizeof(sample)`), but the `global_index` reports this was actually sample number 1000 in the original datastream, indicating that 500 samples were lost before they could be recorded. \\begin{verbatim} ...\n \"captures\": [ \n { \n \"core:sample_start\": 0, \n \"core:global_index\": 0 \n }, \n { \n \"core:sample_start\": 500, \n \"core:global_index\": 1000 \n }\n ],\n ... \\end{verbatim} ", "type": "integer", "minimum": 0, - "maximum": 9223372036854776000 + "maximum": 9223372036854775807 }, "core:header_bytes": { "description": "The number of bytes preceding a chunk of samples that are not sample data, used for NCDs. This field specifies a number of bytes that are not valid sample data that are physically located at the start of where the chunk of samples referenced by this Segment would otherwise begin. If omitted, this value SHOULD be treated as equal zero. If included, the Dataset is by definition a Non-Conforming Dataset. For example, the below Metadata for a Non-Conforming Dataset contains two segments describing chunks of 8-bit complex samples (2 bytes per sample) recorded to disk with 4-byte headers that are not valid for processing. Thus, to map these two chunks of samples into memory, a reader application would map the `500 samples` (equal to `1000 bytes`) in the first Segment, starting at a file offset of `4 bytes`, and then the remainder of the file through EOF starting at a file offset of `1008 bytes` (equal to the size of the previous Segment of samples plus two headers). \\begin{samepage}\\begin{verbatim} { \n \"global\": { \n \"core:datatype\": \"cu8\", \n \"core:version\": \"1.2.0\", \n \"core:dataset\": \"non-conforming-dataset-01.dat\" \n }, \n \"captures\": [ \n { \n \"core:sample_start\": 0, \n \"core:header_bytes\": 4, \n }, \n { \n \"core:sample_start\": 500, \n \"core:header_bytes\": 4, \n }\n ],\n \"annotations\": []\n } \\end{verbatim}\\end{samepage}", "type": "integer", "minimum": 0, - "maximum": 9223372036854776000 + "maximum": 9223372036854775807 }, "core:geolocation": { "description": "The location of the recording system at the start of this Captures segment, as a single RFC 7946 GeoJSON `point` Object. For moving emitters, this provides a rudimentary means to manage location through different captures segments. While `core:geolocation` is also allowed in the Global object for backwards compatibility reasons, adding it to Captures is preferred. Per the GeoJSON specification, the point coordinates use the WGS84 coordinate reference system and are `longitude`, `latitude` (REQUIRED, in decimal degrees), and `altitude` (OPTIONAL, in meters above the WGS84 ellipsoid) - in that order. An example including the altitude field is shown below: \\begin{verbatim} \"captures\": {\n ...\n \"core:geolocation\": {\n \"type\": \"Point\",\n \"coordinates\": [-107.6183682, 34.0787916, 2120.0]\n }\n ...\n } \\end{verbatim} GeoJSON permits the use of *Foreign Members* in GeoJSON documents per RFC 7946 Section 6.1. Because the SigMF requirement for the `geolocation` field is to be a valid GeoJSON `point` Object, users MAY include *Foreign Member* fields here for user-defined purposes (position valid indication, GNSS SV counts, dillution of precision, accuracy, etc). It is strongly RECOMMENDED that all fields be documented in a SigMF Extension document. *Note:* Objects named `geometry` or `properties` are prohibited Foreign Members as specified in RFC 7946 Section 7.1.", @@ -279,14 +279,14 @@ "default": 0, "description": "The sample index at which this Segment takes effect.", "minimum": 0, - "maximum": 9223372036854776000, + "maximum": 9223372036854775807, "type": "integer" }, "core:sample_count": { "description": "The number of samples that this Segment applies to.", "type": "integer", "minimum": 0, - "maximum": 9223372036854776000 + "maximum": 9223372036854775807 }, "core:freq_lower_edge": { "description": "The frequency (Hz) of the lower edge of the feature described by this annotation. The `freq_lower_edge` and `freq_upper_edge` fields SHOULD be at RF if the feature is at a known RF frequency. If there is no known center frequency (as defined by the `frequency` field in the relevant Capture Segment Object), or the center frequency is at baseband, the `freq_lower_edge` and `freq_upper_edge` fields SHOULD be relative to baseband. It is REQUIRED that both `freq_lower_edge` and `freq_upper_edge` be provided, or neither; the use of just one field is not allowed. ",