{"id":918,"date":"2026-05-12T11:53:46","date_gmt":"2026-05-12T11:53:46","guid":{"rendered":"https:\/\/samaruc.webs.upv.es\/?page_id=918"},"modified":"2026-07-22T10:38:52","modified_gmt":"2026-07-22T10:38:52","slug":"samlab","status":"publish","type":"page","link":"https:\/\/samaruc.webs.upv.es\/index.php\/samlab\/","title":{"rendered":"SAMLab Technical Documentation"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">This page describes the internal architecture, deployment workflow, plugin system, and extension mechanisms used by SAMLab. <\/p>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-fe48e5de wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link has-text-align-center wp-element-button\" href=\"#See_Architecture\">See architecture<\/a><\/div>\n\n\n\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link has-text-align-center wp-element-button\" href=\"#User_Workflow\">User Workflow<\/a><\/div>\n\n\n\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"#Build_a_plugin\">Build a Plugin<\/a><\/div>\n\n\n\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"#GPLv3\">Licensing<\/a><\/div>\n<\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<h3 class=\"wp-block-heading has-text-align-center\">Explore recordings<\/h3>\n\n\n\n<p class=\"has-background wp-block-paragraph\" style=\"background-color:#eceff0\">Open WAV files, navigate by time, zoom by frequency, adjust dynamic range, and play segments directly from the interface.<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<h3 class=\"wp-block-heading has-text-align-center\">Annotate events<\/h3>\n\n\n\n<p class=\"has-background wp-block-paragraph\" style=\"background-color:#eceff0\">Select regions in time and frequency, assign categories, edit or delete annotations, and save deployment-level annotation CSV files.<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<h3 class=\"wp-block-heading has-text-align-center\">Run analyses<\/h3>\n\n\n\n<p class=\"has-background wp-block-paragraph\" style=\"background-color:#eceff0\">Choose one or more automatic analysis plugins, view detected events, and export deployment indicators and detected event tables.<\/p>\n<\/div>\n<\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 id=\"See_Architecture\" class=\"wp-block-heading\">How SAMLab is structured<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">SAMLab is structured around a PySide6 graphical interface, reusable processing modules, and an extensible plugin system.  Computational work is moved into Qt worker threads so the interface remains responsive while plugins run.<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column has-background is-layout-flow wp-block-column-is-layout-flow\" style=\"background-color:#eceff0;flex-basis:50%\">\n<p class=\"has-text-align-center has-medium-font-size wp-block-paragraph\"><strong><strong>Main application<\/strong><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>samlab.py<\/strong> defines the MainWindow class and coordinates the main application workflow, including: menu actions, spectrogram visualisation, deployment navigation, event browsing, audio playback, plugin execution, and manual annotation tools.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The graphical interface integrates matplotlib visualisation widgets with PySide6 controls to provide interactive exploration of large underwater acoustic recordings.<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column has-background is-layout-flow wp-block-column-is-layout-flow\" style=\"background-color:#eceff0;flex-basis:50%\">\n<p class=\"has-text-align-center has-medium-font-size wp-block-paragraph\"><strong><strong>Core modules<\/strong><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <strong>modules\/<\/strong>&nbsp;package contains the reusable components used throughout the application, including: graphical dialogs, spectrogram and navigation drawing routines, deployment analysis workflows, shared data models, plugin selection interfaces, status and progress windows, and multithreaded worker classes.<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column has-background is-layout-flow wp-block-column-is-layout-flow\" style=\"background-color:#eceff0;flex-basis:50%\">\n<p class=\"has-text-align-center has-medium-font-size wp-block-paragraph\"><strong>Workers Threads<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Long-running computational tasks are executed in Qt worker threads to prevent the graphical interface from freezing during deployment analyses or plugin execution. Worker classes are responsible for:<br>executing plugins asynchronously, updating progress windows, handling cancellation requests, and returning detected events and indicators back to the main application thread.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This architecture allows SAMLab to process large deployments while maintaining an interactive user experience.<\/p>\n<\/div>\n<\/div>\n\n\n\n<div style=\"height:8px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 id=\"User_Workflow\" class=\"wp-block-heading\">SAMLab user Workflow<\/h2>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"card step\">\n  <h3>\n    <span class=\"step-number\">1<\/span>\n    Open audio\n  <\/h3>\n\n  <p>\n    Use\u00a0<strong>File<\/strong> \u2192 <strong>Open File\u2026<\/strong>\u00a0or double click in the <strong>Deployment Navigation Graph<\/strong> of a deployment to load a WAV file into SAMLab.\n  <\/p>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"card step\">\n  <h3>\n    <span class=\"step-number\">2<\/span>\n    Inspect\n  <\/h3>\n\n  <p>\n    Move through time, zoom into a frequency band of the spectrogram representation, adjust FFT size, dynamic range, etc.\n  <\/p>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"card step\">\n  <h3>\n    <span class=\"step-number\">3<\/span>\n    Analyze\n  <\/h3>\n\n  <p>\n   Use <strong>Analyze<\/strong> \u2192 <strong>Analyze current File\u2026<\/strong> or <strong>Analyze Deployment\u2026<\/strong>, choose specific plugins for acoustic event detection, and review automatically detected events.\n  <\/p>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"card step\">\n  <h3>\n    <span class=\"step-number\">4<\/span>\n    Annotate\n  <\/h3>\n\n  <p>\n    Use manual annotation tools to draw time-frequency boxes, classify acoustic events, and save annotations.\n  <\/p>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Deployment Analysis workflow<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Deployment analysis loads <code>deployment_info.mat<\/code>, scans all <strong>*.WAV<\/strong> files within a deployment directory<sup data-fn=\"ebe11342-18c7-4002-a209-96eaf4beb846\" class=\"fn\"><a href=\"#ebe11342-18c7-4002-a209-96eaf4beb846\" id=\"ebe11342-18c7-4002-a209-96eaf4beb846-link\">1<\/a><\/sup>, executes the selected analysis plugins on each recording, exports deployment indicators to <strong>deployment_indicators.csv<\/strong>, and stores detected events in the HDF5 file <strong>detected_events.h5<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The workflow also supports:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>interrupted-analysis recovery,<\/li>\n\n\n\n<li>partial reprocessing,<\/li>\n\n\n\n<li>resumable deployment analyses,<\/li>\n\n\n\n<li>deployment-level visualisation of extracted indicators.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><br>Deployment indicators can later be visualised through the deployment navigation interface for rapid inspection of long-term acoustic trends.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 id=\"Build_a_plugin\" class=\"wp-block-heading\">Plugin architecture<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Analysis plugins are located in the&nbsp;<code>analysis_plugins\/<\/code>&nbsp;package and are dynamically discovered through:<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column has-background is-layout-flow wp-block-column-is-layout-flow\" style=\"background-color:#eceff0\">\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><code>plugin_loader.discover_plugins(analysis_plugins)<\/code><\/p>\n<\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Each plugin exposes metadata such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>plugin name,<\/li>\n\n\n\n<li>description,<\/li>\n\n\n\n<li>version,<\/li>\n\n\n\n<li>outputs<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">This metadata is used to automatically populate the plugin selection interface and integrate plugin outputs into deployment analyses and event visualisation workflows.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Plugins can operate either on:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>individual recordings,<\/li>\n\n\n\n<li>or complete deployment processing pipelines.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A plugin declares its outputs once in&nbsp;<code>outputs<\/code>.&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>outputs[\"events\"]<\/code>&nbsp;lists the event types the plugin can produce.<\/li>\n\n\n\n<li><code>outputs[\"indicators\"]<\/code>declares the file-level indicators and their data types.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The&nbsp;<code>analyze()<\/code>&nbsp;method returns an <strong>event<\/strong>&nbsp;<code>DataFrame<\/code>&nbsp;and an <strong>indicator<\/strong> dictionary whose keys match&nbsp;<code>outputs[\"indicators\"]<\/code>. <strong>Indicators<\/strong> consist of summarized event information, such as the number of events of a given type, and are used for graphical navigation through the deployment in the <strong>Deployment Navigation Graph<\/strong>.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Adding a new analysis plugin<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">A SAMLab analysis plugin is a Python class with metadata and an&nbsp;<code>analyze()<\/code>&nbsp;method. The method receives the audio array, sampling rate, DSP calibration, band calibration, and a verbosity flag. It returns two objects: <strong>events<\/strong> and file-level <strong>indicators<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. Create a new file<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Place your plugin in the&nbsp;<code>analysis_plugins\/<\/code>&nbsp;package, for example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>analysis_plugins\/my_detector.py<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. Implement the plugin class<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>import numpy as np\nimport pandas as pd\nimport time\n\nfrom modules.models import EVENT_FIELDS_TYPES\n\n\nclass MyDetector:\n    name = \"MyDetector\"\n    description = \"Detects a custom acoustic event and reports one indicator.\"\n    version = \"1.0.0\"\n\n    outputs = {\n        \"events\": &#91;\n            {\n                \"type\": \"MDE\",\n                \"tag\": \"My Detector Event\",\n            }\n        ],\n        \"indicators\": {\n            \"MyDetector_Count &#91;#]\": int,\n        },\n    }\n\n    def analyze(self, x, fs, dsp, bands, verbose=False):\n        \"\"\"\n        Returns\n        -------\n        events : pandas.DataFrame\n            Rows describing detected events, or an empty event DataFrame.\n        indicators : dict\n            File-level values matching outputs&#91;\"indicators\"].\n        \"\"\"\n        start_time = time.time()\n\n        events = pd.DataFrame({\n            name: pd.Series(dtype=dtype)\n            for name, dtype in EVENT_FIELDS_TYPES\n        })\n\n        indicators = {\n            key: np.nan\n            for key in self.outputs&#91;\"indicators\"]\n        }\n\n        event_type = self.outputs&#91;\"events\"]&#91;0]&#91;\"type\"]\n        event_tag = self.outputs&#91;\"events\"]&#91;0]&#91;\"tag\"]\n\n        if verbose:\n            print(\"Running My Detector...\")\n\n        x = np.asarray(x, dtype=float)\n        threshold = np.mean(np.abs(x)) + 4 * np.std(x)\n        hits = np.flatnonzero(np.abs(x) &gt; threshold)\n\n        if hits.size:\n            start = int(hits&#91;0])\n            end = int(hits&#91;-1])\n\n            events.loc&#91;len(events)] = {\n                \"start\": np.uint32(start),\n                \"end\": np.uint32(end),\n                \"fmin\": np.float32(0.0),\n                \"fmax\": np.float32(fs \/ 2),\n                \"f0\": np.float32(np.nan),\n                \"BW\": np.float32(np.nan),\n                \"ICI\": np.float32(np.nan),\n                \"SPL\": np.float32(np.nan),\n                \"score\": np.int8(1),\n                \"user\": np.float32(np.nan),\n                \"type\": event_type,\n                \"tag\": event_tag,\n                \"Tdata\": np.nan,\n                \"Fdata\": np.nan,\n            }\n\n        indicators&#91;\"MyDetector_Count &#91;#]\"] = int(len(events))\n\n        if verbose:\n            print(f\"Analysis finished in {time.time()-start_time:.2f} s\")\n\n        return events, indicators<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. Pandas &#8220;events&#8221; fields expected by SAMLab<\/h3>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><tbody><tr><td><span style=\"caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-family: -webkit-standard; font-size: medium; white-space: normal;\">Field<\/span><\/td><td><span style=\"caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-family: -webkit-standard; font-size: medium; white-space: normal;\">Meaning<\/span><\/td><\/tr><tr><td><code>start<\/code>,&nbsp;<code>end<\/code><\/td><td>Event limits in samples, not seconds.<\/td><\/tr><tr><td><code>fmin<\/code>,&nbsp;<code>fmax<\/code><\/td><td>Frequency bounds in Hz.<\/td><\/tr><tr><td><code>f0<\/code>,&nbsp;<code>BW<\/code>,&nbsp;<code>ICI<\/code>,&nbsp;<code>SPL<\/code><\/td><td>Event central frequency, Bandwidth, Inter Event Interval, and Sound Pressure level (used by the miniature event navigation graph and combo box).<\/td><\/tr><tr><td><code>score<\/code><\/td><td>Detection score or confidence value.<\/td><\/tr><tr><td><code><code>tag<\/code><\/code><\/td><td>Human-readable event label shown in the spectrogram.<\/td><\/tr><tr><td><code>type<\/code>&nbsp;<\/td><td>Compact event code used internally and for filtering.<\/td><\/tr><tr><td><code>Tdata<\/code>,&nbsp;<code>Fdata<\/code><\/td><td>Contour points for time-frequency tracks; use&nbsp;<code>np.nan<\/code>&nbsp;if not applicable.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">4. Match returned indicators to declared output<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If your plugin declares&nbsp;two indicators in <code>outputs<\/code>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code> \"indicators\": {<br>        \"<code>Number of events A [#]<\/code>\": int,<br>        <code>\"Number of events B [#]\"<\/code>: int<br>}<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">, remember to fill the values :<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>indicators[\"<code><code>Number of events A [#]<\/code><\/code>\"] = np.sum(events[\"type\"] == \"A\")<br>indicators[\"<code><code>Number of events B [#]<\/code><\/code>\"] = np.sum(events[\"type\"] == \"B\")<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">These values become extra columns in&nbsp;<code>deployment_indicators.csv<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Test the plugin<\/h3>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"card step\">\n  <h3>\n    <span class=\"step-number\">1<\/span>\n    Import test\n  <\/h3>\n\n  <p>\n    Start SAMLab and check that your plugin appears in the selector with the right name, description, and version.\n  <\/p>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"card step\">\n  <h3>\n    <span class=\"step-number\">2<\/span>\n    Single file\n  <\/h3>\n\n  <p>\n    Run it on a short WAV file and confirm that the event list, spectrogram boxes, and indicators look correct.\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"card step\">\n  <h3>\n    <span class=\"step-number\">3<\/span>\n    Deployment\n  <\/h3>\n\n  <p>\n    Run it on a small deployment folder and check CSV\/HDF5 outputs.\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"card step\">\n  <h3>\n    <span class=\"step-number\">4<\/span>\n  Resume\n  <\/h3>\n\n  <p>\n    For long analyses, verify that interrupted deployment analysis resumes without corrupting results.\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Plugin programming rules<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Do not modify&nbsp;<code>x<\/code>&nbsp;in place unless you intentionally want downstream plugins to see the modified signal. Prefer&nbsp;<code>x = np.asarray(x, dtype=float)<\/code>.<\/li>\n\n\n\n<li>Return an empty&nbsp;<code>DataFrame<\/code>&nbsp;rather than&nbsp;<code>None<\/code>&nbsp;when no events are found.<\/li>\n\n\n\n<li>Keep long loops interrupt-friendly where possible; SAMLab can request interruption between plugins and files.<\/li>\n\n\n\n<li>Use printed progress messages sparingly; they appear in the status window when verbose mode is enabled.<\/li>\n\n\n\n<li>Keep metadata stable. Changing&nbsp;<code>name<\/code>&nbsp;or indicator names in&nbsp;<code>outputs[\"indicators\"]<\/code>&nbsp;affects deployment resume logic and CSV compatibility.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 id=\"GPLv3\" class=\"wp-block-heading\">GPLv3 licensing<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">SAMLab is dual-licensed. Users may choose to use the software under the GNU General Public License version 3 (GPLv3) or under a separate commercial license.<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>GNU General Public License version 3 (GPLv3) <\/strong><br>You may use, modify, and distribute SAMLab under the terms of the GNU General Public License version 3 (GPLv3).  This means users may run, study, share, and modify the software under the GPLv3 terms.<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong><strong>Commercial licensing<\/strong><\/strong><br>Alternatively, if your intended use cannot comply with the GPLv3 (for example, because you wish to distribute SAMLab as part of a proprietary product), a separate commercial license is available from the copyright holder.<\/p>\n<\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Plugin licensing.<\/strong> Developers distributing their own SAMLab plugins should choose an appropriate license for their plugins. Plugins may be released under the GPLv3, under a compatible open-source license, or under a separate commercial or proprietary license, subject to the legal relationship between the plugin and SAMLab.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>SAMLab \u2014 Submarine Acoustic Monitoring Laboratory<\/strong><br>Copyright \u00a9 2026 Universitat Polit\u00e8cnica de Val\u00e8ncia (UPV).<br>Commercial licensing is offered by the copyright holder.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For commercial licensing enquiries, please contact&nbsp;<strong><a>samaruc.info@gmail.com<\/a><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n<ol class=\"wp-block-footnotes\"><li id=\"ebe11342-18c7-4002-a209-96eaf4beb846\"><strong>Deployment requirement:<\/strong>\u00a0a deployment folder should contain\u00a0<code>deployment_info.mat<\/code>\u00a0plus WAV files named with date and time, for example\u00a0<code>XXX_N_1_YYYYMMDD_HHMMSS.WAV<\/code>. <a href=\"#ebe11342-18c7-4002-a209-96eaf4beb846-link\" aria-label=\"Jump to footnote reference 1\">\u21a9\ufe0e<\/a><\/li><\/ol>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This page describes the internal architecture, deployment workflow, plugin system, and extension mechanisms used by SAMLab. Explore recordings Open WAV files, navigate by time, zoom by frequency, adjust dynamic range, and play segments directly from the interface. Annotate events Select regions in time and frequency, assign categories, edit or delete annotations, and save deployment-level annotation [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":"[{\"content\":\"<strong>Deployment requirement:<\/strong>\u00a0a deployment folder should contain\u00a0<code>deployment_info.mat<\/code>\u00a0plus WAV files named with date and time, for example\u00a0<code>XXX_N_1_YYYYMMDD_HHMMSS.WAV<\/code>.\",\"id\":\"ebe11342-18c7-4002-a209-96eaf4beb846\"}]"},"class_list":["post-918","page","type-page","status-publish","hentry","entry"],"_links":{"self":[{"href":"https:\/\/samaruc.webs.upv.es\/index.php\/wp-json\/wp\/v2\/pages\/918","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/samaruc.webs.upv.es\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/samaruc.webs.upv.es\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/samaruc.webs.upv.es\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/samaruc.webs.upv.es\/index.php\/wp-json\/wp\/v2\/comments?post=918"}],"version-history":[{"count":150,"href":"https:\/\/samaruc.webs.upv.es\/index.php\/wp-json\/wp\/v2\/pages\/918\/revisions"}],"predecessor-version":[{"id":1132,"href":"https:\/\/samaruc.webs.upv.es\/index.php\/wp-json\/wp\/v2\/pages\/918\/revisions\/1132"}],"wp:attachment":[{"href":"https:\/\/samaruc.webs.upv.es\/index.php\/wp-json\/wp\/v2\/media?parent=918"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}