sinapsis-data-tools 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. sinapsis_data_readers/src/sinapsis_data_readers/__init__.py +0 -0
  2. sinapsis_data_readers/src/sinapsis_data_readers/helpers/__init__.py +0 -0
  3. sinapsis_data_readers/src/sinapsis_data_readers/helpers/coco_dataclasses.py +60 -0
  4. sinapsis_data_readers/src/sinapsis_data_readers/helpers/file_path_helpers.py +69 -0
  5. sinapsis_data_readers/src/sinapsis_data_readers/helpers/image_color_space_converter.py +53 -0
  6. sinapsis_data_readers/src/sinapsis_data_readers/helpers/sklearn_dataset_subset.py +17 -0
  7. sinapsis_data_readers/src/sinapsis_data_readers/helpers/text_input_helpers.py +16 -0
  8. sinapsis_data_readers/src/sinapsis_data_readers/templates/__init__.py +55 -0
  9. sinapsis_data_readers/src/sinapsis_data_readers/templates/audio_readers/__init__.py +0 -0
  10. sinapsis_data_readers/src/sinapsis_data_readers/templates/audio_readers/audio_reader_pydub.py +152 -0
  11. sinapsis_data_readers/src/sinapsis_data_readers/templates/audio_readers/audio_reader_soundfile.py +129 -0
  12. sinapsis_data_readers/src/sinapsis_data_readers/templates/audio_readers/audio_reader_to_bytes.py +57 -0
  13. sinapsis_data_readers/src/sinapsis_data_readers/templates/audio_readers/base_audio_reader.py +57 -0
  14. sinapsis_data_readers/src/sinapsis_data_readers/templates/base_file_data_loader.py +184 -0
  15. sinapsis_data_readers/src/sinapsis_data_readers/templates/datasets_readers/__init__.py +0 -0
  16. sinapsis_data_readers/src/sinapsis_data_readers/templates/datasets_readers/dataset_splitter.py +233 -0
  17. sinapsis_data_readers/src/sinapsis_data_readers/templates/datasets_readers/sklearn_datasets.py +144 -0
  18. sinapsis_data_readers/src/sinapsis_data_readers/templates/datasets_readers/sktime_datasets.py +88 -0
  19. sinapsis_data_readers/src/sinapsis_data_readers/templates/image_readers/__init__.py +0 -0
  20. sinapsis_data_readers/src/sinapsis_data_readers/templates/image_readers/base_image_folder_data_loader.py +123 -0
  21. sinapsis_data_readers/src/sinapsis_data_readers/templates/image_readers/coco_dataset_reader.py +357 -0
  22. sinapsis_data_readers/src/sinapsis_data_readers/templates/image_readers/csv_dataset_reader.py +151 -0
  23. sinapsis_data_readers/src/sinapsis_data_readers/templates/image_readers/image_folder_reader_cv2.py +83 -0
  24. sinapsis_data_readers/src/sinapsis_data_readers/templates/text_readers/__init__.py +0 -0
  25. sinapsis_data_readers/src/sinapsis_data_readers/templates/text_readers/text_input.py +62 -0
  26. sinapsis_data_readers/src/sinapsis_data_readers/templates/video_readers/__init__.py +0 -0
  27. sinapsis_data_readers/src/sinapsis_data_readers/templates/video_readers/base_video_reader.py +300 -0
  28. sinapsis_data_readers/src/sinapsis_data_readers/templates/video_readers/video_reader_cv2.py +96 -0
  29. sinapsis_data_readers/src/sinapsis_data_readers/templates/video_readers/video_reader_dali.py +235 -0
  30. sinapsis_data_readers/src/sinapsis_data_readers/templates/video_readers/video_reader_ffmpeg.py +120 -0
  31. sinapsis_data_readers/src/sinapsis_data_readers/templates/video_readers/video_reader_torchcodec.py +91 -0
  32. sinapsis_data_tools-0.1.0.dist-info/METADATA +873 -0
  33. sinapsis_data_tools-0.1.0.dist-info/RECORD +72 -0
  34. sinapsis_data_tools-0.1.0.dist-info/WHEEL +5 -0
  35. sinapsis_data_tools-0.1.0.dist-info/top_level.txt +4 -0
  36. sinapsis_data_visualization/src/__init__.py +0 -0
  37. sinapsis_data_visualization/src/sinapsis_data_visualization/__init__.py +0 -0
  38. sinapsis_data_visualization/src/sinapsis_data_visualization/helpers/__init__.py +0 -0
  39. sinapsis_data_visualization/src/sinapsis_data_visualization/helpers/annotation_drawer_tools.py +252 -0
  40. sinapsis_data_visualization/src/sinapsis_data_visualization/helpers/annotation_drawer_types.py +56 -0
  41. sinapsis_data_visualization/src/sinapsis_data_visualization/helpers/color_utils.py +108 -0
  42. sinapsis_data_visualization/src/sinapsis_data_visualization/helpers/detection_utils.py +124 -0
  43. sinapsis_data_visualization/src/sinapsis_data_visualization/helpers/plot_distributions.py +130 -0
  44. sinapsis_data_visualization/src/sinapsis_data_visualization/helpers/scikit_pca_analysis.py +51 -0
  45. sinapsis_data_visualization/src/sinapsis_data_visualization/templates/__init__.py +25 -0
  46. sinapsis_data_visualization/src/sinapsis_data_visualization/templates/base_annotation_drawer.py +103 -0
  47. sinapsis_data_visualization/src/sinapsis_data_visualization/templates/bbox_drawer.py +105 -0
  48. sinapsis_data_visualization/src/sinapsis_data_visualization/templates/data_distribution_visualization_template.py +245 -0
  49. sinapsis_data_visualization/src/sinapsis_data_visualization/templates/key_points_drawer.py +122 -0
  50. sinapsis_data_visualization/src/sinapsis_data_visualization/templates/label_drawer.py +292 -0
  51. sinapsis_data_visualization/src/sinapsis_data_visualization/templates/oriented_bbox_drawer.py +121 -0
  52. sinapsis_data_visualization/src/sinapsis_data_visualization/templates/segmentation_mask_drawer.py +137 -0
  53. sinapsis_data_writers/src/sinapsis_data_writers/__init__.py +0 -0
  54. sinapsis_data_writers/src/sinapsis_data_writers/templates/__init__.py +26 -0
  55. sinapsis_data_writers/src/sinapsis_data_writers/templates/annotation_writers/__init__.py +0 -0
  56. sinapsis_data_writers/src/sinapsis_data_writers/templates/annotation_writers/base_annotation_writer.py +192 -0
  57. sinapsis_data_writers/src/sinapsis_data_writers/templates/annotation_writers/coco_annotation_writer.py +290 -0
  58. sinapsis_data_writers/src/sinapsis_data_writers/templates/audio_writers/__init__.py +0 -0
  59. sinapsis_data_writers/src/sinapsis_data_writers/templates/audio_writers/audio_writer_soundfile.py +121 -0
  60. sinapsis_data_writers/src/sinapsis_data_writers/templates/image_writers/__init__.py +0 -0
  61. sinapsis_data_writers/src/sinapsis_data_writers/templates/image_writers/image_saver.py +183 -0
  62. sinapsis_data_writers/src/sinapsis_data_writers/templates/image_writers/pdf_to_image_converter.py +101 -0
  63. sinapsis_data_writers/src/sinapsis_data_writers/templates/video_writers/__init__.py +0 -0
  64. sinapsis_data_writers/src/sinapsis_data_writers/templates/video_writers/base_video_writer.py +129 -0
  65. sinapsis_data_writers/src/sinapsis_data_writers/templates/video_writers/video_writer_cv2.py +82 -0
  66. sinapsis_data_writers/src/sinapsis_data_writers/templates/video_writers/video_writer_ffmpeg.py +89 -0
  67. sinapsis_generic_data_tools/src/sinapsis_generic_data_tools/__init__.py +1 -0
  68. sinapsis_generic_data_tools/src/sinapsis_generic_data_tools/helpers/__init__.py +0 -0
  69. sinapsis_generic_data_tools/src/sinapsis_generic_data_tools/helpers/postprocess.py +33 -0
  70. sinapsis_generic_data_tools/src/sinapsis_generic_data_tools/templates/__init__.py +20 -0
  71. sinapsis_generic_data_tools/src/sinapsis_generic_data_tools/templates/mask_non_roi.py +99 -0
  72. sinapsis_generic_data_tools/src/sinapsis_generic_data_tools/templates/packet_buffer_queue.py +127 -0
@@ -0,0 +1,60 @@
1
+ # -*- coding: utf-8 -*-
2
+ from pydantic.dataclasses import dataclass
3
+
4
+
5
+ @dataclass(frozen=True)
6
+ class CocoJsonKeys:
7
+ """
8
+ Keys to access the annotations dictionary in coco format
9
+ IMAGES (str): Key to access the 'images' entry.
10
+ FILE_NAME (str): Key to access the 'file_name' entry.
11
+ IMAGE_ID (str): Key to access the 'image_id' entry.
12
+ COCO_LICENSE (str): Key to access the 'coco_license' entry.
13
+ COCO_URL (str): Key to access the 'coco_url' entry.
14
+ HEIGHT (str): Key to access the 'height' entry.
15
+ WIDTH (str): Key to access the 'width' entry.
16
+ DATE (str): Key to access the 'date' entry.
17
+ ANNOTATIONS (str): Key to access the 'annotations' entry.
18
+ """
19
+
20
+ IMAGES: str = "images"
21
+ FILE_NAME: str = "file_name"
22
+ IMAGE_ID: str = "id"
23
+ COCO_LICENSE: str = "license"
24
+ COCO_URL: str = "coco_url"
25
+ HEIGHT: str = "height"
26
+ WIDTH: str = "width"
27
+ DATE: str = "date_captured"
28
+ ANNOTATIONS: str = "annotations"
29
+
30
+
31
+ @dataclass(frozen=True)
32
+ class CocoAnnotationsKeys:
33
+ """
34
+ Keys to access the annotations fields in the coco-format annotations
35
+ IMAGE_ID (str): key to access the 'image_id' field.
36
+ SEGMENTATIONS (str): key to access the 'segmentations' field.
37
+ BBOX (str): key to access the 'bbox' field.
38
+ ORIENTED_BBOX (str): key to access the 'oriented_bbox' field.
39
+ ANNOTATION_ID (str): key to access the 'annotation_id' field.
40
+ AREA (str): key to access the 'area' field.
41
+ CATEGORY_ID (str): key to access the 'category_id' field.
42
+ IS_CROWD (str): key to access the 'is_crowd' field.
43
+ NUM_KEYPOINTS (str): key to access the 'num_keypoints' field.
44
+ KEYPOINTS (str): key to access the 'keypoints' field.
45
+ SEGMENTS_INFO (str): key to access the 'segments_info' field.
46
+ SCORE (str): key to access the 'score' field.
47
+ """
48
+
49
+ IMAGE_ID: str = "image_id"
50
+ SEGMENTATIONS: str = "segmentation"
51
+ BBOX: str = "bbox"
52
+ ORIENTED_BBOX: str = "oriented_bbox"
53
+ ANNOTATION_ID: str = "id"
54
+ AREA: str = "area"
55
+ CATEGORY_ID: str = "category_id"
56
+ IS_CROWD: str = "iscrowd"
57
+ NUM_KEYPOINTS: str = "num_keypoints"
58
+ KEYPOINTS: str = "keypoints"
59
+ SEGMENTS_INFO: str = "segments_info"
60
+ SCORE: str = "score"
@@ -0,0 +1,69 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from pathlib import Path
4
+
5
+
6
+ def is_regex(fpath: str) -> bool:
7
+ """
8
+ Determine if the fiven path contains the character (*) indicating that it might be a regular
9
+ expresion or a glob pattern.
10
+ Args:
11
+ fpath (str): the file path to check
12
+ Returns
13
+ (bool): True if the character is in the pattern, false otherwise.
14
+
15
+ """
16
+ return "*" in fpath
17
+
18
+
19
+ SUPPORTED_VIDEO_TYPE_EXT = ["mp4", "wav", "mov"]
20
+
21
+
22
+ def process_single_path(single_path: str) -> list[str]:
23
+ """Determines all the paths to be visited according to the single
24
+ path provided
25
+
26
+ Args:
27
+ single_path (str): single path provided
28
+
29
+ Returns:
30
+ list[str]: List of all the paths to be visited when processing the data
31
+ """
32
+ video_file_paths: list[str] = []
33
+
34
+ if is_regex(single_path):
35
+ search_pattern_start = single_path.find("*")
36
+ search_pattern_end = single_path.rfind("*")
37
+ root_dir = single_path[0:search_pattern_start]
38
+ pattern = single_path[search_pattern_end:]
39
+ video_file_paths += [str(f.resolve()) for f in Path(root_dir).glob(pattern)]
40
+
41
+ elif "." in single_path and single_path.split(".")[-1].lower() in SUPPORTED_VIDEO_TYPE_EXT:
42
+ video_file_paths = [single_path]
43
+
44
+ elif Path(single_path).is_dir():
45
+ for vid_type in SUPPORTED_VIDEO_TYPE_EXT:
46
+ video_file_paths += [str(f.resolve()) for f in Path(single_path).glob(f"**/*{vid_type}")]
47
+
48
+ return video_file_paths
49
+
50
+
51
+ def parse_file_paths(file_paths: str | list[str]) -> list[str]:
52
+ """
53
+ Check if the path provided is a single path or a list of paths.
54
+ If it's a single path, parse the content inside.
55
+ If it's a list of paths, loop though the list and parse each of them.
56
+
57
+ Args:
58
+ file_paths (str | list[str]): path or list of paths to parse.
59
+
60
+ Returns:
61
+ list[str]: list of complete paths to process
62
+ """
63
+ return_file_paths: list[str] = []
64
+ if isinstance(file_paths, str):
65
+ return_file_paths += process_single_path(file_paths)
66
+ elif isinstance(file_paths, list):
67
+ for file_path in file_paths:
68
+ return_file_paths += process_single_path(file_path)
69
+ return return_file_paths
@@ -0,0 +1,53 @@
1
+ # -*- coding: utf-8 -*-
2
+ from enum import Enum
3
+
4
+ import cv2
5
+ from sinapsis_core.data_containers.data_packet import ImageColor, ImagePacket
6
+ from sinapsis_core.utils.logging_utils import sinapsis_logger
7
+
8
+ color_mapping = {
9
+ (ImageColor.RGB, ImageColor.BGR): cv2.COLOR_RGB2BGR,
10
+ (ImageColor.RGB, ImageColor.GRAY): cv2.COLOR_RGB2GRAY,
11
+ (ImageColor.RGB, ImageColor.RGBA): cv2.COLOR_RGB2RGBA,
12
+ (ImageColor.BGR, ImageColor.RGB): cv2.COLOR_BGR2RGB,
13
+ (ImageColor.BGR, ImageColor.GRAY): cv2.COLOR_BGR2GRAY,
14
+ (ImageColor.BGR, ImageColor.RGBA): cv2.COLOR_BGR2RGBA,
15
+ (ImageColor.GRAY, ImageColor.RGB): cv2.COLOR_GRAY2RGB,
16
+ (ImageColor.GRAY, ImageColor.BGR): cv2.COLOR_GRAY2BGR,
17
+ (ImageColor.GRAY, ImageColor.RGBA): cv2.COLOR_GRAY2RGBA,
18
+ (ImageColor.RGBA, ImageColor.RGB): cv2.COLOR_RGBA2RGB,
19
+ (ImageColor.RGBA, ImageColor.BGR): cv2.COLOR_RGBA2BGR,
20
+ (ImageColor.RGBA, ImageColor.GRAY): cv2.COLOR_RGBA2GRAY,
21
+ }
22
+
23
+
24
+ def convert_color_space_cv(image: ImagePacket, desired_color_space: Enum) -> ImagePacket:
25
+ """Converts an image from one color space to another, provided
26
+ they are in the color mapping options.
27
+
28
+ Args:
29
+ image (ImagePacket): Image packet to apply the conversion
30
+ desired_color_space (Enum): Color space to convert the image
31
+
32
+ Returns:
33
+ ImagePacket: Updated ImagePacket with content converted into the new color space
34
+
35
+ Raises:
36
+ ValueError: If the conversion is not possible, return an error.
37
+
38
+ """
39
+ current_color_space = image.color_space
40
+
41
+ if (current_color_space, desired_color_space) in color_mapping:
42
+ conversion_code = color_mapping[(current_color_space, desired_color_space)]
43
+ try:
44
+ image.content = cv2.cvtColor(image.content, conversion_code)
45
+ image.color_space = desired_color_space
46
+
47
+ except cv2.error:
48
+ sinapsis_logger.error(f"Invalid conversion between {current_color_space} and {desired_color_space}")
49
+
50
+ else:
51
+ raise ValueError(f"Conversion from {current_color_space} to {desired_color_space} is not supported.")
52
+
53
+ return image
@@ -0,0 +1,17 @@
1
+ # -*- coding: utf-8 -*-
2
+ from typing import Callable
3
+
4
+ from sklearn import datasets
5
+
6
+ _sklearn_supported_loaders = {
7
+ name: getattr(datasets, name) for name in dir(datasets) if name.startswith(("load", "fetch"))
8
+ }
9
+
10
+
11
+ def __getattr__(name: str) -> Callable:
12
+ if name in _sklearn_supported_loaders:
13
+ return _sklearn_supported_loaders[name]
14
+ raise AttributeError(f"Function `{name}` not found in sklearn.datasets.")
15
+
16
+
17
+ __all__ = list(_sklearn_supported_loaders.keys())
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Module for processing text input from TextPacket objects."""
3
+
4
+ from sinapsis_core.data_containers.data_packet import TextPacket
5
+
6
+
7
+ def load_input_text(input_data: list[TextPacket]) -> str:
8
+ """Loads and concatenates the text content of all TextPacket objects into a single string.
9
+
10
+ Args:
11
+ input_data (list[TextPacket]): A list of TextPacket objects containing text content.
12
+
13
+ Returns:
14
+ str: A single string containing the concatenated text from all TextPacket objects.
15
+ """
16
+ return "".join(t.content for t in input_data)
@@ -0,0 +1,55 @@
1
+ # -*- coding: utf-8 -*-
2
+ import importlib
3
+ from typing import Callable
4
+
5
+ from sinapsis.templates import _import_template_package
6
+
7
+ _root_lib_path = "sinapsis_data_readers.templates"
8
+
9
+ _template_lookup = {
10
+ "AudioReaderPydub": f"{_root_lib_path}.audio_readers.audio_reader_pydub",
11
+ "AudioReaderSoundfile": f"{_root_lib_path}.audio_readers.audio_reader_soundfile",
12
+ "AudioReaderToBytes": f"{_root_lib_path}.audio_readers.audio_reader_to_bytes",
13
+ "CSVImageDataset": f"{_root_lib_path}.image_readers.csv_dataset_reader",
14
+ "CocoDetectionDatasetCV2": f"{_root_lib_path}.image_readers.coco_dataset_reader",
15
+ "CocoKeypointsDatasetCV2": f"{_root_lib_path}.image_readers.coco_dataset_reader",
16
+ "CocoSegmentationDatasetCV2": f"{_root_lib_path}.image_readers.coco_dataset_reader",
17
+ "ExecuteNTimesAudioReaderPydub": f"{_root_lib_path}.audio_readers.audio_reader_pydub",
18
+ "ExecuteNTimesAudioReaderSoundfile": f"{_root_lib_path}.audio_readers.audio_reader_soundfile",
19
+ "ExecuteNTimesLazyAudioReaderPydub": f"{_root_lib_path}.audio_readers.audio_reader_pydub",
20
+ "ExecuteNTimesLazyAudioReaderSoundfile": f"{_root_lib_path}.audio_readers.audio_reader_soundfile",
21
+ "FolderImageDatasetCV2": f"{_root_lib_path}.image_readers.image_folder_reader_cv2",
22
+ "ImageDatasetSplitter": f"{_root_lib_path}.datasets_readers.dataset_splitter",
23
+ "LazyAudioReaderPydub": f"{_root_lib_path}.audio_readers.audio_reader_pydub",
24
+ "LazyAudioReaderSoundfile": f"{_root_lib_path}.audio_readers.audio_reader_soundfile",
25
+ "MultiVideoReaderCV2": f"{_root_lib_path}.video_readers.video_reader_cv2",
26
+ "MultiVideoReaderDali": f"{_root_lib_path}.video_readers.video_reader_dali",
27
+ "MultiVideoReaderDaliPytorch": f"{_root_lib_path}.video_readers.video_reader_dali",
28
+ "MultiVideoReaderFFMPEG": f"{_root_lib_path}.video_readers.video_reader_ffmpeg",
29
+ "MultiVideoReaderTorchCodec": f"{_root_lib_path}.video_readers.video_reader_torchcodec",
30
+ "TabularDatasetSplitter": f"{_root_lib_path}.datasets_readers.dataset_splitter",
31
+ "TextInput": f"{_root_lib_path}.text_readers.text_input",
32
+ "VideoReaderCV2": f"{_root_lib_path}.video_readers.video_reader_cv2",
33
+ "VideoReaderDali": f"{_root_lib_path}.video_readers.video_reader_dali",
34
+ "VideoReaderDaliPytorch": f"{_root_lib_path}.video_readers.video_reader_dali",
35
+ "VideoReaderFFMPEG": f"{_root_lib_path}.video_readers.video_reader_ffmpeg",
36
+ "VideoReaderTorchCodec": f"{_root_lib_path}.video_readers.video_reader_torchcodec",
37
+ }
38
+
39
+
40
+ _ADDITIONAL_TEMPLATE_MODULES = [
41
+ f"{_root_lib_path}.datasets_readers.sklearn_datasets",
42
+ f"{_root_lib_path}.datasets_readers.sktime_datasets",
43
+ ]
44
+ for t_module in _ADDITIONAL_TEMPLATE_MODULES:
45
+ _template_lookup |= _import_template_package(t_module)
46
+
47
+
48
+ def __getattr__(name: str) -> Callable:
49
+ if name in _template_lookup:
50
+ module = importlib.import_module(_template_lookup[name])
51
+ return getattr(module, name)
52
+ raise AttributeError(f"template `{name}` not found in {_root_lib_path}")
53
+
54
+
55
+ __all__ = list(_template_lookup.keys())
@@ -0,0 +1,152 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import io
4
+ import os
5
+ from typing import cast
6
+
7
+ import numpy as np
8
+ from pydub import AudioSegment
9
+ from sinapsis_core.data_containers.data_packet import AudioPacket, DataContainer
10
+ from sinapsis_core.template_base.multi_execute_template import (
11
+ execute_template_n_times_wrapper,
12
+ )
13
+
14
+ from sinapsis_data_readers.templates.audio_readers.base_audio_reader import (
15
+ _AudioBaseReader,
16
+ )
17
+
18
+
19
+ class AudioReaderPydub(_AudioBaseReader):
20
+ """Audio reader for reading audio data directly from bytes or files using Pydub.
21
+
22
+ This class can read audio data from either a bytes object or a file path,
23
+ using the Pydub library.
24
+ When reading from bytes, it retains the data in byte format.
25
+ When reading from a file, it converts the audio data to a NumPy array.
26
+
27
+
28
+ Usage example:
29
+
30
+ agent:
31
+ name: my_test_agent
32
+ templates:
33
+ - template_name: InputTemplate
34
+ class_name: InputTemplate
35
+ attributes: {}
36
+ - template_name: AudioReaderPydub
37
+ class_name: AudioReaderPydub
38
+ template_input: InputTemplate
39
+ attributes:
40
+ audio_file_path: '/path/to/file.mp3'
41
+ source: 'source/of/file'
42
+ sample_rate_khz: 16
43
+ from_bytes: false
44
+ """
45
+
46
+ class AttributesBaseModel(_AudioBaseReader.AttributesBaseModel):
47
+ """Attributes for the AudioReaderAudioSegment.
48
+
49
+ Args:
50
+ sample_rate_khz (int):
51
+ Sample rate in khz for the processed audio. Defaults to 16hkz.
52
+ from_bytes (bool):
53
+ Flag to determine if the file is in bytes. Defaults to True
54
+
55
+
56
+ """
57
+
58
+ sample_rate_khz: int = 16
59
+ from_bytes: bool = True
60
+
61
+ def read_file(self) -> AudioPacket | None:
62
+ """Reads audio data from a file path or bytes and returns an AudioPacket.
63
+
64
+ If reading from bytes, it returns the audio data in bytes format.
65
+ If reading from a file, it returns audio data as a NumPy array.
66
+
67
+ Returns:
68
+ Optional[AudioPacket]: An AudioPacket containing the audio data,
69
+ sample rate, and metadata, or None if there was an error.
70
+ """
71
+
72
+ audio_data: bytes | np.ndarray
73
+ if self.attributes.from_bytes:
74
+ audio_bytes: bytes = cast(bytes, self.attributes.audio_file_path)
75
+ audio_segment = AudioSegment.from_file(io.BytesIO(audio_bytes))
76
+
77
+ else:
78
+ audio_file_path: str = cast(str, self.attributes.audio_file_path)
79
+ if os.path.exists(audio_file_path):
80
+ audio_segment = AudioSegment.from_file(audio_file_path, format="wav")
81
+
82
+ else:
83
+ self.logger.error("Invalid audio file path: %s", audio_file_path)
84
+ return None
85
+ audio_segment = audio_segment.set_frame_rate(self.attributes.sample_rate_khz * 1000)
86
+ audio_segment = audio_segment.set_channels(1)
87
+
88
+ audio_data = np.array(audio_segment.get_array_of_samples(), dtype=np.float32)
89
+ audio_data = audio_data / (2**15)
90
+
91
+ audio_packet = AudioPacket(
92
+ source=self.attributes.source,
93
+ content=audio_data,
94
+ sample_rate=audio_segment.frame_rate,
95
+ )
96
+ return audio_packet
97
+
98
+
99
+ @execute_template_n_times_wrapper
100
+ class ExecuteNTimesAudioReaderPydub(AudioReaderPydub):
101
+ """
102
+ This template provides functionality to read multiple audios, each of them assigned to
103
+ its own DataContainer and to its own reader process.
104
+ Similar to its base class, it reads the audios using the Pydub library
105
+ """
106
+
107
+
108
+ class LazyAudioReaderPydub(AudioReaderPydub):
109
+ """Reads an audio file using Pydub, obtaining the file path
110
+ from the generic_field of the DataContainer and setting is as the file_path in the attributes.
111
+
112
+ Usage example:
113
+
114
+ agent:
115
+ name: my_test_agent
116
+ templates:
117
+ - template_name: InputTemplate
118
+ class_name: InputTemplate
119
+ attributes: {}
120
+ - template_name: LazyAudioReaderPydub
121
+ class_name: LazyAudioReaderPydub
122
+ template_input: InputTemplate
123
+ attributes:
124
+ sample_rate_khz: 16
125
+ from_bytes: False
126
+ """
127
+
128
+ def get_file_path_from_generic_data(self, container: DataContainer) -> None:
129
+ """Method to retrieve the file path from the genetic data field of DataContainer.
130
+ The method extracts the file path from the generic field and sets as attribute
131
+
132
+ Args:
133
+ container (DataContainer): The DataContainer to extract the file path from
134
+ """
135
+ file_path = container.generic_data.get("audio_path", "")
136
+ self.attributes.audio_file_path = file_path
137
+
138
+ def execute(self, container: DataContainer) -> DataContainer:
139
+ self.get_file_path_from_generic_data(container)
140
+ if self.attributes.audio_file_path:
141
+ return super().execute(container)
142
+
143
+ return container
144
+
145
+
146
+ @execute_template_n_times_wrapper
147
+ class ExecuteNTimesLazyAudioReaderPydub(LazyAudioReaderPydub):
148
+ """
149
+ This template provides functionality to read multiple audios, each of them assigned to
150
+ its own DataContainer and to its own reader process.
151
+ Similar to its base class, it reads the file path from the generic field of the DataContainer
152
+ """
@@ -0,0 +1,129 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import os
4
+ from typing import cast
5
+
6
+ import soundfile as sf
7
+ from sinapsis_core.data_containers.data_packet import AudioPacket, DataContainer
8
+ from sinapsis_core.template_base.multi_execute_template import (
9
+ execute_template_n_times_wrapper,
10
+ )
11
+
12
+ from sinapsis_data_readers.templates.audio_readers.base_audio_reader import (
13
+ _AudioBaseReader,
14
+ )
15
+
16
+
17
+ class AudioReaderSoundfile(_AudioBaseReader):
18
+ """Reads audio data from a file path using Soundfile.
19
+
20
+ This class utilizes the Soundfile library to read audio data from a specified file path.
21
+ It returns the audio data wrapped in an AudioPacket, which includes additional metadata
22
+ such as sample rate and source information.
23
+
24
+
25
+ Usage example:
26
+
27
+ agent:
28
+ name: my_test_agent
29
+ templates:
30
+ - template_name: InputTemplate
31
+ class_name: InputTemplate
32
+ attributes: {}
33
+ - template_name: AudioReaderSoundfile
34
+ class_name: AudioReaderSoundfile
35
+ template_input: InputTemplate
36
+ attributes:
37
+ audio_file_path: '/path/to/file.mp3'
38
+ source: 'source/of/file'
39
+ sample_rate_khz: 16
40
+ from_bytes: true
41
+
42
+ """
43
+
44
+ AttributesBaseModel = _AudioBaseReader.AttributesBaseModel
45
+
46
+ def read_file(self) -> AudioPacket | None:
47
+ """Reads audio data from a file path and returns an AudioPacket.
48
+
49
+ This method checks if the specified audio file exists and attempts to read
50
+ the audio data using the Soundfile library. If successful, it wraps the audio
51
+ data in an AudioPacket and returns it. If the file does not exist or if there
52
+ is an error during reading, it logs the error and returns None.
53
+
54
+ Returns:
55
+ AudioPacket|None: An AudioPacket containing the audio data and
56
+ sample rate, or None if the file could not be read or was invalid.
57
+ """
58
+ audio_path = cast(str, self.attributes.audio_file_path)
59
+ if os.path.exists(audio_path):
60
+ try:
61
+ audio_content, sample_rate = sf.read(audio_path)
62
+ audio_packet = AudioPacket(
63
+ source=self.attributes.source,
64
+ content=audio_content,
65
+ sample_rate=sample_rate,
66
+ )
67
+ return audio_packet
68
+ except (ValueError, TypeError) as e:
69
+ self.logger.error("Error reading audio file: %s", e)
70
+ return None
71
+ else:
72
+ self.logger.error("Invalid audio file path: %s", audio_path)
73
+ return None
74
+
75
+
76
+ @execute_template_n_times_wrapper
77
+ class ExecuteNTimesAudioReaderSoundfile(AudioReaderSoundfile):
78
+ """
79
+ This template provides functionality to read multiple audios, each of them assigned to
80
+ its own DataContainer and to its own reader process.
81
+ Similar to its base class, it reads the audio using the Soundfile library
82
+ """
83
+
84
+
85
+ class LazyAudioReaderSoundfile(AudioReaderSoundfile):
86
+ """Reads audio data from a file path using Soundfile.
87
+
88
+ This class utilizes the Soundfile library to read audio data from a specified file path.
89
+ It returns the audio data wrapped in an AudioPacket, which includes additional metadata
90
+ such as sample rate and source information.
91
+
92
+ Usage example:
93
+
94
+ agent:
95
+ name: my_test_agent
96
+ templates:
97
+ - template_name: InputTemplate
98
+ class_name: InputTemplate
99
+ attributes: {}
100
+ - template_name: LazyAudioReaderSoundfile
101
+ class_name: LazyAudioReaderSoundfile
102
+ template_input: InputTemplate
103
+ attributes:
104
+ sample_rate_khz: 16
105
+ from_bytes: true
106
+ """
107
+
108
+ def get_file_path_from_generic_data(self, container: DataContainer) -> None:
109
+ """Method to retrieve the file path from the genetic data field of DataContainer.
110
+ The method extracts the file path from the generic field and sets as attribute
111
+
112
+ Args:
113
+ container (DataContainer): The DataContainer to extract the file path from
114
+ """
115
+ file_path = container.generic_data["audio_path"]
116
+ self.attributes.audio_file_path = file_path
117
+
118
+ def execute(self, container: DataContainer) -> DataContainer:
119
+ self.get_file_path_from_generic_data(container)
120
+ return super().execute(container)
121
+
122
+
123
+ @execute_template_n_times_wrapper
124
+ class ExecuteNTimesLazyAudioReaderSoundfile(LazyAudioReaderSoundfile):
125
+ """
126
+ This template provides functionality to read multiple audios, each of them assigned to
127
+ its own DataContainer and to its own reader process.
128
+ Similar to its base class, it reads the audio using the Soundfile library
129
+ """
@@ -0,0 +1,57 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from sinapsis_core.data_containers.data_packet import AudioPacket
4
+
5
+ from sinapsis_data_readers.templates.audio_readers.base_audio_reader import (
6
+ _AudioBaseReader,
7
+ )
8
+
9
+
10
+ class AudioReaderToBytes(_AudioBaseReader):
11
+ """
12
+ AudioReader for Reading Audio Files and Converting to Bytes.
13
+ Usage example:
14
+
15
+ agent:
16
+ name: my_test_agent
17
+ templates:
18
+ - template_name: InputTemplate
19
+ class_name: InputTemplate
20
+ attributes: {}
21
+ - template_name: AudioReaderToBytes
22
+ class_name: AudioReaderToBytes
23
+ template_input: InputTemplate
24
+ attributes:
25
+ audio_file_path: '/path/to/file.mp3'
26
+ source: 'source/of/file'
27
+ from_bytes: true
28
+ """
29
+
30
+ def read_file(self) -> AudioPacket | None:
31
+ """
32
+ Reads an audio file from the specified path and converts it into an `AudioPacket`.
33
+
34
+ Returns:
35
+ AudioPacket: An `AudioPacket` object containing the audio data.
36
+
37
+ Raises:
38
+ FileNotFoundError: If the specified audio file does not exist.
39
+ IOError: If there is an error reading the audio file.
40
+ """
41
+
42
+ try:
43
+ with open(self.attributes.audio_file_path, "rb") as audio_file:
44
+ audio_content = audio_file.read()
45
+
46
+ audio_file.close()
47
+ audio_packet = AudioPacket(
48
+ source=self.attributes.audio_file_path,
49
+ content=audio_content,
50
+ )
51
+ return audio_packet
52
+ except FileNotFoundError:
53
+ self.logger.error(f"Audio file not found: {self.attributes.audio_file_path}")
54
+ return None
55
+ except IOError as e:
56
+ self.logger.error(f"Error reading audio file: {e}")
57
+ return None
@@ -0,0 +1,57 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import abc
4
+ from uuid import uuid4
5
+
6
+ from sinapsis_core.data_containers.data_packet import AudioPacket, DataContainer
7
+ from sinapsis_core.template_base import TemplateAttributes
8
+
9
+ from sinapsis_data_readers.templates.base_file_data_loader import _BaseDataReader
10
+
11
+
12
+ class _AudioBaseReader(_BaseDataReader):
13
+ PACKET_ATT_NAME = "audios"
14
+
15
+ class AttributesBaseModel(TemplateAttributes):
16
+ """Attributes for the AudioBaseReader.
17
+
18
+ audio_file_path (str):
19
+ Path to the audio file to be read.
20
+
21
+ source (str):
22
+ The source identifier, defaults to "streamlit".
23
+ """
24
+
25
+ audio_file_path: str
26
+ source: str = str(uuid4())
27
+
28
+ @abc.abstractmethod
29
+ def read_file(self) -> AudioPacket | None:
30
+ """Abstract method to read the audio data.
31
+
32
+ This method must be implemented by subclasses to
33
+ read the audio data and return an AudioPacket with the content
34
+ of the audio.
35
+
36
+ Returns:
37
+ AudioPacket: The audio data wrapped in an AudioPacket.
38
+ """
39
+
40
+ def has_elements(self) -> bool:
41
+ """Flag to indicate if there is still content to process"""
42
+ return True
43
+
44
+ def append_packets_to_container(self, container: DataContainer) -> None:
45
+ """Adds a packet to the input container
46
+
47
+ Args:
48
+ container (DataContainer): container where data is to be appended
49
+ """
50
+ data_packets_to_add = [self.read_file()]
51
+ if data_packets_to_add:
52
+ data_packets_to_add += getattr(container, self.PACKET_ATT_NAME)
53
+ setattr(container, self.PACKET_ATT_NAME, data_packets_to_add)
54
+
55
+ def make_data_entries(self) -> list[AudioPacket]:
56
+ audio_packets: list[AudioPacket] = []
57
+ return audio_packets