SUD Files (#83)

* Adding comments to table definitions.

Update tabledefs so tableitems can have descriptions. Useful to the
coder, but can also export formal xms schema for each table.

* Writing xml schema

Writing xml schema for PAMGuard database with annotations as complex
types

* Working SUD click extractor

Seems to be mostly working and can generate PAMGuard click files
automatically when processing SUD files using the soundtrap click
detector

* Small changes to SUD in PAMGuard

* Better SUD timing

Using latest microsecond time extraction from SUD unpack

* SUD Processing

Extraction of SUD file clicks with SoundTrap Click Detector. Timing now
correct. Added some help pages.

* Functional SUD Reader and SUD Click Extractor

All seems working. Seems to throw the odd exception at end of file, but
works OK.
This commit is contained in:
Douglas Gillespie 2022-11-13 17:41:13 +00:00 committed by GitHub
parent 4a75afc414
commit ea32c5cdcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 1959 additions and 355 deletions

View File

@ -15,12 +15,12 @@
@font-face
{font-family:"Calibri Light";
panose-1:2 15 3 2 2 2 4 3 2 4;}
@font-face
{font-family:Tahoma;
panose-1:2 11 6 4 3 5 4 4 2 4;}
@font-face
{font-family:Cambria;
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Tahoma;
panose-1:2 11 6 4 3 5 4 4 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin-top:0cm;
@ -368,8 +368,8 @@ should be something like:</p>
-Xms384m -Xmx4096m -Djava.library.path=lib64 -jar Pamguard_xxxxxx.jar</span></em></p>
<p class=MsoNormal>The -Xms384m -Xmx4096m specify the initial and maximum heap
size for the JVM being used to run Pamguard i.e. how much memory it gets to use.
The default max size usually being too low.</p>
size for the JVM being used to run Pamguard i.e. how much memory it gets to
use. The default max size usually being too low.</p>
<p class=MsoNormal>The -Djava.library.path=lib64 tells the JVM that it should
look in the folder called &quot;lib64&quot; for the required shared libraries (change
@ -381,8 +381,8 @@ a &quot;-m&quot; or &quot;-v&quot; to the list of java arguments. On Windows
just run the appropriately named executable (e.g. PamguardBeta_MixedMode.exe or
PamguardBeta_ViewerMode.exe):</p>
<p class=MsoNormal><em><span style='font-family:"Calibri",sans-serif'>java
-Xms384m -Xmx4096m -Djava.library.path=lib64 -jar PamguardBeta_xxxxxx.jar -v</span></em></p>
<p class=MsoNormal><em><span style='font-family:"Calibri",sans-serif'>java -Xms384m
-Xmx4096m -Djava.library.path=lib64 -jar PamguardBeta_xxxxxx.jar -v</span></em></p>
<p class=MsoNormal><em><span style='font-family:"Calibri",sans-serif'>&nbsp;</span></em></p>
@ -444,7 +444,26 @@ Version 2.00.10 June 2017</a></span></h1>
<h1><span style='font-size:12.0pt'><a href="#_Older_Versions">Older Versions</a></span></h1>
<h1><a name="_Latest_Version_2.02.03_1"></a><a name="_Latest_Version_2.02.05"></a><span
lang=EN-US>Latest Version 2.02.05 October 2022</span></h1>
lang=EN-US>Latest Version 2.02.06 November 2022</span></h1>
<h2><span lang=EN-US>Bug Fix</span></h2>
<p class=MsoNormal><span lang=EN-US>A memory leak has been found which seems to
mostly occur in Viewer mode. Some data on background noise measurements are not
being cleared from memory, so memory will eventually run out. This could happen
after browsing a lot of data, but was most likely when reprocessing files
offline, for example running click classifiers. This is now fixed. </span></p>
<h2><span lang=EN-US>New Features</span></h2>
<p class=MsoNormal><span lang=EN-US>SoundTrap SUD file reading. If youre using
SoundTrap autonomous recorders from Ocean Instruments, you no longer need to decompress
the SoundTrap files prior to processing. This will save time and a lot of disk
space. Extraction of clicks from the inbuilt SoundTrap Click detector an also
happen while processing SUD file data with other detectors, thereby
streamlining the whole processing chain. Read the online Help for details.   </span></p>
<h1><span lang=EN-US>Latest Version 2.02.05 October 2022</span></h1>
<h2><span lang=EN-US>Click Train Detector Features and Bug Fixes</span></h2>
@ -452,8 +471,9 @@ lang=EN-US>Latest Version 2.02.05 October 2022</span></h1>
<p class=MsoNormal><span lang=EN-US>Changes to GUI to make dialog shorter for
low DPI screens. </span></p>
<p class=MsoNormal><span lang=EN-US>Complete rewrite of the classification
system to have nested classifiers which can be enabled or disabled. </span></p>
<p class=MsoNormal><span lang=EN-US>Complete rewrite of the classification system
to have nested classifiers which can be enabled or disabled. </span></p>
<p class=MsoNormal><span lang=EN-US>Changes to classification GUI to
accommodate the new classification system.</span></p>
@ -498,9 +518,9 @@ audio files. </span></p>
<h2><span lang=EN-US>Bug Fixes</span></h2>
<p class=MsoNormal><span lang=EN-US>Soundtrap DWV import. Will now generate binary
files even if DWV file doesn’t exist (which is correct behavior in quiet
conditions when no clicks were detected). </span></p>
<p class=MsoNormal><span lang=EN-US>Soundtrap DWV import. Will now generate
binary files even if DWV file doesnÂt exist (which is correct behavior in
quiet conditions when no clicks were detected). </span></p>
<p class=MsoNormal><span lang=EN-US>Spectrogram. Changes to stop occasional
crashing when restarting processing of wav files. </span></p>
@ -534,8 +554,8 @@ running in real time. Added template names based on file names. </p>
<p class=MsoNormal>#13 Merging files when offline processing file folders: Had
an error introduced in last release which caused it to fail to recognise gaps
between files, meaning that some output data (i.e. after a gap) would have an
incorrect time stamp. This did not affect data if the ‘merge contiguous files’
option was not selected. </p>
incorrect time stamp. This did not affect data if the ÃÂmerge contiguous
filesÃÂ option was not selected. </p>
<p class=MsoNormal>#14 Logger forms data were not plotting correctly. This was
due to the required data selection functions not being fully implemented. This
@ -574,23 +594,23 @@ understand the notes listed for <a href="#_Latest_Beta_Version_2.00.10">Beta
Version 2.00.10</a> before proceeding with installation and use of this
version.</b></p>
<p class=MsoNormal>This version of PAMGuard has been bundled with Java 16
(OpenJDK release), so you will not need to install a java runtime engine
separately. PSFX files generated in previous beta releases (2.xx.xx) should be
compatible with this version, and vice-versa. PSF files generated in core
releases (1.15.xx) can be loaded in this version, but will be converted to PSFX
files when PAMGuard exits.</p>
<p class=MsoNormal>This version of PAMGuard has been bundled with Java 16 (OpenJDK
release), so you will not need to install a java runtime engine separately.
PSFX files generated in previous beta releases (2.xx.xx) should be compatible
with this version, and vice-versa. PSF files generated in core releases
(1.15.xx) can be loaded in this version, but will be converted to PSFX files
when PAMGuard exits.</p>
<p class=MsoNormal style='margin-bottom:0cm'><span style='font-size:12.0pt;
font-family:"Times New Roman",serif'>&nbsp;</span></p>
<h2>File Format Change</h2>
<p class=MsoNormal>Changes have been made to the binary file format to support
the output of additional noise outputs for certain detectors (See below).
Binary files created with this version will not be compatible with earlier
versions 2.01.### and below. This version will read and may convert earlier
format binary files.</p>
<p class=MsoNormal>Changes have been made to the binary file format to support the
output of additional noise outputs for certain detectors (See below). Binary
files created with this version will not be compatible with earlier versions
2.01.### and below. This version will read and may convert earlier format
binary files.</p>
<p class=MsoNormal style='margin-bottom:0cm'><span style='font-size:12.0pt;
font-family:"Times New Roman",serif'>&nbsp;</span></p>
@ -608,10 +628,10 @@ href="http://www.pamguard.org/downloads.php?cat_id=3">here</a>.</p>
<p class=MsoNormal><b><span lang=EN-US>Detection Group Localiser</span></b><span
lang=EN-US> </span></p>
<p class=MsoNormal>This module has been renamed “Detection Grouper”, so as to
avoid confusion with the Group 3D localizer. This is because the Detection
Grouper is more for organizing data into groups to be localized than it is for
doing localization.</p>
<p class=MsoNormal>This module has been renamed ÓDetection GrouperÔ, so
as to avoid confusion with the Group 3D localizer. This is because the
Detection Grouper is more for organizing data into groups to be localized than
it is for doing localization.</p>
<p class=MsoNormal><b><span lang=EN-US>Minor Bug Fixes</span></b><span
lang=EN-US> </span></p>
@ -729,10 +749,10 @@ included in a future release. </p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>17. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
An implementation of the Generalized Power Law Detector, developed by Tyler
Helble ([Helble et al., ‘A generalized power-law detection algorithm for humpback
whale vocalizations’, The Journal of the Acoustical Society of America, vol.
131, no. 4, pp. 2682–2699, 2012) is now available. For details, see the online
help </p>
Helble ([Helble et al., ÃÂA generalized power-law detection algorithm for
humpback whale vocalizationsÃÂ, The Journal of the Acoustical Society of
America, vol. 131, no. 4, pp. 2682ÃÂ2699, 2012) is now available. For
details, see the online help </p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>18. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
@ -754,10 +774,10 @@ Version 2.00.10</a> before proceeding with installation and use of this
version.</b></p>
<p class=MsoNormal>This version of PAMGuard has been bundled with Java 13
(release 13.0.1). PSFX files generated in previous beta releases (2.xx.xx) should
be compatible with this version, and vice-versa. PSF files generated in core
releases (1.15.xx) can be loaded in this version, but will be converted to PSFX
files when PAMGuard exits.</p>
(release 13.0.1). PSFX files generated in previous beta releases (2.xx.xx)
should be compatible with this version, and vice-versa. PSF files generated in
core releases (1.15.xx) can be loaded in this version, but will be converted to
PSFX files when PAMGuard exits.</p>
<p class=MsoNormal><b><span lang=EN-US>Bug Fixes</span></b></p>
@ -840,8 +860,8 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
Added logger form annotation to Spectrogram Annotation module. </p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>6. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
Better auto-scaling in Ishmael Detector graphics window. </p>
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
lang=EN-US> </span>Better auto-scaling in Ishmael Detector graphics window. </p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>7. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
@ -968,8 +988,8 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
<p class=MsoNormal><b><span lang=EN-US>Upgrades</span></b></p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>1. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
Add functionality for bluetooth headsets. </p>
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
lang=EN-US> </span>Add functionality for bluetooth headsets. </p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>2. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
@ -1093,9 +1113,9 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
Bug 441. Plot coordinate calculations incorrect in PamAxis.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>10. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
Bug 442. BT Display does not change click symbol color when Colour By
Superdetection is selected.</p>
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
lang=EN-US> </span>Bug 442. BT Display does not change click symbol color when
Colour By Superdetection is selected.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>11. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
@ -1108,8 +1128,8 @@ files.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>13. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
Bug 445. Overlay data in FX spectrogram display gets out of sync with underlying
spectrogram image.</p>
Bug 445. Overlay data in FX spectrogram display gets out of sync with
underlying spectrogram image.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>14. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
@ -1182,9 +1202,9 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
Added a few new options to the Click Detector Sweep Classifier. </p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>10. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
Add option to the Map module's Plot Overlay Options dialog, to show events
occuring in the future (<em><span style='font-family:"Calibri",sans-serif'>look
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
lang=EN-US> </span>Add option to the Map module's Plot Overlay Options dialog,
to show events occuring in the future (<em><span style='font-family:"Calibri",sans-serif'>look
ahead</span></em>) instead of the default display of events which have already
occurred. Can make it easier to match up the map with clicks seen in the Click
Detector display. </p>
@ -1234,8 +1254,9 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
Bug 429. Click Bearings at 180 degrees</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>4. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
Bug 430. Rocca calculates inflection point parameters incorrectly</p>
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
lang=EN-US> </span>Bug 430. Rocca calculates inflection point parameters
incorrectly</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>5. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
@ -1249,8 +1270,8 @@ Bug 432. MySQL database interface - connection problems</p>
<p class=MsoNormal><b><span lang=EN-US>Upgrades</span></b></p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>1. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
New display for Gebco Netcdf bathymetry maps.</p>
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
lang=EN-US> </span>New display for Gebco Netcdf bathymetry maps.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>2. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
@ -1331,8 +1352,8 @@ files.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>12. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Bug 425. Rocca crashing if Click Detector is used as source but the
Click Classifier is not configured properly.</p>
</span>Bug 425. Rocca crashing if Click Detector is used as source but the Click
Classifier is not configured properly.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>13. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@ -1346,9 +1367,9 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
Upgrades to the Group Localiser, including better error estimation.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>2. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
Click Train Detector upgrades, including ability to import time chunks from csv
file for batch processing.</p>
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
lang=EN-US> </span>Click Train Detector upgrades, including ability to import
time chunks from csv file for batch processing.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>3. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
@ -1475,14 +1496,14 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
Updates to the Ishmael module.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>9. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
Added option to the WarnOnce dialog to hide a warning for the current PAMGuard
session, but not forever.</p>
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
lang=EN-US> </span>Added option to the WarnOnce dialog to hide a warning for
the current PAMGuard session, but not forever.</p>
<!-- ************************************************************************************************************************** --><!-- ************************************************************************************************************************** -->
<h1><a name="_Latest_Beta_Version_2.00.14c"></a><span lang=EN-US>Beta Version 2.00.14c
October 2018</span></h1>
<h1><a name="_Latest_Beta_Version_2.00.14c"></a><span lang=EN-US>Beta Version
2.00.14c October 2018</span></h1>
<p class=MsoNormal><span lang=EN-US>PAMGuard Version 2 contains major updates.
You should read and understand the notes listed for <a
@ -1518,10 +1539,10 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
lang=EN-US> </span>Added decimal degrees option to latitude/longitude dialog.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>2. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
Added option in the Click Delay parameters to restrict the number of initial
samples used in the calculation. This can be useful for cleaning up delays in
the presence of echoes and small time delays.</p>
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
lang=EN-US> </span>Added option in the Click Delay parameters to restrict the
number of initial samples used in the calculation. This can be useful for
cleaning up delays in the presence of echoes and small time delays.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>3. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
@ -1589,7 +1610,8 @@ Annotation module which has now been given two text type annotations.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>9. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Bug 391. Click Detector not registering change in multi-threading option.</p>
</span>Bug 391. Click Detector not registering change in multi-threading
option.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>10. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@ -1632,11 +1654,11 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
lang=EN-US> </span>Added ability to read differential GPS data.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>5. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
Added check for duplicate settings in the psf file when exiting Pamguard. If
duplicate settings are found, user is given the option to leave them in the psf
or get rid of them. Duplicate settings are ignored by Pamguard, but can cause
the psf file to grow large over time.</p>
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
lang=EN-US> </span>Added check for duplicate settings in the psf file when
exiting Pamguard. If duplicate settings are found, user is given the option to
leave them in the psf or get rid of them. Duplicate settings are ignored by
Pamguard, but can cause the psf file to grow large over time.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>6. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
@ -1704,8 +1726,8 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>10. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Bug 376. Error when using a serialised data map which spans a period of time
in which Pamguard modules have changed.</p>
</span>Bug 376. Error when using a serialised data map which spans a period of
time in which Pamguard modules have changed.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>11. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@ -1744,8 +1766,9 @@ used in older versions. Older psf files can be loaded with this version, but
will be converted.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>4. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
Many updates to the Video Range module. Will currently only work with landmarks.</p>
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
lang=EN-US> </span>Many updates to the Video Range module. Will currently only
work with landmarks.</p>
<!-- ************************************************************************************************************************** -->
@ -1808,8 +1831,8 @@ Beta versions</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>11. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Bug 366. Rocca manual whistle contour extraction throws error when trying
to classify a boxed whistle</p>
</span>Bug 366. Rocca manual whistle contour extraction throws error when
trying to classify a boxed whistle</p>
<p class=MsoNormal><b><span lang=EN-US>Upgrades</span></b></p>
@ -1878,8 +1901,8 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>10.</span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Bug 354. Whistle Classifier was crashing if user accidentally entered invalid
parameters. Have added diagnostics to prevent this.</p>
</span>Bug 354. Whistle Classifier was crashing if user accidentally entered
invalid parameters. Have added diagnostics to prevent this.</p>
<p class=MsoNormal><b><span lang=EN-US>Upgrades</span></b></p>
@ -2009,8 +2032,8 @@ C:\MySurvey\binarydata_WithUID. </span></p>
<p class=MsoNormal><span lang=EN-US>The additional UID column will be added to
all database tables and populated with unique values. For data which are stored
in both the binary files and in database tables, the same UID’s will be used in
both data stores. </span></p>
in both the binary files and in database tables, the same UIDÃÂs will be used
in both data stores. </span></p>
<h3><span lang=EN-US>New Displays</span></h3>
@ -2024,11 +2047,11 @@ Note that this display is only available if you are running Java 8 or later. </s
<h3><span lang=EN-US>Event Marking and the Detection Group Localiser</span></h3>
<p class=MsoNormal><span lang=EN-US>A new system of event marking which can be used
both online and offline has been added to PAMGuard. Details are in the PAMGuard
help file (Displays/Display Marking). Data can be selected on the Map, the
Spectrogram Display and the new Time Display FX in a similar way and sent to
other PAMGuard modules. The new marking and data selection system works with
<p class=MsoNormal><span lang=EN-US>A new system of event marking which can be
used both online and offline has been added to PAMGuard. Details are in the
PAMGuard help file (Displays/Display Marking). Data can be selected on the Map,
the Spectrogram Display and the new Time Display FX in a similar way and sent
to other PAMGuard modules. The new marking and data selection system works with
the new Detection Group Localiser. The Detection Group Localiser extends the
functionality which always existed in the click detector to other types of data
(e.g. Whistles) so that they can be grouped and tracked using target motion
@ -2146,15 +2169,15 @@ working folder, and therefore is set incorrectly. This has been fixed.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>5.</span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Bug 314. If PAMGuard is started by double-clicking on a psf, nothing
happens when the user selects save as new configuration. This has been fixed.</p>
</span>Bug 314. If PAMGuard is started by double-clicking on a psf, nothing happens
when the user selects save as new configuration. This has been fixed.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>6.</span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Bug 315. code searched for file in working folder, which is the
installation folder when starting PAMGuard using a shortcut link. But when
double-clicking on a psf, the working folder is the location of the psf. This has
been fixed.</p>
double-clicking on a psf, the working folder is the location of the psf. This
has been fixed.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>7.</span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span
@ -2183,8 +2206,8 @@ jar file will be required rather than a new bespoke PAMGuard installation.</span
<p class=MsoNormal><span lang=EN-US>Module code development remains largely
unchanged, in most cases simply requiring the addition of an interface class.
&nbsp;Instructions for the development of new modules utilizing the plug-in scheme
can be found <a href="http://www.pamguard.org/16_HowtomakePlug-Ins.html"
&nbsp;Instructions for the development of new modules utilizing the plug-in
scheme can be found <a href="http://www.pamguard.org/16_HowtomakePlug-Ins.html"
target="_blank">here</a>. &nbsp;Plug-in modules can be downloaded from the
PAMGuard website here, but developers are encouraged to host and maintain their
own modules.</span></p>
@ -2192,8 +2215,8 @@ own modules.</span></p>
<p class=MsoNormal><span lang=EN-US>Modules of interest to the general PAM
community will remain as part of the core PAMGuard installation. However,
specialized modules which are useful to only a small number of users have been
removed and are available as a separate download. The following modules have been
removed:</span></p>
removed and are available as a separate download. The following modules have
been removed:</span></p>
<p class=MsoListParagraph style='margin-left:43.5pt;text-indent:-25.5pt'>1.<span
style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@ -2244,19 +2267,19 @@ November 2016</span></h1>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Bug 303. Some ASIO sound cards not working with either ASIO system in PAMGuard.
For the PAMGuard ASIO system, this was due to a data format used by some sound
cards never being properly implemented. For the “New ASIO system” which is
based on jAsioHost, the unpacking of that format contained a bug which returned
incorrect numbers, so data were swamped with noise. Both systems are now fixed.
By preference, users should use the PAMGuard ASIO system since the JAsioHost
based system seems to drop samples when many channels are running at high
sample rate. </span></p>
cards never being properly implemented. For the ÓNew ASIO systemÔ which
is based on jAsioHost, the unpacking of that format contained a bug which
returned incorrect numbers, so data were swamped with noise. Both systems are
now fixed. By preference, users should use the PAMGuard ASIO system since the
JAsioHost based system seems to drop samples when many channels are running at
high sample rate. </span></p>
<p class=MsoListParagraph style='text-indent:-18.0pt'>2.<span style='font-size-adjust: none;
font-stretch: normal'><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><span lang=EN-US>Bug 305. Date and Time not being correctly
extracted from wav files created using SoundTrap recorders. Fixed by correctly
finding and unpacking information in the accompanying xml log files that come with
SoundTrap files. </span></p>
finding and unpacking information in the accompanying xml log files that come
with SoundTrap files. </span></p>
<h1><a name="_Latest_Version_1.15.06"></a><span lang=EN-US>Version 1.15.06
November 2016</span></h1>
@ -2290,8 +2313,8 @@ data for the least square model. Both fixed. </p>
<p class=MsoListParagraph style='margin-left:40.5pt;text-indent:-22.5pt'>4.<span
style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Bug 294. Click classifier was crashing when the 'min amplitude' option
was used. This is fixed. </p>
</span>Bug 294. Click classifier was crashing when the 'min amplitude' option was
used. This is fixed. </p>
<p class=MsoListParagraph style='margin-left:40.5pt;text-indent:-22.5pt'>5.<span
style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@ -2375,9 +2398,9 @@ the database. </span></p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>2.</span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><span lang=EN-US>The number of data streams associated with the click detector
has been tidied up so that there are a) All Click, b) Tracked Clicks (those
which are part of an event) and c) Events. </span></p>
</span><span lang=EN-US>The number of data streams associated with the click
detector has been tidied up so that there are a) All Click, b) Tracked Clicks
(those which are part of an event) and c) Events. </span></p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>3.</span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@ -2393,9 +2416,9 @@ automatic click train identification and tracking. </span></p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>5.</span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><span lang=EN-US>The automatic click train identification is now using the
same internal structures as the manual tracking, so it's possible to combine
automatic and manual tracking. </span></p>
</span><span lang=EN-US>The automatic click train identification is now using
the same internal structures as the manual tracking, so it's possible to
combine automatic and manual tracking. </span></p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>6.</span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@ -2475,8 +2498,9 @@ today.&nbsp; </p>
<p class=MsoListParagraph style='margin-left:38.25pt;text-indent:-20.25pt'>5.<span
style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Bug 277. Text fields in classifier dialog were not large enough to display
times greater than 10ms. We have increased length of text fields in the dialog.</p>
</span>Bug 277. Text fields in classifier dialog were not large enough to
display times greater than 10ms. We have increased length of text fields in the
dialog.</p>
<p class=MsoListParagraph style='margin-left:38.25pt;text-indent:-20.25pt'>6.<span
style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@ -2494,8 +2518,8 @@ style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&n
</span>Bug 279. GUI Resizing: The whole PAMGuard GUI would suddenly resize to
something very small when a dialog is opened. This has been traced to improper
use of a common dialog component SourcePanel which tries to repack its parent
Window. Some programmers had inadvertently set it to repack the main PAMGuard GUI
instead. This has been Fixed.</p>
Window. Some programmers had inadvertently set it to repack the main PAMGuard
GUI instead. This has been Fixed.</p>
<p class=MsoListParagraph style='margin-left:38.25pt;text-indent:-20.25pt'>8.<span
style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@ -2569,8 +2593,8 @@ and datagram creation.</p>
<h1><a name="_Toc444450394"></a><span lang=EN-US>Version 1.15.00 February 2016</span></h1>
<p class=MsoNormal><span lang=EN-US>Beta Version 1.15.00 64 bit and Core version
1.15.00 32 bit. Both using identical Java core software but linking to
<p class=MsoNormal><span lang=EN-US>Beta Version 1.15.00 64 bit and Core
version 1.15.00 32 bit. Both using identical Java core software but linking to
different libraries for control of sound input devices. </span></p>
<p class=MsoNormal><span lang=EN-US>This is the first release of a 64 bit
@ -2638,12 +2662,12 @@ boundaries when file durations are set to a maximum fixed value. </p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>5.</span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Bug 262. Access to SQLite database conversion. This would fail when tables
were present which were not created by PAMGuard. &nbsp;Fixes have been put in
place for spaces in the table name or for not having an 'Id' column. Fixes have
not been implemented for spaces in a column name or use of a reserved word as a
column name, however if either of these problems do exist it will no longer
crash but issue a clear warning and carry onto the next table.</p>
</span>Bug 262. Access to SQLite database conversion. This would fail when
tables were present which were not created by PAMGuard. &nbsp;Fixes have been
put in place for spaces in the table name or for not having an 'Id' column.
Fixes have not been implemented for spaces in a column name or use of a
reserved word as a column name, however if either of these problems do exist it
will no longer crash but issue a clear warning and carry onto the next table.</p>
<p class=MsoNormal style='margin-left:18.0pt'><span lang=EN-US>&nbsp;</span></p>
@ -2878,8 +2902,8 @@ minutes and seconds. Now correctly displays the number of remaining days. </p>
<p class=MsoListParagraph style='margin-left:47.25pt;text-indent:-29.25pt'><span
lang=EN-US>4.</span><span lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Bug 226. Spectrogram Mark Observer list doesn't refresh when modules added
or removed. </p>
</span>Bug 226. Spectrogram Mark Observer list doesn't refresh when modules
added or removed. </p>
<p class=MsoListParagraph style='margin-left:47.25pt;text-indent:-29.25pt'><span
lang=EN-US>5.</span><span lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@ -3049,12 +3073,11 @@ sonobuoys. See online help for details.&nbsp; </p>
<p class=MsoNormal><i>MEAL Localiser</i> (Localisation Group)</p>
<p class=MsoNormal>This module, developed by Jamie Macaulay of St Andrews
University estimates the 3D localisation of clicks using a variety of
algorithms. It's primarily been developed to track harbour porpoise in three
dimensions over scales of 10's of metres. While currently only working with
output from the click detector, we hope eventually to extend its use to
whistles as well. </p>
<p class=MsoNormal>This module, developed by Jamie Macaulay of St Andrews University
estimates the 3D localisation of clicks using a variety of algorithms. It's
primarily been developed to track harbour porpoise in three dimensions over
scales of 10's of metres. While currently only working with output from the
click detector, we hope eventually to extend its use to whistles as well. </p>
<p class=MsoNormal><i>Accelerometer Readout</i> (Sensors group)</p>
@ -3072,12 +3095,12 @@ marine mammal survey package. See online help for details. </p>
<p class=MsoNormal><i>Alarms</i> (Utilities Group)</p>
<p class=MsoNormal>This is a general system of visual and audio alarms developed
by Doug Gillespie for use on a variety of projects. The alarms can be coupled
to any module or detector in PAMGuard. Where appropriate, modules can control
which of their data will cause an alarm action (e.g. in the Click detector you
can set which types of classified click will fire the alarm). See online help
for details. &nbsp;</p>
<p class=MsoNormal>This is a general system of visual and audio alarms
developed by Doug Gillespie for use on a variety of projects. The alarms can be
coupled to any module or detector in PAMGuard. Where appropriate, modules can
control which of their data will cause an alarm action (e.g. in the Click
detector you can set which types of classified click will fire the alarm). See
online help for details. &nbsp;</p>
<p class=MsoNormal><i>Noise Band Monitor</i> (Sound Processing Group)</p>
@ -3141,8 +3164,8 @@ Millisecond time is also now included in the output file names. </p>
<p class=MsoNormal>Datagram options in Viewer have been improved so that the
user has to verify the time binning for datagrams the first time the viewer is
run and can also change the time bins from the File menu (See the File/BinaryStore/Datagram
options menu. </p>
run and can also change the time bins from the File menu (See the
File/BinaryStore/Datagram options menu. </p>
<p class=MsoNormal><i>Viewer Configuration</i></p>
@ -3164,8 +3187,8 @@ horizon. </p>
<p class=MsoNormal><i>Improved Filter Options</i></p>
<p class=MsoNormal>Filter options (used as stand-alone filter modules and also
within many other modules, such as the click detector and the Filtered Noise
<p class=MsoNormal>Filter options (used as stand-alone filter modules and also within
many other modules, such as the click detector and the Filtered Noise
Measurement module) have been improved so that the user can specify arbitrarily
shaped Finite Impulse Response filters (see online help for details). </p>
@ -3275,9 +3298,9 @@ other data sources for the PAMGuard viewer. </p>
<p class=MsoNormal style='margin-left:36.0pt'><i>Database</i></p>
<p class=MsoNormal style='margin-left:36.0pt'>Can now copy data from binary storage
to the database offline for any module having both binary and database storage.
</p>
<p class=MsoNormal style='margin-left:36.0pt'>Can now copy data from binary
storage to the database offline for any module having both binary and database
storage. </p>
<p class=MsoNormal style='margin-left:36.0pt'>Can create a blank MS Access
database (2007 and later *.accdb formats only).</p>
@ -3376,8 +3399,8 @@ elements has been fixed. </p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span style='font-family:
Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Database Speed: A substantial rewriting of some of the indexing methods in
the database module has led to a significant increase in the speed at which
</span>Database Speed: A substantial rewriting of some of the indexing methods
in the database module has led to a significant increase in the speed at which
data are written to the database (orders of magnitude for large databases).
This is having a significant impact on the overall reliability of the software.
Other changes have increased the speed (again by orders of magnitude) at which
@ -3469,9 +3492,9 @@ Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif
<p class=MsoListParagraph style='text-indent:-18.0pt'><span style='font-family:
Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Offline event marking. Offline event marking similar to functionality in
RainbowClick is now available in the PAMGUARD viewer. Event summary data is stored
in the database and can also be exported to text files (e.g. for importing into
the Distance software).&nbsp; </p>
RainbowClick is now available in the PAMGUARD viewer. Event summary data is
stored in the database and can also be exported to text files (e.g. for
importing into the Distance software).&nbsp; </p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span style='font-family:
Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@ -3506,8 +3529,8 @@ features of the display:</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span style='font-family:
Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>The spectrogram will automatically generate and display spectrogram
data. </p>
</span>The spectrogram will automatically generate and display spectrogram data.
</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span style='font-family:
Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@ -3578,8 +3601,8 @@ the correct data stream. This has been fixed. </p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span style='font-family:
Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Whistle classifier has some new features in the classifier training
panel. It is also now possible to export training data files directly from binary
data files. </p>
panel. It is also now possible to export training data files directly from
binary data files. </p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span style='font-family:
Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@ -3618,10 +3641,10 @@ Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif
<p class=MsoNormal>2. Improved offline viewer functionality. </p>
<p class=MsoNormal>The offline viewer is much improved with better data scrolling
and the ability to view data either stored in the database or the binary
storage system. Work has stated on functions which read and use data stored in
audio files. This is currently limited to re-calculating and displaying
<p class=MsoNormal>The offline viewer is much improved with better data
scrolling and the ability to view data either stored in the database or the
binary storage system. Work has stated on functions which read and use data
stored in audio files. This is currently limited to re-calculating and displaying
displaying spectrogram data during viewer mode operation.&nbsp; </p>
<p class=MsoNormal>3. Heading sensor readout</p>
@ -3696,14 +3719,14 @@ lookup tables relating hardware channel numbers to internal channel numbers.
0 and 1 from a normal sound card or a list of channels 0,1,2,3, etc from an
ASIO card or National Instruments card. However, when using the ASIO sound
acquisition system, it is possible to read out hardware channels 2,3,4,5 say
and those numbers would propagate through PAMGUARD and be used by all the
detectors. While this gave some clarity to&nbsp; the displays, it also created
a number of problems since look up tables were constantly required to relate
hardware numbers and software numbers in every PAMGUARD module. Since this type
of channel numbering was only implemented several years into the PAMGUARD
project, it was never fully implemented or well supported by the different
modules which resulted in a number of bugs which could cause confusion as to
which hydrophones were being used during localisation or during calibrated
and those numbers would propagate through PAMGUARD and be used by all the detectors.
While this gave some clarity to&nbsp; the displays, it also created a number of
problems since look up tables were constantly required to relate hardware
numbers and software numbers in every PAMGUARD module. Since this type of
channel numbering was only implemented several years into the PAMGUARD project,
it was never fully implemented or well supported by the different modules which
resulted in a number of bugs which could cause confusion as to which
hydrophones were being used during localisation or during calibrated
measurement. The situation tended to only arise with a small number of ASIO
sound cards such as the RME Fireface 400 on which the most useful inputs, the
balanced line inputs, are hardware channels 4,5,6 and 7 on the back of the
@ -3718,10 +3741,10 @@ re-label those channels 0,1,2,3. </p>
<p class=MsoNormal>There have been other annoyances with the ASIO channel
numbering scheme. For instance, if you had a configuration which worked in real
time using channels 7 and 8 of a sound card, you could not use that same
configuration to analyse wav files, which would always read their data as
channels 0 and 1. Similarly if you switched sound cards, you may have to
reconfigure every detector and several of the displays to handle the changes in
channel numbering. </p>
configuration to analyse wav files, which would always read their data as channels
0 and 1. Similarly if you switched sound cards, you may have to reconfigure
every detector and several of the displays to handle the changes in channel
numbering. </p>
<p class=MsoNormal>I have spent a considerable amount of time trying to work
out a better system for handling channel numbering in PAMGUARD and have decided
@ -3832,10 +3855,10 @@ port is closed. Might prevent a few problems when using a GPS. </p>
<p class=MsoNormal>Crashes caused in real time or Mixed Mode if the number of
software channels exceeds the number of hydrophones configured in the array
manager. It is of course illogical to have software channels which are not
assigned to a hydrophone, so rather than entirely prevent PAMGUARD from crashing
I have inserted additional checks into the hydrophone array dialog which will
prevent the user from closing that dialog unless all software channels are
assigned to a hydrophone. </p>
assigned to a hydrophone, so rather than entirely prevent PAMGUARD from
crashing I have inserted additional checks into the hydrophone array dialog
which will prevent the user from closing that dialog unless all software
channels are assigned to a hydrophone. </p>
<h2><span style='font-weight:normal'>Version 1.8.01 Beta February 2010</span></h2>
@ -3917,10 +3940,10 @@ synchronisation.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span style='font-family:
Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Wigner time-frequency plot for the click detector. Clicks are NOT
automatically displayed in the Winger window as they are for the waveform and
spectrum windows since the Wigner transformation is very time consuming. Clicks
will be displayed if you select them with the mouse.</p>
</span>Wigner time-frequency plot for the click detector. Clicks are NOT automatically
displayed in the Winger window as they are for the waveform and spectrum
windows since the Wigner transformation is very time consuming. Clicks will be
displayed if you select them with the mouse.</p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span style='font-family:
Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@ -3932,15 +3955,15 @@ classifier is still available). </p>
Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>Bearing ambiguity resolution for planar and volumetric arrays. New
features in array dialog for estimations of errors on array location. These
feed into to a maximum likelihood estimate of angles from small 2D or 3D sub arrays
to give two polar angle coordinates. this can be used to resolve left right
ambiguity and is implemented for both the click and the whistle/moan detectors.
As a result, the click detector bearing time display can now be set to go from
-180 to 180 degrees rather than 0 - 180 degrees. In this case, clicks in the
upper half of the bearing display will be to port and clicks in the right half
will be to starboard. As you pass a whale which is to port, the clicks will
move UP the display. In the long term, I hope to turn this display around so
that time is up the screen rather than across.&nbsp; </p>
feed into to a maximum likelihood estimate of angles from small 2D or 3D sub
arrays to give two polar angle coordinates. this can be used to resolve left
right ambiguity and is implemented for both the click and the whistle/moan
detectors. As a result, the click detector bearing time display can now be set
to go from -180 to 180 degrees rather than 0 - 180 degrees. In this case,
clicks in the upper half of the bearing display will be to port and clicks in
the right half will be to starboard. As you pass a whale which is to port, the
clicks will move UP the display. In the long term, I hope to turn this display
around so that time is up the screen rather than across.&nbsp; </p>
<p class=MsoNormal><b>Small features and bug fixes</b></p>
@ -4135,10 +4158,10 @@ help pages</p>
<p class=MsoNormal><b>Bug Fixes</b></p>
<p class=MsoNormal>Memory leak caused by Night / Day colour manager now fixed. This
would cause memory leaks when multiple files were being analysed off-line and
would eventually crash PAMGUARD. The way that colours are managed in PAMGUARD
has been rewritten.&nbsp; </p>
<p class=MsoNormal>Memory leak caused by Night / Day colour manager now fixed.
This would cause memory leaks when multiple files were being analysed off-line
and would eventually crash PAMGUARD. The way that colours are managed in
PAMGUARD has been rewritten.&nbsp; </p>
<p class=MsoNormal>Some issues with Swing fixed that might have been causing
hang ups on startup especially on Macs/Linux machines</p>
@ -4151,9 +4174,9 @@ Mac/Linux machines)</p>
<p class=MsoNormal>Parameters dialog shows correct channel numbers</p>
<p class=MsoNormal>Click classifier mean filter option had a computational
error which meant that classifiers using this option would not work. This has
now been fixed. </p>
<p class=MsoNormal>Click classifier mean filter option had a computational error
which meant that classifiers using this option would not work. This has now
been fixed. </p>
<p class=MsoNormal><b>Sound Recorder</b></p>
@ -4209,8 +4232,8 @@ file)</p>
<p class=MsoNormal><b>Changes</b></p>
<p class=MsoNormal>The User Input module (for text entry of information by the user)
has been moved from the Displays sub menu of the Add Modules menu, to
<p class=MsoNormal>The User Input module (for text entry of information by the
user) has been moved from the Displays sub menu of the Add Modules menu, to
Utilities. This will not affect how existing settings files are loaded. </p>
<p class=MsoNormal><b>Multi-screen environments.</b></p>
@ -4229,8 +4252,8 @@ acquisition.&nbsp; </p>
<p class=MsoNormal><b>Bug fixes</b></p>
<p class=MsoNormal>Speed up of graphics, particularly regarding large quantities
of gps track &nbsp;data</p>
<p class=MsoNormal>Speed up of graphics, particularly regarding large
quantities of gps track &nbsp;data</p>
<p class=MsoNormal>National Instruments cards with names &gt; 20 characters
long are now correctly &nbsp;recognised. </p>
@ -4713,12 +4736,12 @@ and Ishmael-type detectors and localisers. </p>
<p class=MsoNormal>Information from above modules can be displayed on
configurable user displays which support real time scrolling spectrograms and
radar displays. Detection and localisation information can be optionally
displayed on the map display.Map enhancements include improved scrolling whereby
the user can click and drag to pan the area. PamGuard can now interface with
MySQL database servers and users can easily select which information is logged.
(This replaces the previous 'flat-file' logging feature). A simulation module
allows virtual vocalising animals to be placed on the map to assist in training
and development. Extensive online user help has been added to PamGuard
displayed on the map display.Map enhancements include improved scrolling
whereby the user can click and drag to pan the area. PamGuard can now interface
with MySQL database servers and users can easily select which information is
logged. (This replaces the previous 'flat-file' logging feature). A simulation
module allows virtual vocalising animals to be placed on the map to assist in
training and development. Extensive online user help has been added to PamGuard
Application</p>
<h2>0.03b - first version used in a real 'at sea' environment.18/08/06</h2>

View File

@ -780,12 +780,12 @@
</dependency>
-->
<!-- not in Maven repository -->
<!-- not in Maven repository -->
<dependency>
<groupId>pamguard.org</groupId>
<artifactId>x3</artifactId>
<version>2.1.0</version>
</dependency>
<version>2.2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/it.sauronsoftware/jave -->
<dependency>

View File

@ -0,0 +1,4 @@
#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
#Fri Nov 11 13:13:18 GMT 2022
x3-2.2.0.jar>=
x3-2.2.0.pom>=

Binary file not shown.

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>pamguard.org</groupId>
<artifactId>x3</artifactId>
<version>2.2.0</version>
<description>POM was created from install:install-file</description>
</project>

View File

@ -38,6 +38,9 @@ import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.SwingConstants;
import org.pamguard.x3.sud.Chunk;
import org.pamguard.x3.sud.SudFileListener;
import dataGram.DatagramManager;
import dataMap.OfflineDataMapPoint;
import dataMap.filemaps.OfflineFileServer;
@ -49,12 +52,13 @@ import simulatedAcquisition.SimProcess;
import asiojni.ASIOSoundSystem;
import asiojni.NewAsioSoundSystem;
import nidaqdev.NIDAQProcess;
import nidaqdev.networkdaq.NINetworkDaq;
import Acquisition.filedate.FileDate;
import Acquisition.filedate.StandardFileDate;
import Acquisition.filetypes.SoundFileTypes;
import Acquisition.layoutFX.AquisitionGUIFX;
import Acquisition.offlineFuncs.OfflineWavFileServer;
import Acquisition.rona.RonaOfflineFileServer;
import Acquisition.sud.SUDNotificationManager;
import Array.ArrayManager;
import Array.PamArray;
import Array.Preamplifier;
@ -132,7 +136,10 @@ public class AcquisitionControl extends PamControlledUnit implements PamSettings
* The JavaFX GUI for the sound acquisition module.
*/
private AquisitionGUIFX aquisitionGUIFX;
private SUDNotificationManager sudNotificationManager;
protected SoundFileTypes soundFileTypes;
/**
* Main control unit for audio data acquisition.
@ -158,6 +165,8 @@ public class AcquisitionControl extends PamControlledUnit implements PamSettings
pamController = PamController.getInstance();
soundFileTypes = new SoundFileTypes(this);
registerDaqSystem(new SoundCardSystem(this));
if (PlatformInfo.calculateOS() == OSType.WINDOWS) {
registerDaqSystem(new ASIOSoundSystem(this));
@ -833,5 +842,16 @@ public class AcquisitionControl extends PamControlledUnit implements PamSettings
public String getModuleSummary(boolean clear) {
return getDaqProcess().getRawDataBlock().getSummaryString(clear);
}
/**
* Get the SUD processing notification manager.
* @return SUD processing notification manager.
*/
public SUDNotificationManager getSUDNotificationManager() {
if (sudNotificationManager == null) {
sudNotificationManager = new SUDNotificationManager();
}
return sudNotificationManager;
}
}

View File

@ -33,23 +33,23 @@ public class AcquisitionLogging extends SQLLogging {
this.acquisitionControl = acquisitionControl;
tableDef = new PamTableDefinition(pamDataBlock.getDataName(), UPDATE_POLICY_OVERWRITE);
tableDef.addTableItem(adcClockTime = new PamTableItem("ADC Clock", Types.TIMESTAMP));
tableDef.addTableItem(adcClockMillis = new PamTableItem("ADC Clock millis", Types.INTEGER));
tableDef.addTableItem(rawADCTime = new PamTableItem("RAW ADC Clock", Types.TIMESTAMP));
tableDef.addTableItem(gSamples = new PamTableItem("GigaSamples", Types.INTEGER));
tableDef.addTableItem(samples = new PamTableItem("Samples", Types.INTEGER));
tableDef.addTableItem(GPSPPSTime = new PamTableItem("GPSPPSTime", Types.TIMESTAMP));
tableDef.addTableItem(status = new PamTableItem("Status", Types.CHAR, 20));
tableDef.addTableItem(reason = new PamTableItem("Reason", Types.CHAR, 50));
tableDef.addTableItem(daqSystemType = new PamTableItem("SystemType", Types.CHAR, 50));
tableDef.addTableItem(daqSystemName = new PamTableItem("SystemName", Types.CHAR, 50));
tableDef.addTableItem(sampleRate = new PamTableItem("sampleRate", Types.INTEGER));
tableDef.addTableItem(nChannels = new PamTableItem("nChannels", Types.INTEGER));
tableDef.addTableItem(voltsPeak2Peak = new PamTableItem("voltsPeak2Peak", Types.DOUBLE));
tableDef.addTableItem(gain = new PamTableItem("gain", Types.REAL));
tableDef.addTableItem(duration = new PamTableItem("duration", Types.DOUBLE));
tableDef.addTableItem(clockError = new PamTableItem("clockError", Types.DOUBLE));
tableDef.addTableItem(serverTime = new PamTableItem("Server Time", Types.TIMESTAMP));
tableDef.addTableItem(adcClockTime = new PamTableItem("ADC Clock", Types.TIMESTAMP, "Time based on PC clock and samples since last PC clock read"));
tableDef.addTableItem(adcClockMillis = new PamTableItem("ADC Clock millis", Types.INTEGER, "Millis for adcClockTime if not supported by database"));
tableDef.addTableItem(rawADCTime = new PamTableItem("RAW ADC Clock", Types.TIMESTAMP, "Time based on start time and number of samples acquired"));
tableDef.addTableItem(gSamples = new PamTableItem("GigaSamples", Types.INTEGER, "Billions of samples. Add this*1e9 to samples"));
tableDef.addTableItem(samples = new PamTableItem("Samples", Types.INTEGER, "Samples. Add this to GigaSamples*1e9"));
tableDef.addTableItem(GPSPPSTime = new PamTableItem("GPSPPSTime", Types.TIMESTAMP, "Time derived from a GPS with PPS output"));
tableDef.addTableItem(status = new PamTableItem("Status", Types.CHAR, 20, "Acquisition Status: 'Start', 'Stop', 'Continue'"));
tableDef.addTableItem(reason = new PamTableItem("Reason", Types.CHAR, 50, "Reason for status change"));
tableDef.addTableItem(daqSystemType = new PamTableItem("SystemType", Types.CHAR, 50, "Type of acquisition system"));
tableDef.addTableItem(daqSystemName = new PamTableItem("SystemName", Types.CHAR, 50, "Specific acquistision system"));
tableDef.addTableItem(sampleRate = new PamTableItem("sampleRate", Types.INTEGER, "Sample rate (samples per second)"));
tableDef.addTableItem(nChannels = new PamTableItem("nChannels", Types.INTEGER, "Total number of channels"));
tableDef.addTableItem(voltsPeak2Peak = new PamTableItem("voltsPeak2Peak", Types.DOUBLE, "Peak to peak input voltage of ADC"));
tableDef.addTableItem(gain = new PamTableItem("gain", Types.REAL, "Additional amplifier gain"));
tableDef.addTableItem(duration = new PamTableItem("duration", Types.DOUBLE, "Time since start in seconds"));
tableDef.addTableItem(clockError = new PamTableItem("clockError", Types.DOUBLE, "Clock error in milliseconds"));
tableDef.addTableItem(serverTime = new PamTableItem("Server Time", Types.TIMESTAMP, "Time taken from an Internet time server"));
setTableDefinition(tableDef);
}

View File

@ -254,9 +254,11 @@ public class AcquisitionProcess extends PamProcess {
bufferOverflow = false;
// daqCheckTime = PamCalendar.getTimeInMillis();
Timer t = new Timer(1, new ReallyStart());
t.setRepeats(false);
t.start();
if (!netRX) {
Timer t = new Timer(1, new ReallyStart());
t.setRepeats(false);
t.start();
}
}
private boolean addServerTime(DaqStatusDataUnit daqStatusDataUnit) {

View File

@ -7,6 +7,8 @@ import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@ -14,6 +16,8 @@ import java.io.IOException;
import java.io.Serializable;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.List;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.UnsupportedAudioFileException;
@ -31,6 +35,10 @@ import javax.swing.border.TitledBorder;
import org.jflac.FLACDecoder;
import org.jflac.frame.Frame;
import org.jflac.util.ByteData;
import org.pamguard.x3.sud.Chunk;
import org.pamguard.x3.sud.SudAudioInputStream;
import org.pamguard.x3.sud.SudFileListener;
import org.pamguard.x3.sud.SudParams;
import org.jflac.PCMProcessor;
import org.jflac.metadata.StreamInfo;
import org.jflac.sound.spi.FlacEncoding;
@ -47,15 +55,14 @@ import wavFiles.ByteConverter;
import Acquisition.filedate.FileDate;
import Acquisition.filedate.FileDateDialogStrip;
import Acquisition.filedate.FileDateObserver;
import Acquisition.filetypes.SoundFileType;
import Acquisition.pamAudio.PamAudioFileManager;
import Acquisition.pamAudio.PamAudioFileFilter;
import Acquisition.pamAudio.PamAudioSystem;
import PamController.PamControlledUnitSettings;
import PamController.PamController;
import PamController.PamSettingManager;
import PamController.PamSettings;
import PamDetection.RawDataUnit;
import PamModel.SMRUEnable;
import PamUtils.PamCalendar;
import PamUtils.PamFileChooser;
import PamView.dialog.PamLabel;
@ -140,6 +147,11 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
protected ByteConverter byteConverter;
protected FileDateDialogStrip fileDateStrip;
/**
* Sound file types present in the current selections.
*/
private List<SoundFileType> selectedFileTypes;
/**
* Text field for skipping initial few seconds of a file.
@ -151,6 +163,9 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
*/
private PamWarning fileWarning;
private SudAudioInputStream sudAudioInputStream;
private SudListener sudListener;
public FileInputSystem(AcquisitionControl acquisitionControl) {
this.acquisitionControl = acquisitionControl;
@ -177,7 +192,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
}
return daqDialog;
}
protected JPanel createDaqDialogPanel() {
JPanel p = new JPanel();
@ -216,18 +231,18 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
fileDateStrip.addObserver(this);
p.add(fileDateStrip.getDialogComponent(), constraints);
// if (SMRUEnable.isEnable()) {
// if (SMRUEnable.isEnable()) {
// no reason to hide this option from users.
constraints.gridy++;
constraints.gridx = 0;
constraints.gridwidth = 1;
addComponent(p, new JLabel("Skip initial"), constraints);
constraints.gridx++;
addComponent(p, skipSecondsField = new JTextField(4), constraints);
constraints.gridx++;
addComponent(p, new JLabel("seconds"), constraints);
constraints.anchor = GridBagConstraints.EAST;
// }
constraints.gridy++;
constraints.gridx = 0;
constraints.gridwidth = 1;
addComponent(p, new JLabel("Skip initial"), constraints);
constraints.gridx++;
addComponent(p, skipSecondsField = new JTextField(4), constraints);
constraints.gridx++;
addComponent(p, new JLabel("seconds"), constraints);
constraints.anchor = GridBagConstraints.EAST;
// }
// addComponent(p, new JLabel("File date :"), constraints);
// constraints.gridx++;
@ -251,7 +266,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
// would hold a null. The system type is used by the getParameterSet method to decide
// whether or not to include the parameters in the XML output
if (fileInputParameters.systemType==null) fileInputParameters.systemType=getSystemType();
fillFileList();
if (repeat != null) {
@ -289,7 +304,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
fileInputParameters.recentFiles.trimToSize();
}
}
if (repeat == null) {
fileInputParameters.repeatLoop = false;
}
@ -306,7 +321,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
return false;
}
}
return true;
}
@ -337,7 +352,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
protected void selectFile() {
//IshmaelDetector.MatchFiltParamsDialog copies a bunch of this. If you
//modifiy this, please check that too.
String currFile = (String) fileNameCombo.getSelectedItem();
// seems to just support aif and wav files at the moment
// Type[] audioTypes = AudioSystem.getAudioFileTypes();
@ -393,6 +408,9 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
if (newFile.length() == 0) return;
File file = new File(newFile);
setSelectedFileTypes(acquisitionControl.soundFileTypes.getUsedTypes(file));
if (file == null) return;
// try to work out the date of the file
@ -421,6 +439,10 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
// }
// }
if (audioStream instanceof SudAudioInputStream) {
acquisitionControl.getSUDNotificationManager().interpretNewFile(newFile, (SudAudioInputStream) audioStream);
}
AudioFormat audioFormat = audioStream.getFormat();
// fileLength = file.length();
fileSamples = audioStream.getFrameLength();
@ -477,7 +499,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
public long getSkipStartFileTime() {
return fileInputParameters.skipStartFileTime;
}
@Override
public boolean canPlayBack(float sampleRate) {
// TODO Auto-generated method stub
@ -538,7 +560,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
}
public File getCurrentFile() {
System.out.println("fileInputParameters: " + fileInputParameters);
// System.out.println("fileInputParameters: " + fileInputParameters);
if (fileInputParameters.recentFiles == null) return null;
if (fileInputParameters.recentFiles.size() < 1) return null;
String fileName = fileInputParameters.recentFiles.get(0);
@ -565,7 +587,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
System.out.println("The current file was null");
return false;
}
System.out.printf("*********************************** Opening file %s\n", currentFile.getName());
// System.out.printf("*********************************** Opening file %s\n", currentFile.getName());
try {
@ -575,12 +597,25 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
audioStream = PamAudioFileManager.getInstance().getAudioInputStream(currentFile);
if (audioStream instanceof SudAudioInputStream) {
sudAudioInputStream = (SudAudioInputStream) audioStream;
if (sudListener == null) {
sudListener = new SudListener();
}
sudAudioInputStream.addSudFileListener(sudListener);
// sudAudioInputStream.ad
acquisitionControl.getSUDNotificationManager().newSudInputStream(sudAudioInputStream);
}
else {
sudAudioInputStream = null;
}
if (audioStream == null) {
return false;
}
audioFormat = audioStream.getFormat();
if (audioFormat==null) {
System.err.println("AudioFormat was null: " + currentFile.getAbsolutePath());
return false;
@ -592,7 +627,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
acquisitionControl.getAcquisitionProcess().setSampleRate(audioFormat.getSampleRate(), true);
fileInputParameters.bitDepth = audioFormat.getSampleSizeInBits();
loadByteConverter(audioFormat);
} catch (UnsupportedAudioFileException ex) {
@ -608,18 +643,27 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
return true;
}
private class SudListener implements SudFileListener {
@Override
public void chunkProcessed(int chunkID, Chunk sudChunk) {
acquisitionControl.getSUDNotificationManager().chunkProcessed(chunkID, sudChunk);
}
}
public boolean runFileAnalysis() {
// keep a reference to where data will be put.
this.newDataUnits = acquisitionControl.getDaqProcess().getNewDataQueue();
// if (this.newDataUnits == null) {
// System.err.println("newDataUnits: == null: ");
// return false;
// }
// if (this.newDataUnits == null) {
// System.err.println("newDataUnits: == null: ");
// return false;
// }
if (!prepareInputFile() && getCurrentFile()!=null) {
String audioFileStr = getCurrentFile()==null? "Null File": getCurrentFile().getAbsolutePath();
String title = "Error loading audio file";
String msg = "<html><p>There was an error trying to access the audio file </p><b> " +
@ -647,14 +691,14 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
this.startTimeMS = PamCalendar.getTimeInMillis();
if (audioFormat==null) {
String audioFileStr = getCurrentFile()==null? "Null File": getCurrentFile().getAbsolutePath();
System.err.println("FileInputSystem: runFileAnalysis: AudioFile format is null: " + audioFileStr);
return false;
}
nChannels = audioFormat.getChannels();
acquisitionControl.getDaqProcess().setSampleRate(sampleRate = audioFormat.getSampleRate(), true);
@ -997,6 +1041,9 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
}
}
if (audioStream != null) {
if (audioStream instanceof SudAudioInputStream) {
acquisitionControl.getSUDNotificationManager().sudStreamClosed();
}
try {
audioStream.close();
audioStream = null;
@ -1124,7 +1171,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
}
public void sayEta(long timeMs) {
if (etaLabel==null) return;
if (timeMs < 0) {
@ -1186,4 +1233,27 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
getDialogPanel();
}
}
/**
* @return the selectedFileTypes
*/
public List<SoundFileType> getSelectedFileTypes() {
return selectedFileTypes;
}
/**
* Called when the file or file list selection is changes and finds a list of all
* sound file types included in the selection. this is only implemented for SUD files
* at the moment, the idea being to offer some additional functionality.
* @param selectedFileTypes the selectedFileTypes to set
*/
public void setSelectedFileTypes(List<SoundFileType> selectedFileTypes) {
this.selectedFileTypes = selectedFileTypes;
if (selectedFileTypes == null) {
return;
}
for (SoundFileType aType : selectedFileTypes) {
aType.selected(this);
}
}
}

View File

@ -10,6 +10,8 @@ import java.awt.event.ActionListener;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.swing.BoxLayout;
@ -494,6 +496,9 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings{
// System.out.printf("Wav list recieved with %d files after %d millis\n",
// fileListData.getFileCount(), System.currentTimeMillis() - wavListStart);
allFiles = fileListData.getListCopy();
List<WavFileType> asList = allFiles;
setSelectedFileTypes(acquisitionControl.soundFileTypes.getUsedTypes(allFiles));
setFileDateText();
// also open up the first file and get the sample rate and number of channels from it

View File

@ -13,6 +13,7 @@ import java.util.TimeZone;
import Acquisition.KETime;
import Acquisition.layoutFX.FileDatePane;
import Acquisition.layoutFX.StandardFileDatePane;
import Acquisition.sud.SUDFileTime;
import PamController.PamControlledUnitSettings;
import PamController.PamSettingManager;
import PamController.PamSettings;
@ -157,6 +158,11 @@ public class StandardFileDate implements FileDate, PamSettings {
if (settings.isUseBespokeFormat() && settings.getForcedDateFormat() != null) {
return forcedDataFormat(file, settings.getForcedDateFormat());
}
long sudTime = SUDFileTime.getSUDFileTime(file);
if (sudTime != Long.MIN_VALUE) {
return sudTime;
}
/*
* Dtag files have an accompanying XML file which
@ -168,6 +174,7 @@ public class StandardFileDate implements FileDate, PamSettings {
setLastFormat("D3 time from xml file");
return dTagTime;
}
long stTime = SoundTrapTime.getSoundTrapTime(file, settings.getDateTimeFormatToUse());
if (stTime != Long.MIN_VALUE) {

View File

@ -0,0 +1,29 @@
package Acquisition.filetypes;
import Acquisition.FileInputSystem;
import PamView.dialog.warn.WarnOnce;
public class SUDFileType extends SoundFileType {
private boolean isShown = false;
private String sudInfoText = "<html>There are SoundTrap SUD files in your selection. PAMGuard can now process data from these " +
"directly with no need to unpack them into WAV files. " +
"<p>If the SoundTrap was running with the click detector, then you should add a SoundTrap Click Detector module" +
" and detected clicks will automatically be extracted to binary files while processing the wav data." +
"<p>See the Click Detector help for further details";
public SUDFileType() {
super(".sud");
}
@Override
public void selected(FileInputSystem fileInputSystem) {
if (isShown) {
return;
}
WarnOnce.showWarning("SoundTrap SUD Files", sudInfoText, WarnOnce.OK_OPTION);
isShown = true;
}
}

View File

@ -0,0 +1,65 @@
package Acquisition.filetypes;
import java.io.File;
import java.util.List;
import Acquisition.FileInputSystem;
import Acquisition.pamAudio.PamAudioFileFilter;
import PamUtils.worker.filelist.WavFileType;
/**
* Some functions for the File and Folder input systems to give a bit of
* extra functionality / help for different file types. Primarily introduced
* to give a couple of extras for sud files.
* @author dg50
*
*/
public abstract class SoundFileType {
private String fileType;
private PamAudioFileFilter fileFilter = new PamAudioFileFilter();
public SoundFileType(String fileType) {
this.fileType = fileType.toLowerCase();
}
/**
* Work out if any files of this type are included in the current selection.
* @param fileOrFolder this for a single file.
* @param includeSubfolders used with folders.
* @return true if any exist.
*/
public boolean isFileType(File oneFile) {
if (oneFile == null) {
return false;
}
if (oneFile.isFile()) {
return oneFile.getName().toLowerCase().endsWith(fileType);
}
return false;
}
/**
* Work out if any files of this type are included in the current selection.
* @param fileOrFolder this for a single file.
* @param includeSubfolders used with folders.
* @return true if any exist.
*/
public boolean hasFileType(List<WavFileType> files) {
if (files == null) {
return false;
}
for (File aFile : files) {
if (isFileType(aFile)) {
return true;
}
}
return false;
}
public abstract void selected(FileInputSystem fileInputSystem);
}

View File

@ -0,0 +1,74 @@
package Acquisition.filetypes;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import Acquisition.AcquisitionControl;
import PamUtils.worker.filelist.WavFileType;
/**
* List of SoundFileType objects.
* @author dg50
*
*/
public class SoundFileTypes {
private AcquisitionControl acquisitionControl;
private ArrayList<SoundFileType> availableTypes = new ArrayList<>();
public SoundFileTypes(AcquisitionControl acquisitionControl) {
this.acquisitionControl = acquisitionControl;
availableTypes.add(new SUDFileType());
}
/**
* Get a list of used file types. Reaslistically this
* can only return one value.
* @param aFile
* @return
*/
public SoundFileType getFileType(File aFile) {
ArrayList<SoundFileType> usedTypes = new ArrayList<>();
for (SoundFileType aType : availableTypes) {
if (aType.isFileType(aFile)) {
return aType;
}
}
return null;
}
/**
* Get a list of used file types. Realistically this
* can only return one value but possibly it's useful to have it in the same
* format as the multiple file version. .
* @param aFile
* @return
*/
public List<SoundFileType> getUsedTypes(File aFile) {
ArrayList<SoundFileType> usedTypes = new ArrayList<>();
for (SoundFileType aType : availableTypes) {
if (aType.isFileType(aFile)) {
usedTypes.add(aType);
}
}
return usedTypes;
}
/**
* Get a list of used file types for the folder Input System.
* @param aFile
* @return
*/
public List<SoundFileType> getUsedTypes(List<WavFileType> aFile) {
ArrayList<SoundFileType> usedTypes = new ArrayList<>();
for (SoundFileType aType : availableTypes) {
if (aType.hasFileType(aFile)) {
usedTypes.add(aType);
}
}
return usedTypes;
}
}

View File

@ -109,7 +109,7 @@ public class PamAudioFileManager {
AudioInputStream stream = null;
for (int i = 0; i < pamAudioFileTypes.size(); i++) {
System.out.println(file.getName() + " " + pamAudioFileTypes.get(i).getName());
// System.out.println(file.getName() + " " + pamAudioFileTypes.get(i).getName());
if (isExtension(file, pamAudioFileTypes.get(i))) {
//System.out.println("Get stream for: " +pamAudioFileTypes.get(i).getName());
stream = pamAudioFileTypes.get(i).getAudioStream(file);

View File

@ -0,0 +1,86 @@
package Acquisition.sud;
import java.io.File;
import org.pamguard.x3.sud.ChunkHeader;
import org.pamguard.x3.sud.SudAudioInputStream;
import org.pamguard.x3.sud.SudFileMap;
import org.pamguard.x3.sud.SudParams;
import PamUtils.PamCalendar;
public class SUDFileTime {
private static long sudTime;
private static String lastFilePath = "";
/**
* Temp measure to get the time from the first available sud record.
* @param file
* @return
*/
public static long getSUDFileTime(File file) {
if (file == null || file.exists() == false) {
return Long.MIN_VALUE;
}
if (file.getName().toLowerCase().endsWith(".sud") == false) {
return Long.MIN_VALUE;
}
String filePath = file.getAbsolutePath();
if (filePath.equals(lastFilePath)) {
return sudTime;
}
/**
* Open the sud file and read it until the first chunk arrive, get the time
* from there and close it again. I don't really see another way.
*/
// long t1 = System.currentTimeMillis();
sudTime = Long.MIN_VALUE;
SudParams sudParams = new SudParams();
sudParams.saveMeta = false;
sudParams.saveWav = false;
try {
SudAudioInputStream sudAudioInputStream = SudAudioInputStream.openInputStream(file, sudParams, false);
if (sudAudioInputStream == null) {
return Long.MIN_VALUE;
}
SudFileMap sudMap = sudAudioInputStream.getSudMap();
if (sudMap == null) {
return Long.MIN_VALUE;
}
long t = sudMap.getFirstChunkTimeMillis();
if (t != 0) {
sudTime = t;
}
// sudAudioInputStream.addSudFileListener((chunkID, sudChunk)->{
// ChunkHeader chunkHead = sudChunk.chunkHeader;
// if (chunkHead == null || sudTime != Long.MIN_VALUE) {
// return;
// }
// long millis = (long) chunkHead.TimeS*1000 + (long) chunkHead.TimeOffsetUs/1000;
// if (millis > 0) {
// sudTime = millis;
// lastFilePath = filePath;
// }
// });
//
// while (sudAudioInputStream.available() > 0 && sudTime == Long.MIN_VALUE) {
//
// //note this is reading bytes of uncompressed continuous recordings only.
// sudAudioInputStream.read();
// }
//
sudAudioInputStream.close();
// long t2 = System.currentTimeMillis();
// System.out.printf("SUD file time %s extracted in %d milliseconds\n", PamCalendar.formatDBDateTime(sudTime), t2-t1);
} catch (Exception e) {
System.err.println("Error getting time from SUD file: " + e.getMessage());
}
return sudTime;
}
}

View File

@ -0,0 +1,36 @@
package Acquisition.sud;
import org.pamguard.x3.sud.Chunk;
import org.pamguard.x3.sud.SudAudioInputStream;
import org.pamguard.x3.sud.SudFileListener;
import org.pamguard.x3.sud.SudProgressListener;
public interface SUDNotificationHandler extends SudFileListener, SudProgressListener {
/**
* A new SUD file input stream has been opened.
* @param sudAudioInputStream
*/
public void newSudInputStream(SudAudioInputStream sudAudioInputStream);
/**
* SUD stream has closed.
*/
public void sudStreamClosed();
@Override
public void progress(double arg0, int arg1, int arg2);
@Override
public void chunkProcessed(int chunkId, Chunk sudChunk);
/**
* Notification that a new file or folder is selected. This is called when a file
* or folder is selected in the dialog, NOT when acquisition starts, so is a good
* opportunity for the SUD Click Detector to work out channel maps and sample rates.
* @param newFile
* @param sudAudioStream
*/
public void interpretNewFile(String newFile, SudAudioInputStream sudAudioStream);
}

View File

@ -0,0 +1,66 @@
package Acquisition.sud;
import java.util.ArrayList;
import org.pamguard.x3.sud.Chunk;
import org.pamguard.x3.sud.SudAudioInputStream;
import org.pamguard.x3.sud.SudFileListener;
import org.pamguard.x3.sud.SudProgressListener;
/**
* Class to handle appropriate notifications for SUD files, which go a bit
* beyond what's handled in the chunk notifications.
* @author dg50
*
*/
public class SUDNotificationManager implements SUDNotificationHandler {
private ArrayList<SUDNotificationHandler> handlers = new ArrayList();
public void addNotificationHandler(SUDNotificationHandler sudNotificationHandler) {
if (handlers.contains(sudNotificationHandler)) {
return;
}
handlers.add(sudNotificationHandler);
}
public boolean removeNotificationHandler(SUDNotificationHandler sudNotificationHandler) {
return handlers.remove(sudNotificationHandler);
}
@Override
public void newSudInputStream(SudAudioInputStream sudAudioInputStream) {
for (SUDNotificationHandler handler : handlers) {
handler.newSudInputStream(sudAudioInputStream);
}
}
@Override
public void sudStreamClosed() {
for (SUDNotificationHandler handler : handlers) {
handler.sudStreamClosed();
}
}
@Override
public void progress(double arg0, int arg1, int arg2) {
for (SUDNotificationHandler handler : handlers) {
handler.progress(arg0, arg1, arg2);
}
}
@Override
public void chunkProcessed(int chunkId, Chunk sudChunk) {
for (SUDNotificationHandler handler : handlers) {
handler.chunkProcessed(chunkId, sudChunk);
}
}
@Override
public void interpretNewFile(String newFile, SudAudioInputStream sudAudioStream) {
for (SUDNotificationHandler handler : handlers) {
handler.interpretNewFile(newFile, sudAudioStream);
}
}
}

View File

@ -77,6 +77,9 @@ public class ThreadingHydrophoneLocator extends StraightHydrophoneLocator implem
*/
while (gpsIt.hasPrevious()) {
gpsUnit = gpsIt.previous();
if (gpsUnit == null) {
continue;
}
gpsData = gpsUnit;
if (gpsUnit.getTimeInMillis() < timeMilliseconds) {
break;

View File

@ -1,6 +1,5 @@
package PamController.command;
import Map.GetMapFile;
import PamController.PamControlledUnit;
import PamController.PamController;
import PamUtils.PamCalendar;
@ -56,6 +55,9 @@ public class SummaryCommand extends ExtCommand {
totalString += String.format("\n<%s>%s:%s<\\%s>", aModule.getShortUnitType(),
aModule.getUnitName(), aString, aModule.getShortUnitType());
}
if (clear) {
lastCallTime = nowTime;
}
return totalString;
}

View File

@ -673,11 +673,6 @@ final public class PamModel implements PamModelInterface, PamSettings {
+ "bearings to source, group into click trains, etc.");
mi.setModulesMenuGroup(detectorsGroup);
mi.addGUICompatabilityFlag(PamGUIManager.FX);
mi = PamModuleInfo.registerControlledUnit("soundtrap.STClickControl", "SoundTrap Click Detector");
mi.setModulesMenuGroup(detectorsGroup);
mi.setToolTipText("Click Detector module for Soundtrap detector data");
mi.setHidden(isViewer == false);
mi = PamModuleInfo.registerControlledUnit("clickTrainDetector.ClickTrainControl", "Click Train Detector");
mi.addDependency(new PamDependency(RawDataUnit.class, "clickDetector.ClickControl"));
@ -729,6 +724,11 @@ final public class PamModel implements PamModelInterface, PamSettings {
mi.setToolTipText("Generalised Power Law Detector for tonal sounds");
mi.setModulesMenuGroup(detectorsGroup);
mi = PamModuleInfo.registerControlledUnit("soundtrap.STClickControl", "SoundTrap Click Detector");
mi.setModulesMenuGroup(detectorsGroup);
mi.setToolTipText("Click Detector module for Soundtrap detector data only");
// mi.setHidden(isViewer == false);
// mi = PamModuleInfo.registerControlledUnit("WorkshopDemo.WorkshopController", "Workshop Demo Detector");
// mi.addDependency(new PamDependency(FFTDataUnit.class, "fftManager.PamFFTControl"));
// mi.setToolTipText("Simple demo detector for programmers");

View File

@ -17,7 +17,7 @@ public class PamAudioFileFilter extends PamFileFilter {
// addFileType(".AIFF");
// addFileType(".FLAC");
addFileType(".flac");
// addFileType(".sud");
addFileType(".sud");
}
}

View File

@ -1,7 +1,9 @@
package PamUtils;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
@ -9,6 +11,7 @@ import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
@ -183,4 +186,47 @@ public class XMLUtils {
}
return doc;
}
/**
* Write to the given file.
* @param doc xml document
* @param outFile file
* @throws IOException
*/
public static void writeToFile(Document doc, File outFile) throws IOException {
String asString = getAsString(doc);
if (asString!=null) {
try {
BufferedWriter out = new BufferedWriter(new FileWriter(outFile, false));
out.write(asString);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Get the xml document as a String.
* @param doc xml document
* @return xml content as a a string.
*/
public static String getAsString(Document doc) {
try {
DOMSource domSource = new DOMSource(doc);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
// transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.transform(domSource, result);
return writer.toString();
} catch (TransformerException e) {
e.printStackTrace();
return null;
}
}
}

View File

@ -17,7 +17,7 @@ public class SnrSqlAddon implements SQLLoggingAddon {
public SnrSqlAddon(SNRAnnotationType snrAnnotationType) {
super();
this.snrAnnotationType = snrAnnotationType;
snr = new PamTableItem("snr", Types.DOUBLE);
snr = new PamTableItem("snr", Types.DOUBLE, "Signal to Noise ratio");
}
@Override

View File

@ -18,10 +18,10 @@ public class SPLSqlAddon implements SQLLoggingAddon {
public SPLSqlAddon(SPLAnnotationType splAnnotationType) {
super();
this.splAnnotationType = splAnnotationType;
rms = new PamTableItem("RMS", Types.DOUBLE);
zeroPeak = new PamTableItem("ZeroPeak", Types.DOUBLE);
peakPeak = new PamTableItem("PeakPeak", Types.DOUBLE);
sel = new PamTableItem("SEL", Types.DOUBLE);
rms = new PamTableItem("RMS", Types.DOUBLE, "RMS Level");
zeroPeak = new PamTableItem("ZeroPeak", Types.DOUBLE, "Zero to Peak Level");
peakPeak = new PamTableItem("PeakPeak", Types.DOUBLE, "Peak to Peak Level");
sel = new PamTableItem("SEL", Types.DOUBLE, "Sound Exposure Level");
}
@Override

View File

@ -20,7 +20,7 @@ public class StringSQLLogging implements SQLLoggingAddon {
super();
this.stringAnnotationType = stringAnnotationType;
notes = new PamTableItem(stringAnnotationType.getAnnotationName(),
Types.CHAR, stringAnnotationType.getMaxLength());
Types.CHAR, stringAnnotationType.getMaxLength(), "Notes");
}
@Override

View File

@ -21,16 +21,16 @@ public class BearingAnnotationSQL implements SQLLoggingAddon {
public BearingAnnotationSQL(BearingAnnotationType bearingAnnotationType) {
super();
this.bearingAnnotationType = bearingAnnotationType;
algoName = new PamTableItem("BearingAlgorithm", Types.CHAR, 30);
angle[0] = new PamTableItem("BearingAngle1", Types.REAL);
angle[1] = new PamTableItem("BearingAngle2", Types.REAL);
angleError[0] = new PamTableItem("BearingError1", Types.REAL);
angleError[1] = new PamTableItem("BearingError2", Types.REAL);
refAngles[0] = new PamTableItem("ReferenceAngle1", Types.REAL);
refAngles[1] = new PamTableItem("ReferenceAngle2", Types.REAL);
bfPhones = new PamTableItem("BearingPhones", Types.INTEGER);
bfArrayType = new PamTableItem("BearingArrayType", Types.SMALLINT);
bfContents = new PamTableItem("BearingLocContents", Types.INTEGER);
algoName = new PamTableItem("BearingAlgorithm", Types.CHAR, 30, "Algorithm Name");
angle[0] = new PamTableItem("BearingAngle1", Types.REAL, "Horizontal angle (radians)");
angle[1] = new PamTableItem("BearingAngle2", Types.REAL, "Vertical angle (radians)");
angleError[0] = new PamTableItem("BearingError1", Types.REAL, "Horizontal angle error (radians)");
angleError[1] = new PamTableItem("BearingError2", Types.REAL, "Vertical angle error (radians)");
refAngles[0] = new PamTableItem("ReferenceAngle1", Types.REAL, "Horizontal angle reference");
refAngles[1] = new PamTableItem("ReferenceAngle2", Types.REAL, "Vertical angle reference");
bfPhones = new PamTableItem("BearingPhones", Types.INTEGER, "Used hydrophones bitmap");
bfArrayType = new PamTableItem("BearingArrayType", Types.SMALLINT, "Array Type 1=point;2=line;3=plane;4=volume");
bfContents = new PamTableItem("BearingLocContents", Types.INTEGER, "Bitmap of localisation information types");
}
@Override

View File

@ -130,7 +130,18 @@ public class BinaryStorageDialogPanel {
binaryStoreSettings.autoNewFiles = autoNewFiles.isSelected();
binaryStoreSettings.datedSubFolders = dateSubFolders.isSelected();
binaryStoreSettings.limitFileSize = limitfileSize.isSelected();
if (allowChannelOffsets) {
try {
binaryStoreSettings.channelShift = Integer.valueOf(channelOffset.getText());
}
catch (NumberFormatException e) {
return PamDialog.showWarning(owner, errorTitle, "Invalid channel offset number format");
}
if (binaryStoreSettings.channelShift < 0 || binaryStoreSettings.channelShift > 31) {
return PamDialog.showWarning(owner, errorTitle, "Channel offset bust be between 0 and 31");
}
}
if (PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW) {
return true;
}
@ -157,17 +168,6 @@ public class BinaryStorageDialogPanel {
return PamDialog.showWarning(owner, errorTitle, "Invalid file size data");
}
}
if (allowChannelOffsets) {
try {
binaryStoreSettings.channelShift = Integer.valueOf(channelOffset.getText());
}
catch (NumberFormatException e) {
return PamDialog.showWarning(owner, errorTitle, "Invalid channel offset number format");
}
if (binaryStoreSettings.channelShift < 0 || binaryStoreSettings.channelShift > 31) {
return PamDialog.showWarning(owner, errorTitle, "Channel offset bust be between 0 and 31");
}
}
NoiseStoreType nst = (NoiseStoreType) noiseStoreType.getSelectedItem();
if (nst == null) {
return PamDialog.showWarning(owner, errorTitle, "You must select a noise storage type");

View File

@ -1096,7 +1096,7 @@ public class ClickDetector extends PamProcess {
* @return true if the tasks complete successfully and the click is to be kept.
* false otherwise.
*/
private boolean completeClick(ClickDetection newClick) {
public boolean completeClick(ClickDetection newClick) {
if (newClick.dataType == ClickDetection.CLICK_CLICK) {
int nChannels = PamUtils.getNumChannels(newClick.getChannelBitmap());

View File

@ -428,11 +428,26 @@ PamSettingsSource {
JMenuItem speedMenu = new JMenuItem("Test database speed");
speedMenu.addActionListener(new SpeedMenu(parentFrame));
menu.add(speedMenu);
JMenuItem exSchema = new JMenuItem("Export database schema");
exSchema.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
exportDatabaseSchema(parentFrame);
}
});
menu.add(exSchema);
}
return menu;
}
protected void exportDatabaseSchema(JFrame parentFrame) {
dbProcess.exportDatabaseSchema(parentFrame);
}
class DatabaseFileMenuAction implements ActionListener {
private Frame frame;

View File

@ -22,6 +22,8 @@ import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
@ -36,7 +38,9 @@ import loggerForms.UDFTableDefinition;
import loggerForms.formdesign.FormEditor;
import PamController.PamControlledUnit;
import PamController.PamController;
import PamController.PamFolders;
import PamUtils.PamCalendar;
import PamUtils.PamFileChooser;
import PamView.dialog.warn.WarnOnce;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
@ -1393,4 +1397,42 @@ public class DBProcess extends PamProcess {
return logViewerSettings;
}
/**
* Export all available database schema, converting PamTableDefinitions into
* valid xsd documents.
* @param parentFrame
*/
public void exportDatabaseSchema(JFrame parentFrame) {
File startLoc = PamFolders.getFileChooserPath(PamFolders.getDefaultProjectFolder());
PamFileChooser fc = new PamFileChooser();
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
startLoc = PamFolders.getFileChooserPath(startLoc);
fc.setCurrentDirectory(startLoc);
int ans = fc.showDialog(parentFrame, "Select storage folder");
if (ans == JFileChooser.APPROVE_OPTION) {
startLoc = fc.getSelectedFile();
exportDatabaseSchema(parentFrame, startLoc);
}
}
/**
* Export all table definitions to xsd files in given folder.
* @param parentFrame
* @param folder
*/
private void exportDatabaseSchema(JFrame parentFrame, File folder) {
ArrayList<PamDataBlock> allDataBlocks = PamController.getInstance().getDataBlocks();
DBSchemaWriter schemaWriter = new DBSchemaWriter();
for (PamDataBlock aBlock : allDataBlocks) {
SQLLogging logging = aBlock.getLogging();
if (logging == null) {
continue;
}
schemaWriter.writeSchema(folder, aBlock);
}
}
}

View File

@ -0,0 +1,263 @@
package generalDatabase;
import java.io.File;
import java.io.IOException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import PamUtils.XMLUtils;
import PamguardMVC.PamDataBlock;
/**
* Functions for writing database table schema in a format
* compatible with the Tethys schemas.
* @author dg50
*
*/
public class DBSchemaWriter {
private PamTableDefinition baseTableDefinition = new PamTableDefinition("PamTableDefinition");
private PamTableDefinition parentTable;
public DBSchemaWriter() {
// TODO Auto-generated constructor stub
}
public boolean writeStandardTableDef(File outputFolder, PamDataBlock dataBlock) {
PamTableDefinition aTable = new PamTableDefinition("PamStandardTable");
parentTable = null;
exportDatabaseSchema(outputFolder, dataBlock, null, aTable);
parentTable = aTable;
return true;
}
public boolean writeSchema(File outputFolder, PamDataBlock dataBlock) {
if (dataBlock == null) {
return false;
}
SQLLogging logging = dataBlock.getLogging();
if (logging == null) {
return false;
}
PamTableDefinition tableDef = logging.getTableDefinition();
tableDef = logging.getBaseTableDefinition();
if (tableDef instanceof PamTableDefinition) {
writeStandardTableDef(outputFolder, dataBlock);
}
else {
parentTable = null;
}
exportDatabaseSchema(outputFolder, dataBlock, logging, tableDef);
return true;
}
private void exportDatabaseSchema(File outputFolder, PamDataBlock dataBlock, SQLLogging logging, PamTableDefinition tableDef) {
/**
* write a parent item, e.g. if tableDef is a sub class of PamTableDefinition
*/
// String parentName = writeParentTableSchema(outputFolder, dataBlock, tableDef);
String tableName = tableDef.getTableName();
Document doc = PamUtils.XMLUtils.createBlankDoc();
Element schemaEl = doc.createElement("xs:schema");
schemaEl.setAttribute("xmlns:xs","http://www.w3.org/2001/XMLSchema");
schemaEl.setAttribute("targetNamespace", "http://tethys.sdsu.edu/schema/1.0");
doc.appendChild(schemaEl);
if (parentTable != null) {
Element parentEl = doc.createElement("xs:include");
parentEl.setAttribute("schemaLocation", parentTable.getTableName()+".xsd");
schemaEl.appendChild(parentEl);
}
fillItemElement(doc, schemaEl, tableDef.pamTableItems);
if (logging != null) {
ArrayList<SQLLoggingAddon> annots = logging.getLoggingAddOns();
if (annots != null) {
for (SQLLoggingAddon addon : annots) {
Element compEl = addAddonElement(doc, schemaEl, addon);
if (compEl != null) {
schemaEl.appendChild(compEl);
}
}
}
}
try {
File outputFile = new File(outputFolder, tableName+".xsd");
XMLUtils.writeToFile(doc, outputFile);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Add a complex element for a SQLLogging addon.
* @param doc
* @param schemaEl
* @param addon
*/
private Element addAddonElement(Document doc, Element schemaEl, SQLLoggingAddon addon) {
Element compEl = doc.createElement("xs:complexType");
Element oEl = doc.createElement("xs:element");
oEl.setAttribute("name", addon.getName());
Element seqEl = doc.createElement("xs:sequence");
PamTableDefinition mtTable = new PamTableDefinition(addon.getName());
addon.addTableItems(mtTable);
// this is a mess ! must avoid the standard items.
fillItemElement(doc, seqEl, mtTable.pamTableItems);
compEl.appendChild(seqEl);
oEl.appendChild(compEl);
return oEl;
}
/**
* Fills information on items in a list into the given element
* This may be the schema element or may be a complex element.
* @param doc
* @param schemaEl
* @param tableItems
*/
private void fillItemElement(Document doc, Element schemaEl, List<PamTableItem> tableItems) {
for (PamTableItem tableItem : tableItems) {
if (shouldSkip(tableItem, parentTable)) {
// element is included in parent table, so skip it.
continue;
}
Element itemEl = doc.createElement("xs:element");
itemEl.setAttribute("name", tableItem.getName());
itemEl.setAttribute("type", sqlTypeToString(tableItem.getSqlType(), tableItem.getLength()));
String documentation = tableItem.getDescription();
if (documentation != null) {
Element annotation = doc.createElement("xs:annotation");
itemEl.appendChild(annotation);
Element docEl = doc.createElement("xs:documentation");
docEl.setTextContent(documentation);
annotation.appendChild(docEl);
}
schemaEl.appendChild(itemEl);
}
}
private boolean shouldSkip(PamTableItem tableItem, PamTableDefinition parentTable) {
if (parentTable == null) {
return false;
}
if (parentTable.findTableItem(tableItem.getName()) != null) {
return true;
}
return false;
}
// private String writeParentTableSchema(File outputFolder, PamDataBlock dataBlock, PamTableDefinition tableDef) {
// /**
// * Write a schema of everything that is in the parent table, then include a reference to that
// * schema. To do this, we need to a) establish if there is a table def parent, then go through
// * all the fields in THIS tableDef, see if the field exists in the parent. IF it exists in the
// * parent, write it in the parent doc, if it's only in this, write it in this doc. So far so good, but
// * we need to also make this recursive so it can build layer on layer ?
// * Reaslistically, this is all too complicated ! Just write out the schema for the PamTableDefinition
// * at the start of everything, and skip those fields in everything else. This will be a bit ad-hoc, but
// * it will otherwise be a nightmare since we don't know which table items are in which class at this point.
// */
// Class tableClass = tableDef.getClass();
// Class parentClass = tableClass.getSuperclass();
// if (parentClass.isAssignableFrom(tableClass) == false) {
// return null;
// }
//
//
// return null;
// }
private String sqlTypeToString(int sqlType, int length) {
switch (sqlType) {
case Types.ARRAY:
return "ARRAY";
case Types.BIGINT:
return "xs:long";
case Types.BINARY:
return "BINARY";
case Types.BIT:
return "BIT";
case Types.BLOB:
return "BLOB";
case Types.BOOLEAN:
return "xs:boolean";
case Types.CHAR:
return "xs:string";
case Types.CLOB:
return "CLOB";
case Types.DATALINK:
return "DATALINK";
case Types.DATE:
return "xs:dateTime";
case Types.DECIMAL:
return "DECIMAL";
case Types.DISTINCT:
return "DISTINCT";
case Types.DOUBLE:
return "xs:double";
case Types.FLOAT:
return "xs:float";
case Types.INTEGER:
return "xs:int";
case Types.JAVA_OBJECT:
return "JAVA_OBJECT";
case Types.LONGVARBINARY:
return "LONGVARBINARY(" + length + ")";
case Types.LONGVARCHAR:
return "LONGVARCHAR(" + length + ")";
case Types.NULL:
return "NULL";
case Types.NUMERIC:
return "NUMERIC";
case Types.OTHER:
return "OTHER";
case Types.REAL:
return "xs:float";
case Types.REF:
return "REF";
case Types.SMALLINT:
return "xs:short";
case Types.STRUCT:
return "STRUCT";
case Types.TIME:
return "TIME";
case Types.TIMESTAMP:
return "xs:dateTime";
case Types.TINYINT:
return "TINYINT";
case Types.VARBINARY:
return "VARBINARY(" + length + ")";
case Types.VARCHAR:
return "VARCHAR(" + length + ")";
}
return null;
}
}

View File

@ -43,7 +43,7 @@ public class EmptyTableDefinition implements Cloneable {
this.tableName = tableName;
this.setUpdatePolicy(updatePolicy);
pamTableItems = new ArrayList<PamTableItem>();
pamTableItems.add(indexItem = new PamTableItem(indexColName, Types.INTEGER));
pamTableItems.add(indexItem = new PamTableItem(indexColName, Types.INTEGER, "Primary key"));
indexItem.setPrimaryKey(true);
indexItem.setCounter(true);
}

View File

@ -55,15 +55,15 @@ public class PamTableDefinition extends EmptyTableDefinition implements Cloneabl
*/
public PamTableDefinition(String tableName, int updatePolicy) {
super(tableName, updatePolicy);
pamTableItems.add(uid = new PamTableItem("UID", Types.BIGINT));
pamTableItems.add(timeStampItem = new PamTableItem(utcColName, Types.TIMESTAMP));
pamTableItems.add(timeStampMillis = new PamTableItem("UTCMilliseconds", Types.SMALLINT));
pamTableItems.add(localTime = new PamTableItem("PCLocalTime", Types.TIMESTAMP));
pamTableItems.add(pcTime = new PamTableItem("PCTime", Types.TIMESTAMP));
pamTableItems.add(channelBitmap = new PamTableItem("ChannelBitmap", Types.INTEGER));
pamTableItems.add(sequenceBitmap = new PamTableItem("SequenceBitmap", Types.INTEGER));
pamTableItems.add(uid = new PamTableItem("UID", Types.BIGINT, "Unique Identifier"));
pamTableItems.add(timeStampItem = new PamTableItem(utcColName, Types.TIMESTAMP, "Timestamp UTC"));
pamTableItems.add(timeStampMillis = new PamTableItem("UTCMilliseconds", Types.SMALLINT, "Time milliseconds (for databases which do not support millis)"));
pamTableItems.add(localTime = new PamTableItem("PCLocalTime", Types.TIMESTAMP, "Local time on PC"));
pamTableItems.add(pcTime = new PamTableItem("PCTime", Types.TIMESTAMP, "Time data written, UTC. Same as UTC for real time data, current time for offline file analysis"));
pamTableItems.add(channelBitmap = new PamTableItem("ChannelBitmap", Types.INTEGER, "Bitmap of input channels used"));
pamTableItems.add(sequenceBitmap = new PamTableItem("SequenceBitmap", Types.INTEGER, "Bitmap of beam or channel outputs used"));
if (updatePolicy == SQLLogging.UPDATE_POLICY_WRITENEW) {
addTableItem(updateReference = new PamTableItem("UpdateOf", Types.INTEGER));
addTableItem(updateReference = new PamTableItem("UpdateOf", Types.INTEGER, "Reference to previous value"));
}
}

View File

@ -50,6 +50,14 @@ public class PamTableItem implements Cloneable {
*/
private Object value;
/**
* Test description of field. Can be exported to schema and may
* be possible to write into database description fields one day. In any case
* it can be useful to the programmer when looking back to see what on earth
* code is supposed to be doing.
*/
private String description;
/*
* Reference to another PamTableItem in a different
* table. This must be of the same sqlType as this
@ -60,6 +68,11 @@ public class PamTableItem implements Cloneable {
*/
private PamTableItem crossReferenceItem;
/**
* Generate a table item
* @param name name of table item
* @param sqlType SQL Type from java.sql.Types, e.g. Types.INTEGER
*/
public PamTableItem(String name, int sqlType) {
super();
this.name = name;
@ -67,7 +80,28 @@ public class PamTableItem implements Cloneable {
this.length = 0;
this.required = false;
}
/**
* Generate a table item
* @param name name of table item
* @param sqlType SQL Type from java.sql.Types, e.g. Types.INTEGER
* @param description optional description
*/
public PamTableItem(String name, int sqlType, String description) {
super();
this.name = name;
this.sqlType = sqlType;
this.description = description;
this.length = 0;
this.required = false;
}
/**
* Generate a table item
* @param name name of table item
* @param sqlType SQL Type from java.sql.Types, e.g. Types.INTEGER
* @param length length (only applicable to Types.CHAR types)
*/
public PamTableItem(String name, int sqlType, int length) {
super();
this.name = name;
@ -76,6 +110,22 @@ public class PamTableItem implements Cloneable {
this.required = false;
}
/**
* Generate a table item
* @param name name of table item
* @param sqlType SQL Type from java.sql.Types, e.g. Types.INTEGER
* @param length length (only applicable to Types.CHAR types)
* @param description optional description
*/
public PamTableItem(String name, int sqlType, int length, String description) {
super();
this.name = name;
this.sqlType = sqlType;
this.length = length;
this.description = description;
this.required = false;
}
public PamTableItem(String name, int sqlType, int length, boolean required) {
super();
this.name = name;
@ -500,6 +550,20 @@ public class PamTableItem implements Cloneable {
return null;
}
}
/**
* @return the description
*/
public String getDescription() {
return description;
}
/**
* @param description the description to set
*/
public void setDescription(String description) {
this.description = description;
}
}

View File

@ -2183,5 +2183,12 @@ public abstract class SQLLogging {
return subDetection.getSuperDetection(superDataBlock);
}
/**
* @return the loggingAddOns
*/
public ArrayList<SQLLoggingAddon> getLoggingAddOns() {
return loggingAddOns;
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,2 +1,2 @@
JavaSearch 1.0
TMAP bs=2048 rt=1 fl=-1 id1=6679 id2=1
TMAP bs=2048 rt=1 fl=-1 id1=6700 id2=1

Binary file not shown.

View File

@ -574,6 +574,8 @@
<mapID target="utilities.SIDEModule.docs.SIDE_Overview_seq" url="utilities/SIDEModule/docs/SIDE_Overview.html#seq"/>
<mapID target="detectors.clickDetectorHelp.docs.SoundTrapClickDetector" url="detectors/clickDetectorHelp/docs/SoundTrapClickDetector.html"/>
<mapID target="utilities.spectrogramannotations.docs.using" url="utilities/spectrogramannotations/docs/using.html"/>
<mapID target="visual_methods.loggerFormsHelp.docs.NMEAINT" url="visual_methods/loggerFormsHelp/docs/NMEAINT.html"/>
@ -802,6 +804,8 @@
<mapID target="visual_methods.loggerFormsHelp.docs.NMEACHAR" url="visual_methods/loggerFormsHelp/docs/NMEACHAR.html"/>
<mapID target="sound_processing.AcquisitionHelp.docs.sudfiles" url="sound_processing/AcquisitionHelp/docs/sudfiles.html"/>
<mapID target="sound_processing.LTSA.Docs.LTSADisplays" url="sound_processing/LTSA/Docs/LTSADisplays.html"/>
<mapID target="localisation.difar.difarLocalisation.docs.difar_PostProcessingTutorial__Toc396467156" url="localisation/difar/difarLocalisation/docs/difar_PostProcessingTutorial.html#_Toc396467156"/>

View File

@ -1,7 +1,13 @@
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!--generated by JHelpDev Version: 0.63, 14 May 2008, see jhelpdev.sourceforge.net--><!DOCTYPE helpset PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp HelpSet Version 2.0//EN" "http://java.sun.com/products/javahelp/helpset_2_0.dtd">
<helpset version="1.0">
@ -20,7 +26,13 @@
<title>Help </title>
@ -39,7 +51,13 @@
<maps>
@ -60,7 +78,13 @@
<homeID>
top
</homeID>
@ -79,7 +103,13 @@ top
<mapref location="Map.jhm"/>
@ -98,7 +128,13 @@ top
</maps>
@ -117,7 +153,13 @@ top
<view mergetype="javax.help.UniteAppendMerge">
@ -138,7 +180,13 @@ top
<name>
TOC
</name>
@ -159,7 +207,13 @@ TOC
<label>
TOC
</label>
@ -180,7 +234,13 @@ TOC
<type>
javax.help.TOCView
</type>
@ -201,7 +261,13 @@ javax.help.TOCView
<data>
PAMGUARDTOC.xml
</data>
@ -220,7 +286,13 @@ PAMGUARDTOC.xml
</view>
@ -239,7 +311,13 @@ PAMGUARDTOC.xml
<view>
@ -260,7 +338,13 @@ PAMGUARDTOC.xml
<name>
Index
</name>
@ -281,7 +365,13 @@ Index
<label>
Index
</label>
@ -302,7 +392,13 @@ Index
<type>
javax.help.IndexView
</type>
@ -323,7 +419,13 @@ javax.help.IndexView
<data>
PAMGUARDIndex.xml
</data>
@ -342,7 +444,13 @@ PAMGUARDIndex.xml
</view>
@ -361,7 +469,13 @@ PAMGUARDIndex.xml
<view>
@ -382,7 +496,13 @@ PAMGUARDIndex.xml
<name>
Search
</name>
@ -403,7 +523,13 @@ Search
<label>
Search
</label>
@ -424,7 +550,13 @@ Search
<type>
javax.help.SearchView
</type>
@ -445,7 +577,13 @@ javax.help.SearchView
<data engine="com.sun.java.help.search.DefaultSearchEngine">
JavaHelpSearch
</data>
@ -464,7 +602,13 @@ JavaHelpSearch
</view>

View File

@ -2,6 +2,18 @@
<!DOCTYPE index PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp Index Version 1.0//EN" "http://java.sun.com/products/javahelp/index_2_0.dtd"><!--generated by JHelpDev Version: 0.63, 14 May 2008, see jhelpdev.sourceforge.net-->
<index version="1.0">
<indexitem text="SUD Files " target="sound_processing.AcquisitionHelp.docs.sudfiles"/>
<indexitem text="SoundTrap " target="sound_processing.AcquisitionHelp.docs.sudfiles"/>
<indexitem text="Sound Trap " target="sound_processing.AcquisitionHelp.docs.sudfiles"/>
<indexitem text="Click Train " target="detectors.ClickTrainDetector.docs.ClickTrainDetector"/>
<indexitem text="SUD " target="detectors.clickDetectorHelp.docs.SoundTrapClickDetector"/>
<indexitem text="SoundTrap " target="detectors.clickDetectorHelp.docs.SoundTrapClickDetector"/>
<indexitem text="3D Localisation " target="detectors.Pam3DHelp.docs.guiOverview"/>
<indexitem text="Adding or Editing a Hydrophone " target="utilities.hydrophoneArrayManagerHelp.docs.Array_NewHydrophone"/>

View File

@ -278,8 +278,10 @@
<tocitem text="Asio Sound Cards " target="sound_processing.AcquisitionHelp.docs.AcquisitionAsioSoundCard" image="topic"/>
<tocitem text="Audio Files " target="sound_processing.AcquisitionHelp.docs.AcquisitionFile" image="topic"/>
<tocitem text="Audio Files " target="sound_processing.AcquisitionHelp.docs.AcquisitionFile" image="topic">
<tocitem text="SUD Files " target="sound_processing.AcquisitionHelp.docs.sudfiles" image="topic"/>
</tocitem>
<tocitem text="Audio File Folders " target="sound_processing.AcquisitionHelp.docs.AcquisitionFileFolder" image="topic"/>
<tocitem text="File Dates " target="sound_processing.AcquisitionHelp.docs.FileTimeZone" image="topic"/>
@ -426,6 +428,8 @@
<tocitem text="Create Binary Files Offline " target="utilities.BinaryStore.docs.CreateBinariesOffline" image="topic"/>
</tocitem>
<tocitem text="SoundTrap Click Detector " target="detectors.clickDetectorHelp.docs.SoundTrapClickDetector" image="topic"/>
</tocitem>
<tocitem text="Whistle and Moan Detector ">
<tocitem text="Overview " target="detectors.whistleMoanHelp.docs.whistleMoan_Overview" image="topic"/>

View File

@ -0,0 +1,82 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<link href="../../../pamHelpStylesheet.css" type="text/css" rel="STYLESHEET"><title>Click Classification</title></head>
<body><h1>Click Detector</h1>
<h2>SoundTrap Click Detector</h2>
<p>If you are using a SountTrap recording device with built in click detection from
<a href="https://www.oceaninstruments.co.nz/">Ocean Instruments</a>,
you may need to use a modified version of the <a href="ClickDetector_clickDetector.html">Click Detector</a>.
</p>
<p>The SoundTrap click detector allows you to detect and store clicks at high frequencies (say 384kS/sec), suitable for odontocete echolocation clicks, and
at the same time, record audio data files at a lower frequency (e.g. 96 or 48kS/sec). This optimises disk space usage and makes long deployments
of several months possible without running out of data storage. </p>
<p>Having two sample rates present within a single PAMGuard configuration is possible using
<a href="../../../sound_processing/decimatorHelp/docs/decimator_decimator.html">Decimator</</a> modules. However such configurations become particularly
complicated to configure when the sample rate of the recorded files is lower than the sample rate of the click detector.</p>
<p>We therefore recommend that you use a modified version of the <a href="ClickDetector_clickDetector.html">Click Detector</a>, which manages it's own sample rate and
channel information based on information extracted from the SoundTrap data.</p>
<p>Note that the SoundTrap click detector should only be used for clicks automatically detected by the SoundTrap. If you want to detect clicks from the
SoundTrap recordings, then use a normal <a href="ClickDetector_clickDetector.html">Click Detector</a> in the normal way.</p>
<h3>Creating an instance of the SoundTrap Click Detector</h3>
<p>
From the <strong><em>File>Add modules>Detectors</em></strong> menu, or
from the pop-up menu on the data model display, select <i>'SoundTrap Click
Detector'</i> near the bottom of the Detectors list. Enter a descriptive name for the new detector and press Ok.
</p>
<h3>Importing SoundTrap Data</h3>
<p>SoundTrap data are stored in proprietary files called <a href="../../../sound_processing/AcquisitionHelp/docs/sudfiles.html">SUD files</a>.</p>
<p> There are two ways in which you can get data from <a href="../../../sound_processing/AcquisitionHelp/docs/sudfiles.html">SUD files</a> into
the SoundTrap Click Detector. </p>
<h4>The Old Way</h4>
<p>The 'standard' way of using SoundTrap data was to inflate all of the data from the compressed SUD files. For details of this process, see the
SoundTrap user manuals and the SoundTrap Host software.</p>
<p>Normally, several inflated files are generated from each sud file:</p>
<ol>
<li>A wav file: Audio data in standard wav file format</li>
<li>An XML file: Metadata on the SoundTrap configuration, file start times in various formats, etc.</li>
<li>If the click detector was running BCL and DWV files, which contain the times of clicks and click waveforms respectively.</li>
</ol>
<p>To convert the SUD files to the binary storage format used by PAMGuard, working in the
<a href="../../../overview/PamMasterHelp/docs/viewerMode.html">PAMGuard Viewer</a>, create a Binary Store, a
SoundTrap Click Detector and also create a 'SoundTrap Detector Import' module. Then use the import module to import the BCL and DWV
data into PAMGuard. Once imported you can run <a href="ClickDetector_clickClassification.html">Click Classifiers</a>
and use other Click Detector offline functions to mark events, etc. </p>
<p>If you want to run additional analysis on the WAV file data (for example to
<a href="../../../sound_processing/NoiseBands/Docs/NoiseBands.html">make noise measurements</a> or to
<a href="../../whistleMoanHelp/docs/whistleMoan_Overview.html">detect whistles</a>),
create a different PAMGuard configuration to process those data.<p>
<h4>The (better) New Way</h4>
<p>Current versions of PAMGuard can read <a href="../../../sound_processing/AcquisitionHelp/docs/sudfiles.html">SUD files</a> directly,
without first unpacking them into WAV, XML, BCL and DWV files. This not
only reduces the amount of disk space you need by about x4, but also saves a lot of time.</p>
<p>Better still, you can now set up PAMGuard in normal mode to simultaneously process the audio data in the
<a href="../../../sound_processing/AcquisitionHelp/docs/sudfiles.html">SUD file</a> with one set of
detectors, and simultaneously extract the click detector data into appropriate files for a SoundTrap Click Detector. </p>
<p>Start PAMGuard in <a href="../../../overview/PamMasterHelp/docs/normalMode.html">Normal Mode</a> and add a
<a href="../../../sound_processing/AcquisitionHelp/docs/AcquisitionOverview.html">Sound Acquisition</a> module.
Add a SoundTrap Click Detector, a <a href="../../../utilities/BinaryStore/docs/binarystore_overview.html">Binary Store</a> store and a
<a href="../../../utilities/generalDatabaseHelp/docs/database_database.html">Database</a>
module (optional). In the <a href="../../../sound_processing/AcquisitionHelp/docs/AcquisitionConfiguration.html">Sound Acquisition dialog</a>
select a single SUD file or a folder of SUD files. At this point, the SoundTrap
Click Detector will be automatically configured with the correct sample rate (which won't be the sample rate displayed in the Sound Acquisition
module). </p>
<p>Configure any <a href="ClickDetector_clickClassification.html">Click Classifiers</a> you want to be run on the SoundTrap click data as it is imported.</p>
<p>You can then add any other detectors and measurement processes you want to run on the SoundTrap audio data, this may include
instances of the normal Click Detector module if you want to detect clicks in the lower frequency audio data.</p>
<p>Process the data in the normal way and clicks will automatically be generated within the SoundTrap click detector</p>
<p>Further process you data using the <a href="../../../overview/PamMasterHelp/docs/viewerMode.html">PAMGuard Viewer</a> in the normal way.</p>
<br>
<br>
<br>
</body></html>

View File

@ -7,7 +7,9 @@
<h1>Audio Files</h1>
<p>As well as analysing data from sound cards in real time, PAMGUARD can be used to analyse archived data
from audio filed in WAV or AIF format.</p>
from audio filed in <a href="https://en.wikipedia.org/wiki/WAV">WAV</a>,
<a href="https://en.wikipedia.org/wiki/Audio_Interchange_File_Format">AIF</a>, <a href="https://en.wikipedia.org/wiki/FLAC">FLAC</a>,
or <a href="sudfiles.html">SUD</a> file format.</p>
<br>
<h2>Setting up an Audio File</h2>

View File

@ -0,0 +1,32 @@
<html>
<head>
<LINK href="../../../pamHelpStylesheet.css" type=text/css rel=STYLESHEET>
<title>SUD Files</title>
</head>
<body>
<h1>SoundTrap data files</h1>
<h3>SUD Files</h3>
<p>
SoundTrap recorders from
<a href="https://www.oceaninstruments.co.nz/">Ocean Instruments</a>
store data in proprietary files called SUD files. See SoundTrap documentation for information on how to
extract SUD files from SoundTrap recorders. </p>
<p>Earlier versions of PAMGuard required you to 'inflate' the SUD files into standard wav audio files using
the <a href="https://www.oceaninstruments.co.nz/downloads/">SoundTrap Host software</a> before they could be processed.</p>
<p>The current version of PAMGuard no longer requires this since it can read data directly from the SUD files.</p>
<p>Inflating SUD files to WAV files generally required between 3 and 5 times as much disk space and could also take
a fair amount of time, so not inflating will save both!</p>
<h3>Mixing SUD and WAV files</h3>
<p>If a SUD file and a WAV file with the same name are in the same folder, then PAMGuard will ignore the SUD file
and process the WAV file. Note that in this case, PAMGuard will be unable to extract any metadata from the SUD file
and will not extract SoundTrap Click Detections (see below).</p>
<h3>SoundTrap Click Detector</h3>
<p>If you are using the SoundTrap build in click detector (see SoundTrap manuals) then the SUD files will also contain
detected clicks.</p> <p>See the help page for the <a href="../../../detectors/clickDetectorHelp/docs/SoundTrapClickDetector.html">SoundTrap Click Detector</a>
for information on how to get these clicks from the SUD files into PAMGuard. </p>
<br><br><br>
</body>
</html>

View File

@ -144,4 +144,9 @@ public class BuoyStatusData implements Serializable, ManagedParameters {
return ps;
}
@Override
public String toString() {
return String.format("Buoy %d(%d) ip %s", buoyId1, buoyId2, ipAddr);
}
}

View File

@ -387,6 +387,11 @@ public class BuoyStatusDataUnit extends PamDataUnit {
return buoyStatusData;
}
@Override
public String toString() {
return String.format("Status %s\n", buoyStatusData.toString());
}
// /**
// * @return the genericStringPairsChanged
// */

View File

@ -770,7 +770,7 @@ public class NetworkReceiver extends PamControlledUnit implements PamSettings, N
}
private NetworkObject interpretPamCommand(NetworkObject receivedData, BuoyStatusDataUnit buoyStatusDataUnit) {
// System.out.println("Network command received: " + getPamCommandString(dataId2));
// System.out.println("Network command received: " + getPamCommandString(dataId2));
buoyStatusDataUnit.setCommandStatus(receivedData.getDataType2());
long time = PamCalendar.getTimeInMillis();
if (receivedData.getData() != null && receivedData.getDataLength() >= 8) {

View File

@ -25,13 +25,20 @@
package soundtrap;
import java.awt.Frame;
import java.util.ArrayList;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import Acquisition.AcquisitionControl;
import Acquisition.sud.SUDNotificationManager;
import PamController.PamController;
import PamguardMVC.PamRawDataBlock;
import clickDetector.ClickBTDisplay;
import clickDetector.ClickControl;
import clickDetector.ClickDisplay;
import clickDetector.ClickDisplayManager;
import soundtrap.sud.SudFileDWVHandler;
/**
* @author mo55
@ -45,6 +52,9 @@ public class STClickControl extends ClickControl {
* The private sound acquisition module linked to the Soundtrap click data
*/
private AcquisitionControl rawSource;
private SudFileDWVHandler sudFileDWVHandler;
/**
* @param name
@ -54,6 +64,9 @@ public class STClickControl extends ClickControl {
// create a private acquisition control that only this module can see
rawSource = new AcquisitionControl("Private Sound Acq for Soundtrap Click Detector");
sudFileDWVHandler = new SudFileDWVHandler(this);
sudFileDWVHandler.subscribeSUD();
}
@Override
@ -106,6 +119,40 @@ public class STClickControl extends ClickControl {
return newMenu;
}
@Override
public void pamStart() {
sudFileDWVHandler.pamStart();
super.pamStart();
}
@Override
public void pamStop() {
sudFileDWVHandler.pamStop();
super.pamStop();
}
@Override
public void notifyModelChanged(int changeType) {
super.notifyModelChanged(changeType);
if (changeType == PamController.INITIALIZATION_COMPLETE) {
sudFileDWVHandler.subscribeSUD();
}
}
/**
* Called when running SUD file data to find and scroll the BT Display's
* @param timeMillis
*/
public void updateDisplayScrollers(long timeMillis) {
ClickDisplayManager dispManager = getDisplayManager();
ArrayList<ClickDisplay> dispList = dispManager.getWindowList();
for (ClickDisplay display : dispList) {
if (display instanceof ClickBTDisplay) {
((ClickBTDisplay) display).newScrollTimingData(timeMillis);
}
}
}
}

View File

@ -0,0 +1,59 @@
package soundtrap.sud;
import org.pamguard.x3.sud.Chunk;
public class BCLDetectionChunk {
private long javaMillis;
private boolean isDetection;
private String bclRecord;
private Chunk sudChunk;
private long javaMicros;
public BCLDetectionChunk(long javaMillis, long javaMicros, boolean isDetection, String bclRecord, Chunk sudChunk) {
super();
this.javaMillis = javaMillis;
this.javaMicros = javaMicros;
this.isDetection = isDetection;
this.bclRecord = bclRecord;
this.sudChunk = sudChunk;
}
/**
* @return the javaMillis
*/
public long getJavaMillis() {
return javaMillis;
}
/**
* @return the isDetection
*/
public boolean isDetection() {
return isDetection;
}
/**
* @return the bclRecord
*/
public String getBclRecord() {
return bclRecord;
}
/**
* @return the sudChunk
*/
public Chunk getSudChunk() {
return sudChunk;
}
/**
* @return the javaMicros
*/
public long getJavaMicros() {
return javaMicros;
}
}

View File

@ -0,0 +1,265 @@
package soundtrap.sud;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.pamguard.x3.sud.Chunk;
import org.pamguard.x3.sud.SudAudioInputStream;
import org.pamguard.x3.sud.SudDataInputStream;
import Acquisition.AcquisitionControl;
import Acquisition.sud.SUDNotificationHandler;
import Acquisition.sud.SUDNotificationManager;
import PamController.PamController;
import PamUtils.PamCalendar;
import clickDetector.ClickDetection;
import clickDetector.ClickDetector;
import clickDetector.ClickDetector.ChannelGroupDetector;
import soundtrap.STClickControl;
import wavFiles.ByteConverter;
/**
* Class to handle BCL and DWV data from a SUD file during sud file processing.
* SUD files are the compressed data files from soundtraps. The latest PAMGuard
* version contains a audioinputstream for SUD files, making it possible to
* process them withoug having to first inflate them to wav files. During
* 'normal mode' processing, this class will subscribe to packets from the SUD
* files, unpack what would normally be BCL and DWV data and generate
* appropriate binary output files.
*
* @author dg50
*
*/
public class SudFileDWVHandler implements SUDNotificationHandler {
private STClickControl stClickControl;
private SudAudioInputStream sudAudioInputStream;
private int txtCount = 0;
private List<Chunk> clickChunks = new LinkedList();
private List<BCLDetectionChunk> bclChunks = new LinkedList();
int bclDetCount, bclNoiseCount, dwvCount, processedChunks;
private long effortStart, fileStartMicros;
private double sampleRate;
private ByteConverter byteConverter;
private ClickDetector clickDetector;
private ChannelGroupDetector channelGroupDetector;
public SudFileDWVHandler(STClickControl stClickControl) {
this.stClickControl = stClickControl;
clickDetector = stClickControl.getClickDetector();
}
@Override
public void newSudInputStream(SudAudioInputStream sudAudioInputStream) {
this.sudAudioInputStream = sudAudioInputStream;
interpretNewFile(null, sudAudioInputStream);
bclDetCount = bclNoiseCount = dwvCount = processedChunks = 0;
bclChunks.clear();
clickChunks.clear();
byteConverter = ByteConverter.createByteConverter(sudAudioInputStream.getFormat());
}
@Override
public void interpretNewFile(String newFile, SudAudioInputStream sudAudioInputStream) {
// this is the wav sample rate, not the detector sample rate, so don't use it
// sampleRate = sudAudioInputStream.getFormat().getFrameRate();
// this is the right one
sampleRate = sudAudioInputStream.getSudMap().clickDetSampleRate;
fileStartMicros = sudAudioInputStream.getSudMap().getFirstChunkTimeMicros();
stClickControl.findRawDataBlock().setChannelMap(1);
stClickControl.findRawDataBlock().setSampleRate((float) sampleRate, true);
stClickControl.getSTAcquisition().acquisitionParameters.sampleRate = (float) sampleRate;
// System.out.printf("Open input stream fs = %3.1f\n", sampleRate);
}
@Override
public void sudStreamClosed() {
System.out.printf("SUD input stream closed, %d DWV, %d bcl Detectins and %d BCL Noise, %d chunks processed\n",
dwvCount, bclDetCount, bclNoiseCount, processedChunks);
}
@Override
public void progress(double arg0, int arg1, int arg2) {
// TODO Auto-generated method stub
}
@Override
public void chunkProcessed(int chunkID, Chunk sudChunk) {
if (sudAudioInputStream == null) {
return;
}
String chunkName = "Unknown";
int chunkSize = sudChunk.buffer.length;
if (sudAudioInputStream.getChunkIDString(chunkID).equals("wav")) {
long millis = sudChunk.getChunkHeader().getMillisTime();
stClickControl.updateDisplayScrollers(millis);
if (sudAudioInputStream.isChunkIDWav(chunkID)) {
// chunkName = "RECORDINGS";
// System.out.printf("Chunk ID %d, size %d, type %s\n", chunkID, chunkSize,
// chunkName);
// System.out.println("ID: " + chunkID + " This is raw data from detected
// CLICKS: " + sudAudioInputStream.getChunkIDString(chunkID));
} else {
chunkName = "CLICKS";
processClickChunk(chunkID, sudChunk);
}
}
if (sudAudioInputStream.getChunkIDString(chunkID).equals("csv")) {
// System.out.println("CSV data the bytes convert directly to comma delimted data");
}
if (sudAudioInputStream.getChunkIDString(chunkID).equals("txt")) {
processTextChunk(chunkID, sudChunk);
txtCount++;
}
}
/**
* Pairwise byte swap, i.e. change endianness of int16's. Won't work for
* anything else.
*
* @param data
*/
public void swapEndian(byte[] data) {
for (int i = 0; i < data.length; i += 2) {
byte b = data[i];
data[i] = data[i + 1];
data[i + 1] = b;
}
}
private void processTextChunk(int chunkID, Chunk sudChunk) {
SudDataInputStream dis = new SudDataInputStream(new ByteArrayInputStream(sudChunk.getBuffer()));
try {
while (dis.available() > 0) {
long rtime = (dis.readInt()) & 0xffffffffL;
long mticks = (dis.readInt()) & 0xffffffffL;
int n = dis.readUnsignedShort();
long javaMillis = (long) rtime * 1000 + mticks / 1000;
long javaMicros = (long) rtime * 1000000 + mticks;
byte[] b = new byte[(n % 2 == 1) ? n + 1 : n];
dis.read(b);
swapEndian(b);
String s = new String(b, "UTF-8");
String[] bits = s.split(",");
if (bits[0].equals("E")) {
// start or end record.
boolean isStart = bits[1].equals("1");
if (isStart) {
effortStart = javaMicros;
}
dwvEffort(javaMillis, isStart);
} else if (bits[0].equals("D")) {
boolean isDet = bits[1].equals("1");
if (isDet) {
bclDetCount++;
String bclText = String.format("%9d,%6d,%s has %d bits", rtime, mticks, s, bits.length);
BCLDetectionChunk bclChunk = new BCLDetectionChunk(javaMillis, javaMicros, isDet, bclText,
sudChunk);
bclChunks.add(bclChunk);
} else {
bclNoiseCount++;
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
convertChunks();
}
/**
* Convert bcl and dwv data to click detections.
*/
private void convertChunks() {
int nProc = 0;
while (bclChunks.size() > 0 && clickChunks.size() > 0) {
BCLDetectionChunk bclChunk = bclChunks.remove(0);
Chunk dwvChunk = clickChunks.remove(0);
makeClick(bclChunk, dwvChunk);
nProc++;
processedChunks++;
}
}
private void makeClick(BCLDetectionChunk bclChunk, Chunk dwvChunk) {
long elapsedSamples = (long) ((bclChunk.getJavaMicros() - fileStartMicros) * (sampleRate / 1e6));
long millis = bclChunk.getJavaMillis();
byte[] rawData = dwvChunk.getBuffer();
int nBytes = rawData.length;
int nSamples = nBytes / Short.BYTES;
double[][] wavData = new double[1][nSamples];
byteConverter.bytesToDouble(rawData, wavData, nBytes);
// channelGroupDetector = clickDetector.getChannelGroupDetector(0);
ClickDetection click = new ClickDetection(1, elapsedSamples, nSamples, clickDetector, channelGroupDetector, 1);
click.setTimeMilliseconds(millis);
click.setWaveData(wavData);
// if (groupDetector != null) {
// groupDetector.
// }
if (clickDetector.completeClick(click)) {
clickDetector.getClickDataBlock().addPamData(click);
}
}
private void dwvEffort(long javaMillis, boolean isStart) {
System.out.printf("DWV Effort %s at %s\n", isStart ? "Start" : "End", PamCalendar.formatDBDateTime(javaMillis));
}
private void processClickChunk(int chunkID, Chunk sudChunk) {
clickChunks.add(sudChunk);
dwvCount++;
}
public void pamStart() {
subscribeSUD();
}
public void pamStop() {
// TODO Auto-generated method stub
}
public boolean subscribeSUD() {
if (stClickControl.isViewer()) {
return false;
}
AcquisitionControl daq = (AcquisitionControl) PamController.getInstance()
.findControlledUnit(AcquisitionControl.unitType);
if (daq == null) {
return false;
}
SUDNotificationManager sudManager = daq.getSUDNotificationManager();
if (sudManager == null) {
return false;
}
sudManager.addNotificationHandler(this);
return true;
}
}

View File

@ -183,11 +183,6 @@ public class WhistleMoanControl extends PamControlledUnit implements PamSettings
return true;
}
@Override
public String getModuleSummary() {
return whistleToneProcess.getModuleSummary();
}
@Override
public Object getShortUnitType() {
return "WMD";
@ -225,4 +220,9 @@ public class WhistleMoanControl extends PamControlledUnit implements PamSettings
}
return null;
}
@Override
public String getModuleSummary(boolean clear) {
return whistleToneProcess.getModuleSummary(clear);
}
}

View File

@ -968,17 +968,6 @@ public class WhistleToneConnectProcess extends PamProcess {
}
public String getModuleSummary() {
String sumText = String.format("%d", NSUMMARYPOINTS);
for (int i = 0; i < NSUMMARYPOINTS; i++) {
sumText += String.format(",%d",whistleSummaryCount[i]);
}
clearSummaryData();
return sumText;
}
/**
* When delay data are written to binary files, int16's are used, but these
* must be scaled up to allow for sub-sample timing. How much they can be
@ -1099,4 +1088,20 @@ public class WhistleToneConnectProcess extends PamProcess {
return fftUnitsOut;
}
/*
* replicate Decimus function to give counts of whistles in four evenly spaced frequency
* bins.
*/
public String getModuleSummary(boolean clear) {
String sumText = String.format("%d", NSUMMARYPOINTS);
for (int i = 0; i < NSUMMARYPOINTS; i++) {
sumText += String.format(",%d",whistleSummaryCount[i]);
}
if (clear) {
clearSummaryData();
}
return sumText;
}
}