# Getting started with `sis-meta`

sis_meta is a Python package specifically designed for working with 
.meta files—annotation files generated by [SIS](https://speechpro.com/product/forensic_analysis/ikarlab-3#tab3), 
an audio forensic software. This package offers an intuitive interface for 
seamlessly reading, creating, editing, and saving metadata files, making it 
an essential tool for handling annotated audio data.

## Installing the package

Get the latest release of this package using the ``pip`` installer::

```
pip install -U sis-meta
```

After that, you can import the package as in the following line.

```python
import sis_meta
```

## Reading Metadata Files

To read the contents of an existing meta file, use the function 
`sis_meta.read_from_file()`. This function returns an instance of the
`sis_meta.Meta` class.

```python
import sis_meta

path = '/home/Documents/data/sound1.wav.meta'
meta = sis_meta.read_from_file(path)
```

The `sis_meta.Meta` object created through this method includes both the
`guide marks` and `groups defined` in the original file.

## Creating a New Meta Object

You can also initialize a `sis_meta.Meta` object from scratch.

```python
import sis_meta

meta = sis_meta.Meta()
```

This newly created object does not include any guide marks. However, 
it comes preloaded with a set of default groups

## Iterating Through Guide Marks

You can iterate through the guide marks in a `sis_meta.Meta` object
using a for.

```python
import sis_meta

path = 'home/Documents/data/sound1.wav.meta'
meta = sis_meta.read_from_file(path)

for guide_mark in meta:
    print('')
    print('position: ', guide_mark.position)
    print('length: ', guide_mark.length)
    print('text: ', guide_mark.text)
    print('group_id: ', guide_mark.group_id)
    print('group_name: ', guide_mark.group_name)
```
In this example, the contents of a meta file are read into a 
`sis_meta.Meta` object. Then, the for loop iterates through its
guide marks. For each iteration, a `sis_meta.mark.GuideMark` 
object is returned, and its attributes are printed.

```
position:  12.992729166666669
length:  36.41172247942387
text: "Hi"
group_id:  6
group_name:  "M1"

position:  51.48970447530865
length:  5.854748328189302
text:  "Where are you?"
group_id:  7
group_name:  "M2"

position:  70.49758603395063
length:  2.325858924897119
text: "Uhm..."
group_id:  6
group_name:  "M1"
```

The attributes printed include:

1. **position:** The starting point of a guide mark in seconds.

2. **length:** The duration of the guide mark in seconds. Marks can represent
intervals or points; for point marks, the length is always 0.

3. **text:** The annotation tied to the guide mark.

4. **group_id:** : A unique identifier for the group to which the guide
mark belongs.

6. **group_name:** The name of the group to which the guide mark belongs.
Group names can be repeated across different guide marks.

## Adding Guide Marks

Once a `sis_meta.Meta` object has been initialized, you can insert new 
guide marks using the method `sis_meta.Meta.insert_guide_mark`.

```python
import sis_meta

# Initialize a Meta object
meta = sis_meta.Meta()

# Insert guide marks
meta.insert_guide_mark('Speakers/M1', 10.424, 1.32, 'Hi')
meta.insert_guide_mark('Speakers/M2', 11.93, 2.42, 'Where are you?')
```

In this example, two guide marks are inserted. For each insertion:

1. The first argument is the group name.

2. The second argument is the starting point of the mark, in seconds.

3. The third argument is the length of the guide mark, also in seconds.

4. The last argument is the text associated with the guide mark.

Every guide mark belongs to a group. The following groups are included by default:

|Group name|Group Id
|---|---|
|`Single`|2|
|`Sounds`|3|
|`Noises`|4|
|`Speakers/M1`|6|
|`Speakers/M2`|7|
|`Speakers/F1`|8|
|`Speakers/F2`|9|
|`VAD`|10|
|`For_AutoCmp`|11|
|`Edit_Tracker/ET_LM`|13|

In the example above:

- The first guide mark belongs to the Speakers/M1 group.
- The second guide mark belongs to the Speakers/M2 group.

## Saving Metadata Files

You can create a new `meta` file using the method `sis_meta.Meta.write()`

```python
  import sis_meta

  meta = sis_meta.Meta()
  meta.insert_guide_mark('Speakers/M1', 10.424, 1.32, 'Hi')
  meta.insert_guide_mark('Speakers/M2', 11.93, 2.42, 'Where are you?')

  # Write a meta file
  meta.write('home/Documents/data/sound1.wav.meta')
```

> [!WARNING]
> If your meta object does not contain any guide marks, attempting
> to write a file will raise an exception

## Managing Groups

### Creating Groups and Subgroups

You can manage the groups in your `sis_meta.Meta` instance. 

To insert a new group, use `sis_meta.Meta.insert_group()` and pass the group
name as the first argument. For example, let's create a group named `MyCat`.

```python
meta = Meta()

# Manage groups
meta.insert_group('MyCat')
```

Once the new group `MyCat` has been created, you can insert guide marks into it

```python
meta.insert_guide_mark('MyCat', 10.424, 1.32, 'Meow')
```

You can also create subgroups to organize your marks. For instance, let’s 
create a parent group `MyCats` and two child groups: `Akuma` and `Kirris`

```python
meta = Meta()

meta.insert_group('MyCats') # Parent group
meta.insert_group('MyCats/Akuma') # Child group
meta.insert_group('MyCats/Kirris') # Child group
```
In this example:

- The parent group `MyCats` is created first.
- Then, subgroups are added by specifying a path.
The leftmost elements in the path represent the parent groups,
while the rightmost element is the name of the subgroup. Elements
are separated by a forward slash (/).

For example, in `MyCats/Akuma`, `MyCats` is the parent group, and `Akuma`
is the subgroup.

You can use the same paths to insert guide marks into specific groups:

```python
# Insert marks
meta.insert_guide_mark('MyCats/Akuma', 1.753, 2.242, 'Aló')
meta.insert_guide_mark('MyCats/Kirris', 3.2424, 2.853, 'hola')
```

In this example:

- The guide mark with text 'Aló' is inserted into the subgroup MyCats/Akuma.
- The guide mark with text 'hola' is inserted into the subgroup MyCats/Kirris


### Removing Groups

You can remove groups using `sis_meta.Meta.remove_group()`

```python
  meta = Meta()

  # Insert groups
  meta.insert_group('Praat')
  meta.insert_group('Praat/Aarón')
  meta.insert_group('Praat/Javier')
  meta.insert_group('Praat/Rolando')

  # Remove marks
  meta.remove_group('Praat/Aarón')
 ```

> [!CAUTION]
> Be cautious when removing groups! All guide marks associated with
> the removed groups will be deleted as well

# License Information

`sis-meta` is distributed under the terms of the [GPL-3.0-or-later](https://spdx.org/licenses/GPL-3.0-or-later.html) license.

# Supporting the Project
This project is developed and maintained by me, and I’m passionate about
making it as useful as possible for the community. If you’ve found sis-meta
helpful in your work or projects, and you’d like to support its continued 
development, you can contribute to my efforts via PayPal.

[Support the Project on PayPal](https://paypal.me/rolandomuar)

Your support is greatly appreciated and helps ensure the project stays updated and functional for everyone. Thank you!
