Skip to content

Commit

Permalink
Adding term to data
Browse files Browse the repository at this point in the history
  • Loading branch information
mbsantiago committed Aug 27, 2024
1 parent 6e49d19 commit c348f81
Show file tree
Hide file tree
Showing 44 changed files with 3,731 additions and 937 deletions.
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.9
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,4 @@ docs: ## Build the documentation.
.PHONY: docs-serve
docs-serve: ## Build the documentation and watch for changes.
@echo "building documentation ..."
URL="http://localhost:8000/soundevent/"; xdg-open $$URL || sensible-browser $$URL || x-www-browser $$URL || gnome-open $$URL
@$(ENV_PREFIX)mkdocs serve
@$(ENV_PREFIX)mkdocs serve --open
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![PyPI version](https://badge.fury.io/py/soundevent.svg)](https://badge.fury.io/py/soundevent)
![tests](https://github.com/mbsantiago/soundevent/actions/workflows/test.yml/badge.svg)
[![docs](https://github.com/mbsantiago/soundevent/actions/workflows/docs.yml/badge.svg)](https://mbsantiago.github.io/soundevent/)
![Python 3.8 +](https://img.shields.io/badge/python->=_3.8-blue.svg)
![Python 3.9 +](https://img.shields.io/badge/python->=_3.9-blue.svg)
![Static Badge](https://img.shields.io/badge/formatting-black-black)
[![codecov](https://codecov.io/gh/mbsantiago/soundevent/branch/main/graph/badge.svg?token=42kVE87avA)](https://codecov.io/gh/mbsantiago/soundevent)

Expand Down
92 changes: 37 additions & 55 deletions docs/data_schemas/descriptors.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
# Data Description

Let's delve into **users**, **tags**, **features**, and **notes** – the tools
that add depth to our bioacoustic research. Categorical tags, numerical
features, and freeform notes bring an extra layer of understanding to our
research objects, while user information provides adequate attribution
to the contribution of all involved.
Let's explore **users**, **terms**, **tags**, **features**, and **notes** – essential tools for enriching bioacoustic research.
Controlled vocabularies (terms), categorical tags, numerical features, and free-form notes provide deeper context and insights into your research objects.
User information ensures proper attribution for everyone involved.

## Users

Collaboration is at the heart of most bioacoustic analyses, involving data
collectors, annotators, reviewers, administrators, developers, and researchers.
To ensure proper attribution of work, soundevent introduces a
[**Users**][soundevent.data.User] data schema, holding minimal information about
each individual involved. The **User** object can optionally include a _name_,
_email_, _username_ (a commonly known alias), and _institution_. Recognizing the
sensitivity of this information, it's important to ensure that individuals are
comfortable sharing these details. If privacy concerns persist, User objects can
be omitted altogether.
Bioacoustic analysis often involves collaboration between data collectors, annotators, reviewers, administrators, developers, and researchers.
To acknowledge contributions, soundevent introduces a [**Users**][soundevent.data.User] data schema, storing basic information about each individual.
The **User** object can optionally include _name_, _email_, _username_ and _institution_.
It's crucial to respect privacy and ensure individuals are comfortable sharing this information.
If concerns remain, User objects can be omitted entirely.

```mermaid
erDiagram
Expand All @@ -29,31 +23,33 @@ erDiagram
}
```

## Terms

[**Terms**][soundevent.data.Term] ensure everyone's on the same page.
Inconsistent naming like "species" vs. "Species" wastes time.
**Terms** provide a controlled vocabulary for common properties used in annotations and descriptions.
We've chosen terms from established vocabularies like Darwin Core and Audiovisual Core, aligning you with best practices.

## Tags

[**Tags**][soundevent.data.Tag] within the `soundevent` package are like
categorical variables that add specific meaning to the objects they adorn—be it
recordings, clips, or sound events. Serving as informative labels, **Tags**
offer a way to organize and contextualize data.
[**Tags**][soundevent.data.Tag] are informative labels within the `soundevent` package.
They add meaning to recordings, clips, or sound events, helping organize and contextualize data.

A **Tag** comprises two essential components: a _key_ and a _value_, both in the
form of simple text. While in many computational contexts, a **Tag** might be
considered just a text, we find it exceptionally beneficial to introduce a
_"namespace"_—the _key_—for each tag. This _key_ refines the meaning of the
**Tag** and establishes the context in which it is employed.
A **Tag** has two parts: a _term_ and a _value_.
The term acts as a namespace, refining the Tag's meaning and context.

```mermaid
erDiagram
Tag{
string key
Tag {
string value
}
Term
Tag ||--o| Term: term
```

The beauty lies in the flexibility offered – there are no restrictions on what
can be employed as a _key_ or _value_. This flexibility accommodates
project-specific requirements, allowing researchers to tailor **Tags** to their
unique needs and objectives.
You have the flexibility to use a term or not.
We strongly recommend it, but it's not mandatory.
This adaptability allows you to tailor Tags to your specific project needs.

??? Note "What is a namespace?"

Expand All @@ -72,42 +68,28 @@ unique needs and objectives.

## Features

[**Features**][soundevent.data.Feature] serve as numerical descriptions,
providing valuable information to the objects they enhance. They can encompass a
range of nature – from measurements of environmental sensors to attributes of
individuals creating a sound, even extending to abstract features extracted by
general-purpose deep learning models. When multiple **Features** accompany sound
events, clips, or recordings, they become tools for understanding similarities
and differences, allowing comparison and visualization in feature space.
**Features** play a pivotal role in outlier identification, gaining insights
into characteristic distribution, and enabling statistical analyses.

A **Feature** comprises a textual _name_ and a floating _value_. In
`soundevent`, lists of **Features** can be attached to various objects without
restrictions on the name or value. This flexibility allows for tailoring
features to specific project needs
[**Features**][soundevent.data.Feature] are numerical descriptions.
They can include measurements from environmental sensors, attributes of sound-producing individuals, or even abstract features extracted by deep learning models.
**Features** enable comparison, visualization, outlier identification, understanding characteristic distributions, and statistical analysis.

A **Feature** consists of a **Term** and a numerical _value_.

```mermaid
erDiagram
Feature {
string name
float value
}
Term
Feature ||--o| Term: term
```

## Notes

[**Notes**][soundevent.data.Note] serve as textual companions, allowing
communication among researchers and providing nuanced context to the objects
they accompany. Whether conveying vital information, engaging in discussions
about specific aspects of the attached objects, or flagging potential data
issues, **Notes** play an indispensable role in promoting collaboration and
enriching the overall understanding of audio data.

These textual _messages_, varying in length, also capture essential details such
as the note's _creator_ and the _time of creation_, ensuring proper recognition.
Beyond their informative role, **Notes** can be marked as _issues_ when
highlighting significant points requiring external review.
[**Notes**] are free-form textual additions, facilitating communication and providing context.
They can convey information, enable discussions, or flag data issues.

**Notes** can have any length and include the note's _creator_ and _time of creation_.
Notes can also be marked as issues to highlight points needing review.

```mermaid
erDiagram
Expand Down
2 changes: 2 additions & 0 deletions docs/javascripts/jquery-3.3.1.min.js

Large diffs are not rendered by default.

183 changes: 183 additions & 0 deletions docs/javascripts/jquery.json-viewer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/**
* jQuery json-viewer
* @author: Alexandre Bodelot <alexandre.bodelot@gmail.com>
* @link: https://github.com/abodelot/jquery.json-viewer
*/
(function($) {

/**
* Check if arg is either an array with at least 1 element, or a dict with at least 1 key
* @return boolean
*/
function isCollapsable(arg) {
return arg instanceof Object && Object.keys(arg).length > 0;
}

/**
* Check if a string looks like a URL, based on protocol
* This doesn't attempt to validate URLs, there's no use and syntax can be too complex
* @return boolean
*/
function isUrl(string) {
var protocols = ['http', 'https', 'ftp', 'ftps'];
for (var i = 0; i < protocols.length; ++i) {
if (string.startsWith(protocols[i] + '://')) {
return true;
}
}
return false;
}

/**
* Return the input string html escaped
* @return string
*/
function htmlEscape(s) {
return s.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/'/g, '&apos;')
.replace(/"/g, '&quot;');
}

/**
* Transform a json object into html representation
* @return string
*/
function json2html(json, options) {
var html = '';
if (typeof json === 'string') {
// Escape tags and quotes
json = htmlEscape(json);

if (options.withLinks && isUrl(json)) {
html += '<a href="' + json + '" class="json-string" target="_blank">' + json + '</a>';
} else {
// Escape double quotes in the rendered non-URL string.
json = json.replace(/&quot;/g, '\\&quot;');
html += '<span class="json-string">"' + json + '"</span>';
}
} else if (typeof json === 'number' || typeof json === 'bigint') {
html += '<span class="json-literal">' + json + '</span>';
} else if (typeof json === 'boolean') {
html += '<span class="json-literal">' + json + '</span>';
} else if (json === null) {
html += '<span class="json-literal">null</span>';
} else if (json instanceof Array) {
if (json.length > 0) {
html += '[<ol class="json-array">';
for (var i = 0; i < json.length; ++i) {
html += '<li>';
// Add toggle button if item is collapsable
if (isCollapsable(json[i])) {
html += '<a href class="json-toggle"></a>';
}
html += json2html(json[i], options);
// Add comma if item is not last
if (i < json.length - 1) {
html += ',';
}
html += '</li>';
}
html += '</ol>]';
} else {
html += '[]';
}
} else if (typeof json === 'object') {
// Optional support different libraries for big numbers
// json.isLosslessNumber: package lossless-json
// json.toExponential(): packages bignumber.js, big.js, decimal.js, decimal.js-light, others?
if (options.bigNumbers && (typeof json.toExponential === 'function' || json.isLosslessNumber)) {
html += '<span class="json-literal">' + json.toString() + '</span>';
} else {
var keyCount = Object.keys(json).length;
if (keyCount > 0) {
html += '{<ul class="json-dict">';
for (var key in json) {
if (Object.prototype.hasOwnProperty.call(json, key)) {
// define a parameter of the json value first to prevent get null from key when the key changed by the function `htmlEscape(key)`
let jsonElement = json[key];
key = htmlEscape(key);
var keyRepr = options.withQuotes ?
'<span class="json-string">"' + key + '"</span>' : key;

html += '<li>';
// Add toggle button if item is collapsable
if (isCollapsable(jsonElement)) {
html += '<a href class="json-toggle">' + keyRepr + '</a>';
} else {
html += keyRepr;
}
html += ': ' + json2html(jsonElement, options);
// Add comma if item is not last
if (--keyCount > 0) {
html += ',';
}
html += '</li>';
}
}
html += '</ul>}';
} else {
html += '{}';
}
}
}
return html;
}

/**
* jQuery plugin method
* @param json: a javascript object
* @param options: an optional options hash
*/
$.fn.jsonViewer = function(json, options) {
// Merge user options with default options
options = Object.assign({}, {
collapsed: false,
rootCollapsable: true,
withQuotes: false,
withLinks: true,
bigNumbers: false
}, options);

// jQuery chaining
return this.each(function() {

// Transform to HTML
var html = json2html(json, options);
if (options.rootCollapsable && isCollapsable(json)) {
html = '<a href class="json-toggle"></a>' + html;
}

// Insert HTML in target DOM element
$(this).html(html);
$(this).addClass('json-document');

// Bind click on toggle buttons
$(this).off('click');
$(this).on('click', 'a.json-toggle', function() {
var target = $(this).toggleClass('collapsed').siblings('ul.json-dict, ol.json-array');
target.toggle();
if (target.is(':visible')) {
target.siblings('.json-placeholder').remove();
} else {
var count = target.children('li').length;
var placeholder = count + (count > 1 ? ' items' : ' item');
target.after('<a href class="json-placeholder">' + placeholder + '</a>');
}
return false;
});

// Simulate click on toggle button when placeholder is clicked
$(this).on('click', 'a.json-placeholder', function() {
$(this).siblings('a.json-toggle').click();
return false;
});

if (options.collapsed == true) {
// Trigger click to collapse all nodes
$(this).find('a.json-toggle').click();
}
});
};
})(jQuery);
Loading

0 comments on commit c348f81

Please sign in to comment.