Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add presentation Extension #234

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
245 changes: 245 additions & 0 deletions extensions/presentation.sigmf-ext.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
# The `presentation` SigMF Extension Namespace v1.0.0

This document defines the `presentation` extension namespace for the Signal
Metadata Format (SigMF) specification. This extension namespace contains objects
to help define how SigMF metadata should be presented graphically to users.

All fields in the `presentation` extension are optional, thus any SigMF
application using this extension is not required to implement any particular
feature. It is RECOMMENDED that applications adhering to the `presentation`
extension use default values in this document. It is also RECOMMENDED that
applications implementing this extension describe what fields are implemented.

## 0 Datatypes

The `presentation` extension defines the following SigMF datatypes:

|type|long-form name|description|
|----|--------------|-----------|
|`color`|Color String|String representing a color, this may be specified in either "#RRGGBB" or "#RRGGBBAA" hexadecimal form, or one of the 147 SVG named colors.|

### 0.1 The `color` datatype

The `color` datatype is a string which MUST be either 6 or 8 hexadecimal
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you consider also allowing strings from this well-defined set of color names? https://www.w3.org/TR/SVG11/types.html#ColorKeywords

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be ver nice overall but I am not sure if this is burdensome on applications implementing this. Interestingly the merge request with inspectrum does support this (thanks to QT's native support for it).

Open to any thoughts here, especially situations this would be a problem.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thought (I'm not strongly advocating this, but I do like it) is to separate the color and the alpha into two separate fields. That would eliminate the RGBA vs ARGB issue, and simultaneously allow for alpha-izing named colors.

Inasmuch as the .sigmf-meta files are supposed to be "human readable", and inasmuch as I still have a hard time visually decoding hex color strings, named colors would be ... more understandable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

human readability is a strongly beneficial reason to do this. Not sold on separate alpha but i see your use case...will think more. could be an optional that overrides AARRGGBB....

characters long prepended by a "#". It MAY be specified in capital or lower case
characters and applications MUST handle either. The alpha channel is optional,
and while compliant software MUST be able to parse either format presentation of
the alpha channel by visualization software is RECOMMENDED but OPTIONAL. If
software is unable to render the alpha channel then it SHOULD ignore the alpha
value for foreground objects and ignore background objects entirely.

It is RECOMMENDED that applications include support for hexadecimal and named
colors, however if support for one or the other is not possible, it is
permissable for a reasonable default to be used and the application to still be
SigMF Compliant since support for this extension is not required at all for
SigMF Compliance.

Note: RGBA is not compatible with QColor objects, which use ARGB. These must be
converted in QT applications!

For greatest compatibility, it is RECOMMENDED that this value default to
`#ffffffff` (fully opaque white) for foreground features and `#ffffff00` (fully
transparent) for background features.

## 1 Global

The `presentation` extension adds the following fields to the `global` SigMF
object:

|name|required|type|description|
|----|--------|----|-----------|
|`capture_default`|false|`presentation_style`|Default style to be used for captures when a style is not specified.|
|`capture_styles`|false|list of `style_entry`|Color of the fill of the annotation, this is generally used with defined alpha channel.|
|`annotation_default`|false|`presentation_style`|Default style to be used for annotations when a style is not specified.|
|`annotation_styles`|false|list of `style_entry`|Color of the foreground captures segment display features.|

Both `capture_styles` and `annotation_styles` are JSON object containg style
information by short form name. This is a simple mechanism to prevent every
annotation or capture segment from defining these fields repeatedly. These
objects have keys that represent capture segments or annotation `label` fields
they apply to and values consisting of `presentation_style` objects.

In a `capture_styles` object the `key` field MAY be underdetermined if there are
multiple `capture_tags`. The first entry in the `capture_tags` list for which
a `captures_styles` `key` exists SHOULD be used.

Applications implementing this extension will generally parse the `*_styles`
fields into a dictionary for easy reference.

### 1.1 The `style_entry` object

The `presentation_style` object is a JSON dictionary entry and is implemented
for dictionary emulation for efficient serialization:

|name|required|type|description|
|----|--------|----|-----------|
|`key`|true|string|Color of the fill of the annotation, this is generally used with defined alpha channel.|
|`style`|true|`presentation_style`|Color of the fill of the annotation, this is generally used with defined alpha channel.|

### 1.2 The `presentation_style` object

The `presentation_style` object is a JSON object where each value is an object with
the following form:

|name|required|type|default|description|
|----|--------|----|-------|-----------|
|`display_type`|true|`display_type`||Color of the fill of the annotation, this is generally used with defined alpha channel.|
|`line_color`|false|color|`#ffffffff`|Color of the foreground captures segment display features.|
|`line_width`|false|double|1.0|Width of the line (in pixels) surrounding the annotation, fractional values are permitted.|
|`fill_color`|false|color|`#ffffff00`|Color of the background, generally used with significant alpha.|
|`text_color`|false|color|`#ffffffff`|Color of any text rendered next to the annotation (label/comment fields, etc).|
|`text_size`|false|double|8|Size (pt) of text rendered next to the annotation (label/comment fields, etc).|
|`comment`|false|string||User comment field, any string is fine.|

The `key` and `display_type` fields are required for all `presentation_style`
objects. When describing a capture segment, the `key` field refers only to the
first key in the captures list.

### 1.1.1 The `display_type` field

The `display_type` field can have the following values:

|value|description|
|----|-------|
|`none`|Do not apply special presentation to this segment, all other fields are ignored.|
|`box`|Apply a box of `line_color` and `line_width` enclosing defined samples, with background `fill_color` (if defined).|
|`diagonal`|Fill the boxed segment with the specified `fill_color` and apply diagonal `line_color` lines to the foreground.|
|`grayscale`|This captures segment should be rendered completely desaturated, other fields are ignored.|
|`point`|Single circle of diameter `line_width` at the center frequency and first sample position. Valid only for annotations.|
|`impulse`|Line covering the entire spectral range at the first sample position. Valid only for annotations.|

## 2 Captures

The `presentation` extension adds the following fields to the `captures` SigMF
object:

|name|required|type|default|description|
|----|--------|----|-------|-----------|
|`style`|false|[presentation style](presentation.sigmf-ext.md#the-presentation-style-field)|{}|Style to use for the segment.|

## 3 Annotations

The `presentation` extension adds the following fields to the `annotations`
SigMF object:

|name|required|type|default|description|
|----|--------|----|-------|-----------|
|`style`|false|[presentation style](presentation.sigmf-ext.md#the-presentation-style-field)|{}|Style to use for the annotation.|
|`color`|false|`color`|`0xffffffff`|Simple suggestion for the annotation color, to be interpreted by the application.|

The `color` and `style` fields SHOULD NOT both be provided. In the event of an
overdetermined specification for color, the first specification found below
should be used to determine the appropriate presentation style:

1. `annotations->presentation:style`
1. `annotations->presentation:color`
1. `global->presentation:annotation_styles`[`annotations->core:label`]
1. default (white box)

## 4 Examples

Example usage of the simple presentation specification, in this case specifying
different box colors (red, then green) in the annotations directly:
```json
...
"annotations": [
{
"core:sample_start": 1000,
"core:sample_count": 100,
"core:label": "signal1",
"core:freq_lower_edge": 119000000,
"core:freq_upper_edge": 120000000,
"presentation:color": "#ff0000ff"
},
{
"core:sample_start": 5000,
"core:sample_count": 100,
"core:label": "signal2",
"core:freq_lower_edge": 119000000,
"core:freq_upper_edge": 120000000,
"presentation:color": "#00ff00ff"
},
]
```

How to use `capture_styles` or `annotation_styles` to specify the same two
annotations above:
```json
"global": {
...
"presentation:capture_styles": [
{
"key": "VALID",
"style": {
"display_type": "none",
"text_size": 0,
"comment": "Valid capture segments have no unique presentation, text disabled."
}
},
{
"key": "INVALID",
"stye": {
"display_type": "diagonal"
"line_color": "#ffff0080",
"line_width": "3.0",
"text_color": "#ffff00ff",
"text_size": 18,
"fill_color": "#00000040",
"comment": "Invalid sections are shaded slightly grey with yellow diagonal lines and large, bright yellow text."
}
}
],
"presentation:annotation_styles": [
{
"key": "signal1",
"style": {
"display_type": "box",
"line_color": "#ff0000",
"comment": "Box signals labeled 'signal1' in RED."
}
},
{
"key": "signal2",
"style": {
"display_type": "box",
"line_color": "#00ff00",
"comment": "Box signals labeled 'signal1' in GREEN."
}
}
]
},
"captures": [
{
"core:sample_start": 0,
"core:capture_tags": ["VALID"],
"core:frequency": 100000000.0
},
{
"core:sample_start": 100000,
"core:capture_tags": ["INVALID","SATURATION"],
"core:frequency": 100000000.0
}
{
"core:sample_start": 101000,
"core:capture_tags": ["VALID"],
"core:frequency": 100000000.0
}
],
"annotations": [
{
"core:sample_start": 1000,
"core:sample_count": 100,
"core:label": "signal1",
"core:freq_lower_edge": 119000000,
"core:freq_upper_edge": 120000000
},
{
"core:sample_start": 5000,
"core:sample_count": 100,
"core:label": "signal2",
"core:freq_lower_edge": 119000000,
"core:freq_upper_edge": 120000000
},
]
```