Merge pull request #27 from PAMGuard/main

Merge SUD changes from main
This commit is contained in:
Douglas Gillespie 2022-11-04 15:09:47 +00:00 committed by GitHub
commit 3e717bd207
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
101 changed files with 18492 additions and 1570 deletions

View File

@ -6,8 +6,9 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/Java 17">
<attributes>
<attribute name="module" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
@ -16,6 +17,5 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="/X3/src/org"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@ -372,9 +372,9 @@ 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 to <em><span style='font-family:"Calibri",sans-serif'>lib</span></em>
for the 32 bit version).</p>
look in the folder called &quot;lib64&quot; for the required shared libraries (change
to <em><span style='font-family:"Calibri",sans-serif'>lib</span></em> for the
32 bit version).</p>
<p class=MsoNormal>For &quot;Mixed&quot; and &quot;Viewer&quot; modes just add
a &quot;-m&quot; or &quot;-v&quot; to the list of java arguments. On Windows
@ -452,7 +452,6 @@ 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>
@ -500,7 +499,7 @@ 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 doesnt exist (which is correct behavior in quiet
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
@ -511,6 +510,10 @@ monitors so that data fields are sized correctly. </span></p>
<p class=MsoNormal><span lang=EN-US>Fixed a memory leak in ROCCA</span></p>
<p class=MsoNormal><span lang=EN-US>Fixed issues with options in Click Detector
bearing time display which (when using planar and 3D arrays) allow you to plot
relative to the array, the vessel, or North. </span></p>
<h1><a name="_Latest_Version_2.02.03_2"></a><span lang=EN-US>Version 2.02.03
February 2022</span></h1>
@ -531,7 +534,7 @@ 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
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
@ -605,7 +608,7 @@ 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
<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>
@ -709,16 +712,16 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
new CPOD features </p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>15. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
Better interpolation of data by the Decimator when decimating/upsampling by a
non-integer amount </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 interpolation of data by the Decimator when
decimating/upsampling by a non-integer amount </p>
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>16. </span><span
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
Noise Level Outputs - as an aid to performance diagnosis, some detectors
(currently the GPL, Click Detector and Whistle and Moan Detector) are
outputting additional noise metrics to their binary output files. These can be
read with the <a href="https://sourceforge.net/projects/pamguard/files/Matlab/">PAMGuard
(currently the GPL, Click Detector and Whistle and Moan Detector) are outputting
additional noise metrics to their binary output files. These can be read with
the <a href="https://sourceforge.net/projects/pamguard/files/Matlab/">PAMGuard
Matlab library</a> and used to diagnose system performance in varying noise
conditions. Improved displays within PAMGuard for these noise metrics will be
included in a future release. </p>
@ -726,10 +729,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. 26822699, 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>
@ -816,8 +819,8 @@ Measurement module. </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>
Speed up adding subdetections to superdetections. </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>Speed up adding subdetections to superdetections. </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
@ -969,15 +972,15 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
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>
Add user-facing option to adjust the startup delay for the time-correction
(Global Time module). This provides a workaround to speed up analysis of
thousands of wav files (i.e. by setting startup delay to 0 instead of default
value of 2000 ms). </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 user-facing option to adjust the startup delay for the
time-correction (Global Time module). This provides a workaround to speed up
analysis of thousands of wav files (i.e. by setting startup delay to 0 instead
of default value of 2000 ms). </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>
Add support for RS Aqua time format. </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 support for RS Aqua time format. </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>
@ -1055,9 +1058,9 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
Bug 433. Custom storage options were being lost when Pamguard restarted.</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>
Bug 434. Pamguard Viewer mode was having problems importing settings from psfx
file.</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 434. Pamguard Viewer mode was having problems importing
settings from psfx file.</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>
@ -1105,8 +1108,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>
@ -1194,10 +1197,10 @@ Detector display. </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>
This version of PAMGuard has been upgraded to make it compatible with Java 12.
psfx files generated in previous beta releases should be compatible with this
version, and vice-versa.</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>This version of PAMGuard has been upgraded to make it
compatible with Java 12. psfx files generated in previous beta releases should
be compatible with this version, and vice-versa.</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>
@ -1352,8 +1355,8 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>&nbsp;&nb
lang=EN-US> </span>Better display of microseconds in dialogs.</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>
Added adaptive noise filter to Ishmael Detectors.</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 adaptive noise filter to Ishmael Detectors.</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
@ -1478,8 +1481,8 @@ 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
@ -1586,8 +1589,7 @@ 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;
@ -1611,9 +1613,9 @@ position for hydrophone 0.</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>
Better way of coupling scrollers in User Display panels - see new options in
main menu.</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 way of coupling scrollers in User Display panels -
see new options in main menu.</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>
@ -1743,8 +1745,7 @@ 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>
Many updates to the Video Range module. Will currently only work with landmarks.</p>
<!-- ************************************************************************************************************************** -->
@ -1807,8 +1808,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>
@ -1877,8 +1878,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>
@ -1994,7 +1995,7 @@ file format is the addition of a Unique Data Identifier (UID) to each unit of
data. This is intended to aid in offline analysis by making it easier for the
user to link what they are seeing on different PAMGuard displays and also to
link with any data post processed in Matlab or other custom analysis software.
UIDs are also added to PAMGuard database tables. </span></p>
UID’s are also added to PAMGuard database tables. </span></p>
<h4><span lang=EN-US>Converting Old Data</span></h4>
@ -2002,13 +2003,13 @@ UID
viewer they will automatically be converted. For safety, the original binary
files will not be overwritten and the new data will be placed in a new folder
on your computer with the same path as the old data, but suffixed with
_WithUID, e.g. if your binary data were previously stored in the folder
‘_WithUID’, e.g. if your binary data were previously stored in the folder
C:\MySurvey\binarydata the new data will be written to
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 UIDs will be used in
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>
@ -2023,11 +2024,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
@ -2152,8 +2153,8 @@ happens when the user selects save as new configuration. This has been fixed.</p
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
@ -2182,8 +2183,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>
@ -2191,8 +2192,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;
@ -2243,7 +2244,7 @@ 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
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
@ -2374,9 +2375,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;
@ -2637,12 +2638,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>
@ -3071,12 +3072,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>
@ -3140,8 +3141,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>
@ -3577,8 +3578,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;
@ -3831,10 +3832,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>
@ -3929,17 +3930,17 @@ classifier is still available). </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>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>
</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>
<p class=MsoNormal><b>Small features and bug fixes</b></p>
@ -4228,8 +4229,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>

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.m2e.Maven2LaunchConfigurationType">
<booleanAttribute key="M2_DEBUG_OUTPUT" value="false"/>
<stringAttribute key="M2_GOALS" value="package shade:shade"/>
<booleanAttribute key="M2_NON_RECURSIVE" value="false"/>
<booleanAttribute key="M2_OFFLINE" value="false"/>
<stringAttribute key="M2_PROFILES" value=""/>
<listAttribute key="M2_PROPERTIES"/>
<stringAttribute key="M2_RUNTIME" value="EMBEDDED"/>
<booleanAttribute key="M2_SKIP_TESTS" value="true"/>
<intAttribute key="M2_THREADS" value="1"/>
<booleanAttribute key="M2_UPDATE_SNAPSHOTS" value="false"/>
<stringAttribute key="M2_USER_SETTINGS" value=""/>
<booleanAttribute key="M2_WORKSPACE_RESOLUTION" value="false"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_ATTR_USE_ARGFILE" value="false"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_SHOW_CODEDETAILS_IN_EXCEPTION_MESSAGES" value="true"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-13/"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-mx6000m&#13;&#10;-Djava.library.path=lib64"/>
<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc:/PamGuard Main DG}"/>
</launchConfiguration>

View File

@ -74,9 +74,9 @@
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.6</version>
<configuration>
<source>16</source>
<target>16</target>
<release>16</release>
<source>17</source>
<target>17</target>
<release>17</release>
</configuration>
</plugin>
<plugin>

24
pom.xml
View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.pamguard</groupId>
<artifactId>Pamguard</artifactId>
<version>2.02.04ac</version>
<version>2.02.05</version>
<name>Pamguard Java12+</name>
<description>Pamguard for Java 12+, using Maven to control dependcies</description>
<url>www.pamguard.org</url>
@ -76,9 +76,9 @@
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.6</version>
<configuration>
<source>16</source>
<target>16</target>
<release>16</release>
<source>17</source>
<target>17</target>
<release>17</release>
</configuration>
</plugin>
@ -391,6 +391,13 @@
<version>${javafx.version}</version>
</dependency>
<!-- Decorates JavaFX components-->
<dependency>
<groupId>net.synedra</groupId>
<artifactId>validatorfx</artifactId>
<version>0.4.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-compress -->
<dependency>
<groupId>org.apache.commons</groupId>
@ -777,7 +784,7 @@
<dependency>
<groupId>pamguard.org</groupId>
<artifactId>x3</artifactId>
<version>2.0.0</version>
<version>2.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/it.sauronsoftware/jave -->
@ -825,6 +832,13 @@
<artifactId>swingx-all</artifactId>
<version>1.6.5-1</version>
</dependency>
<!-- Theme for JavaFX -->
<dependency>
<groupId>io.github.mkpaz</groupId>
<artifactId>atlantafx-base</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>

View File

@ -0,0 +1,4 @@
#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
#Fri Aug 14 15:49:24 CEST 2020
x3-1.0.0.pom>=
x3-1.0.0.jar>=

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>1.0.0</version>
<description>POM was created from install:install-file</description>
</project>

View File

@ -0,0 +1,4 @@
#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
#Fri Sep 25 10:46:11 CEST 2020
x3-2.0.0.pom>=
x3-2.0.0.jar>=

View File

@ -0,0 +1,39 @@
#Fri Jan 14 08:14:25 GMT 2022
repo|file\:///Users/au671271/pamguard/PAMGuard/repo|sources=1632311094649
central|https\://jmachund.jfrog.io/artifactory/jpam2|javadoc=1641807924466
repo|file\:///Users/au671271/git/PAMGuard/repo|javadoc=1642148065400
github|https\://maven.pkg.github.com/macster110/jpam|sources=1642147913185
repo|file\:///Users/au671271/pamguard/PAMGuard_16_mvn/repo|sources=1625576160247
icm|http\://maven.icm.edu.pl/artifactory/repo|javadoc=1600971368390
talan|https\://nexus.talanlabs.com/content/repositories/releases/|sources=1642147913185
geomajas|http\://maven.geomajas.org/|javadoc=1642148065400
central|https\://repo.maven.apache.org/maven2|javadoc=1642065819015
bedatadriven|https\://nexus.bedatadriven.com/content/groups/public/|sources=1642147913185
repo|file\:///Users/au671271/pamguard/PAMGuard_12_mvn/repo|sources=1602589977893
jpamutils|https\://raw.github.com/macster110/jpam/mvn-repo/|javadoc=1642065819015
icm|http\://maven.icm.edu.pl/artifactory/repo|sources=1600971300139
geomajas|http\://maven.geomajas.org/|sources=1642147913185
central|https\://repo1.maven.org/maven2|sources=1642147913185
central|https\://repo.maven.apache.org/maven2|sources=1642065813019
github|https\://maven.pkg.github.com/macster110/jpam|javadoc=1642148065400
bintray-jerady-maven|https\://dl.bintray.com/jerady/maven|sources=1602589977893
bedatadriven|https\://nexus.bedatadriven.com/content/groups/public/|javadoc=1642148065400
jpamutils|https\://raw.github.com/macster110/jpam/mvn-repo/|sources=1642065813019
my-local-repo|file\:///Users/au671271/pamguard/PAMGuard_12_mvn/src/jars|sources=1600949483388
repo|file\:///Users/au671271/git/PAMGuard/repo|sources=1642147913185
bintray-macster110-jtorch4pam|macster110|https\://dl.bintray.com/macster110/jtorch4pam|javadoc=1642148065400
jdl4pam|https\://raw.github.com/macster110/jpam/mvn-repo/|javadoc=1642065819015
unidata-all|https\://artifacts.unidata.ucar.edu/repository/unidata-all/|sources=1642147913185
icm|https\://maven.averbis.com/m2/|sources=1601026887474
bintray-jerady-maven|https\://dl.bintray.com/jerady/maven|javadoc=1602590126606
talan|https\://nexus.talanlabs.com/content/repositories/releases/|javadoc=1642148065400
central|https\://jmachund.jfrog.io/artifactory/jpam2|sources=1641807658592
my-local-repo|file\:///Users/au671271/pamguard/PAMGuard_12_mvn/src/jars|javadoc=1600949605299
unidata-all|https\://artifacts.unidata.ucar.edu/repository/unidata-all/|javadoc=1642148065400
icm|https\://maven.averbis.com/m2/|javadoc=1601027283465
repo|file\:///Users/au671271/pamguard/PAMGuard_12_mvn/repo|javadoc=1602590126606
jdl4pam|https\://raw.github.com/macster110/jpam/mvn-repo/|sources=1642065813019
bintray-macster110-jtorch4pam|macster110|https\://dl.bintray.com/macster110/jtorch4pam|sources=1642147913185
repo|file\:///Users/au671271/pamguard/PAMGuard_16_mvn/repo|javadoc=1625576167973
repo|file\:///Users/au671271/pamguard/PAMGuard/repo|javadoc=1632313121603
central|https\://repo1.maven.org/maven2|javadoc=1642148065400

View File

@ -0,0 +1,38 @@
#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
#Fri Jan 14 08:14:25 GMT 2022
https\://dl.bintray.com/macster110/jtorch4pam/.error=
file\:///Users/au671271/pamguard/PAMGuard_12_mvn/src/jars/.error=
https\://jmachund.jfrog.io/artifactory/jpam2/.lastUpdated=1625576167971
file\:///Users/au671271/pamguard/PAMGuard/repo/.error=
file\:///Users/au671271/pamguard/PAMGuard_16_mvn/repo/.lastUpdated=1622023729745
https\://dl.bintray.com/macster110/jtorch4pam/.lastUpdated=1600949601867
file\:///Users/au671271/git/PAMGuard/repo/.error=
https\://nexus.bedatadriven.com/content/groups/public/.error=
https\://artifacts.unidata.ucar.edu/repository/unidata-all/.error=
https\://artifacts.unidata.ucar.edu/repository/unidata-all/.lastUpdated=1600949603273
https\://maven.averbis.com/m2/.lastUpdated=1601027283464
file\:///Users/au671271/git/PAMGuard/repo/.lastUpdated=1641807924465
https\://raw.github.com/macster110/jpam/mvn-repo/.lastUpdated=1642065819012
file\:///Users/au671271/pamguard/PAMGuard_16_mvn/repo/.error=
http\://maven.icm.edu.pl/artifactory/repo/.lastUpdated=1600971368389
https\://nexus.bedatadriven.com/content/groups/public/.lastUpdated=1600949604396
http\://maven.icm.edu.pl/artifactory/repo/.error=
https\://repo1.maven.org/maven2/.error=
@default-github-https\://maven.pkg.github.com/macster110/jpam/.lastUpdated=1642148065399
file\:///Users/au671271/pamguard/PAMGuard/repo/.lastUpdated=1632313121601
https\://repo1.maven.org/maven2/.lastUpdated=1642148065192
https\://dl.bintray.com/jerady/maven/.lastUpdated=1600949602327
http\://maven.geomajas.org/.lastUpdated=1600949604068
https\://nexus.talanlabs.com/content/repositories/releases/.error=
file\:///Users/au671271/pamguard/PAMGuard_12_mvn/repo/.error=
file\:///Users/au671271/pamguard/PAMGuard_12_mvn/src/jars/.lastUpdated=1600949601869
https\://repo.maven.apache.org/maven2/.lastUpdated=1600949605299
http\://maven.geomajas.org/.error=
https\://jmachund.jfrog.io/artifactory/jpam2/.error=
https\://nexus.talanlabs.com/content/repositories/releases/.lastUpdated=1600949604877
https\://maven.averbis.com/m2/.error=
https\://repo.maven.apache.org/maven2/.error=
file\:///Users/au671271/pamguard/PAMGuard_12_mvn/repo/.lastUpdated=1602590126603
https\://maven.pkg.github.com/macster110/jpam/.error=Could not transfer artifact pamguard.org\:x3\:jar\:javadoc\:2.0.0 from/to github (https\://maven.pkg.github.com/macster110/jpam)\: Access denied to https\://maven.pkg.github.com/macster110/jpam/pamguard/org/x3/2.0.0/x3-2.0.0-javadoc.jar. Error code 401,
https\://dl.bintray.com/jerady/maven/.error=
https\://raw.github.com/macster110/jpam/mvn-repo/.error=

View File

@ -0,0 +1,38 @@
#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
#Fri Jan 14 08:11:53 GMT 2022
https\://dl.bintray.com/macster110/jtorch4pam/.error=
file\:///Users/au671271/pamguard/PAMGuard_12_mvn/src/jars/.error=
https\://jmachund.jfrog.io/artifactory/jpam2/.lastUpdated=1625576160246
file\:///Users/au671271/pamguard/PAMGuard/repo/.error=
file\:///Users/au671271/pamguard/PAMGuard_16_mvn/repo/.lastUpdated=1622023729649
https\://dl.bintray.com/macster110/jtorch4pam/.lastUpdated=1600949479758
file\:///Users/au671271/git/PAMGuard/repo/.error=
https\://nexus.bedatadriven.com/content/groups/public/.error=
https\://artifacts.unidata.ucar.edu/repository/unidata-all/.error=
https\://artifacts.unidata.ucar.edu/repository/unidata-all/.lastUpdated=1600949481209
https\://maven.averbis.com/m2/.lastUpdated=1601026887474
file\:///Users/au671271/git/PAMGuard/repo/.lastUpdated=1641807658590
https\://raw.github.com/macster110/jpam/mvn-repo/.lastUpdated=1642065813017
file\:///Users/au671271/pamguard/PAMGuard_16_mvn/repo/.error=
http\://maven.icm.edu.pl/artifactory/repo/.lastUpdated=1600971300137
https\://nexus.bedatadriven.com/content/groups/public/.lastUpdated=1600949482388
http\://maven.icm.edu.pl/artifactory/repo/.error=
https\://repo1.maven.org/maven2/.error=
@default-github-https\://maven.pkg.github.com/macster110/jpam/.lastUpdated=1642147913184
file\:///Users/au671271/pamguard/PAMGuard/repo/.lastUpdated=1632311094646
https\://repo1.maven.org/maven2/.lastUpdated=1642147912977
https\://dl.bintray.com/jerady/maven/.lastUpdated=1600949480238
http\://maven.geomajas.org/.lastUpdated=1600949482017
https\://nexus.talanlabs.com/content/repositories/releases/.error=
file\:///Users/au671271/pamguard/PAMGuard_12_mvn/repo/.error=
file\:///Users/au671271/pamguard/PAMGuard_12_mvn/src/jars/.lastUpdated=1600949479759
https\://repo.maven.apache.org/maven2/.lastUpdated=1600949483387
http\://maven.geomajas.org/.error=
https\://jmachund.jfrog.io/artifactory/jpam2/.error=
https\://nexus.talanlabs.com/content/repositories/releases/.lastUpdated=1600949482866
https\://maven.averbis.com/m2/.error=
https\://repo.maven.apache.org/maven2/.error=
file\:///Users/au671271/pamguard/PAMGuard_12_mvn/repo/.lastUpdated=1602589977891
https\://maven.pkg.github.com/macster110/jpam/.error=Could not transfer artifact pamguard.org\:x3\:jar\:sources\:2.0.0 from/to github (https\://maven.pkg.github.com/macster110/jpam)\: Access denied to https\://maven.pkg.github.com/macster110/jpam/pamguard/org/x3/2.0.0/x3-2.0.0-sources.jar. Error code 401,
https\://dl.bintray.com/jerady/maven/.error=
https\://raw.github.com/macster110/jpam/mvn-repo/.error=

View File

@ -0,0 +1,18 @@
#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
#Thu Sep 24 13:58:55 CEST 2020
https\://dl.bintray.com/macster110/jtorch4pam/.error=
file\:///Users/au671271/pamguard/PAMGuard_12_mvn/src/jars/.error=
https\://dl.bintray.com/macster110/jtorch4pam/.lastUpdated=1600948677455
https\://artifacts.unidata.ucar.edu/repository/unidata-all/.error=
https\://nexus.bedatadriven.com/content/groups/public/.error=
https\://artifacts.unidata.ucar.edu/repository/unidata-all/.lastUpdated=1600948714963
https\://dl.bintray.com/jerady/maven/.lastUpdated=1600948680041
http\://maven.geomajas.org/.lastUpdated=1600948729479
https\://nexus.talanlabs.com/content/repositories/releases/.error=
file\:///Users/au671271/pamguard/PAMGuard_12_mvn/src/jars/.lastUpdated=1600948677498
https\://repo.maven.apache.org/maven2/.lastUpdated=1600948686447
http\://maven.geomajas.org/.error=
https\://nexus.talanlabs.com/content/repositories/releases/.lastUpdated=1600948735430
https\://repo.maven.apache.org/maven2/.error=
https\://dl.bintray.com/jerady/maven/.error=
https\://nexus.bedatadriven.com/content/groups/public/.lastUpdated=1600948734692

View File

@ -1 +0,0 @@
851e2c9b153f1686858523e69d78da20

View File

@ -1 +0,0 @@
4d89dd98cf0188bb3bfe4afd74dc427ce23d3a41

View File

@ -0,0 +1,18 @@
#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
#Thu Sep 24 13:57:29 CEST 2020
https\://dl.bintray.com/macster110/jtorch4pam/.error=
file\:///Users/au671271/pamguard/PAMGuard_12_mvn/src/jars/.error=
https\://dl.bintray.com/macster110/jtorch4pam/.lastUpdated=1600948647604
https\://artifacts.unidata.ucar.edu/repository/unidata-all/.error=
https\://nexus.bedatadriven.com/content/groups/public/.error=
https\://artifacts.unidata.ucar.edu/repository/unidata-all/.lastUpdated=1600948648002
https\://dl.bintray.com/jerady/maven/.lastUpdated=1600948647670
http\://maven.geomajas.org/.lastUpdated=1600948648672
https\://nexus.talanlabs.com/content/repositories/releases/.error=
file\:///Users/au671271/pamguard/PAMGuard_12_mvn/src/jars/.lastUpdated=1600948647606
https\://repo.maven.apache.org/maven2/.lastUpdated=1600948649503
http\://maven.geomajas.org/.error=
https\://nexus.talanlabs.com/content/repositories/releases/.lastUpdated=1600948649324
https\://repo.maven.apache.org/maven2/.error=
https\://dl.bintray.com/jerady/maven/.error=
https\://nexus.bedatadriven.com/content/groups/public/.lastUpdated=1600948648816

View File

@ -1 +0,0 @@
e09a0e45701b683f485aedf1349cab24

View File

@ -1 +0,0 @@
45129eae7b4f9c502cceffe8358fdc7e19ceaa39

View File

@ -0,0 +1,4 @@
#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
#Tue Oct 11 15:59:57 BST 2022
x3-2.1.0.jar>=
x3-2.1.0.pom>=

View File

@ -0,0 +1,13 @@
#Thu Oct 06 15:38:43 BST 2022
bedatadriven|https\://nexus.bedatadriven.com/content/groups/public/|javadoc=1665067123455
repo|file\:///Users/au671271/git/PAMGuard/repo|javadoc=1665067123455
repo|file\:///Users/au671271/git/PAMGuard/repo|sources=1665067040129
talan|https\://nexus.talanlabs.com/content/repositories/releases/|sources=1665067040129
bintray-macster110-jtorch4pam|macster110|https\://dl.bintray.com/macster110/jtorch4pam|javadoc=1665067123455
bedatadriven|https\://nexus.bedatadriven.com/content/groups/public/|sources=1665067040129
unidata-all|https\://artifacts.unidata.ucar.edu/repository/unidata-all/|sources=1665067040129
talan|https\://nexus.talanlabs.com/content/repositories/releases/|javadoc=1665067123455
central|https\://repo1.maven.org/maven2|sources=1665067040129
unidata-all|https\://artifacts.unidata.ucar.edu/repository/unidata-all/|javadoc=1665067123455
bintray-macster110-jtorch4pam|macster110|https\://dl.bintray.com/macster110/jtorch4pam|sources=1665067040129
central|https\://repo1.maven.org/maven2|javadoc=1665067123455

View File

@ -0,0 +1,14 @@
#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
#Thu Oct 06 15:38:43 BST 2022
@default-talan-https\://nexus.talanlabs.com/content/repositories/releases/.lastUpdated=1665067122194
https\://dl.bintray.com/macster110/jtorch4pam/.error=Could not transfer artifact pamguard.org\:x3\:jar\:javadoc\:2.1.0 from/to bintray-macster110-jtorch4pam (https\://dl.bintray.com/macster110/jtorch4pam)\: Remote host terminated the handshake
https\://repo1.maven.org/maven2/.error=
file\:///Users/au671271/git/PAMGuard/repo/.error=
https\://nexus.bedatadriven.com/content/groups/public/.error=
https\://artifacts.unidata.ucar.edu/repository/unidata-all/.error=
https\://artifacts.unidata.ucar.edu/repository/unidata-all/.lastUpdated=1665067121806
https\://repo1.maven.org/maven2/.lastUpdated=1665067123455
https\://nexus.talanlabs.com/content/repositories/releases/.error=Could not transfer artifact pamguard.org\:x3\:jar\:javadoc\:2.1.0 from/to talan (https\://nexus.talanlabs.com/content/repositories/releases/)\: Access denied to https\://nexus.talanlabs.com/content/repositories/releases/pamguard/org/x3/2.1.0/x3-2.1.0-javadoc.jar. Error code 401, Unauthorized
file\:///Users/au671271/git/PAMGuard/repo/.lastUpdated=1665067120886
4d1f727a0c17e3b21ef2f6654eed0b3113a4db97@default-bintray-macster110-jtorch4pam-https\://dl.bintray.com/macster110/jtorch4pam/.lastUpdated=1665067120883
https\://nexus.bedatadriven.com/content/groups/public/.lastUpdated=1665067122025

View File

@ -0,0 +1,14 @@
#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
#Thu Oct 06 15:37:20 BST 2022
@default-talan-https\://nexus.talanlabs.com/content/repositories/releases/.lastUpdated=1665067039941
https\://dl.bintray.com/macster110/jtorch4pam/.error=Could not transfer artifact pamguard.org\:x3\:jar\:sources\:2.1.0 from/to bintray-macster110-jtorch4pam (https\://dl.bintray.com/macster110/jtorch4pam)\: Remote host terminated the handshake
https\://repo1.maven.org/maven2/.error=
file\:///Users/au671271/git/PAMGuard/repo/.error=
https\://nexus.bedatadriven.com/content/groups/public/.error=
https\://artifacts.unidata.ucar.edu/repository/unidata-all/.error=
https\://artifacts.unidata.ucar.edu/repository/unidata-all/.lastUpdated=1665067039627
https\://repo1.maven.org/maven2/.lastUpdated=1665067040128
https\://nexus.talanlabs.com/content/repositories/releases/.error=Could not transfer artifact pamguard.org\:x3\:jar\:sources\:2.1.0 from/to talan (https\://nexus.talanlabs.com/content/repositories/releases/)\: Access denied to https\://nexus.talanlabs.com/content/repositories/releases/pamguard/org/x3/2.1.0/x3-2.1.0-sources.jar. Error code 401, Unauthorized
file\:///Users/au671271/git/PAMGuard/repo/.lastUpdated=1665067038933
4d1f727a0c17e3b21ef2f6654eed0b3113a4db97@default-bintray-macster110-jtorch4pam-https\://dl.bintray.com/macster110/jtorch4pam/.lastUpdated=1665067038929
https\://nexus.bedatadriven.com/content/groups/public/.lastUpdated=1665067039782

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.1.0</version>
<description>POM was created from install:install-file</description>
</project>

View File

@ -0,0 +1,16 @@
#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
#Thu Oct 06 15:51:34 BST 2022
@default-talan-https\://nexus.talanlabs.com/content/repositories/releases/.lastUpdated=1665067894494
https\://dl.bintray.com/macster110/jtorch4pam/.error=Could not transfer artifact pamguard.org\:x3\:pom\:2.1.0 from/to bintray-macster110-jtorch4pam (https\://dl.bintray.com/macster110/jtorch4pam)\: Remote host terminated the handshake
@default-repo-file\://${project.basedir}/repo/.lastUpdated=1665067029837
https\://repo1.maven.org/maven2/.error=
file\:///Users/au671271/git/PAMGuard/repo/.error=
https\://nexus.bedatadriven.com/content/groups/public/.error=
https\://artifacts.unidata.ucar.edu/repository/unidata-all/.error=
https\://artifacts.unidata.ucar.edu/repository/unidata-all/.lastUpdated=1665067032579
https\://repo1.maven.org/maven2/.lastUpdated=1665067036872
https\://nexus.talanlabs.com/content/repositories/releases/.error=Could not transfer artifact pamguard.org\:x3\:pom\:2.1.0 from/to talan (https\://nexus.talanlabs.com/content/repositories/releases/)\: Access denied to https\://nexus.talanlabs.com/content/repositories/releases/pamguard/org/x3/2.1.0/x3-2.1.0.pom. Error code 401, Unauthorized
file\://${project.basedir}/repo/.error=Could not transfer artifact pamguard.org\:x3\:pom\:2.1.0 from/to repo (file\://${project.basedir}/repo)\: Repository path /repo does not exist, and cannot be created.
file\:///Users/au671271/git/PAMGuard/repo/.lastUpdated=1665067033714
4d1f727a0c17e3b21ef2f6654eed0b3113a4db97@default-bintray-macster110-jtorch4pam-https\://dl.bintray.com/macster110/jtorch4pam/.lastUpdated=1665067894257
https\://nexus.bedatadriven.com/content/groups/public/.lastUpdated=1665067034011

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>pamguard.org</groupId>
<artifactId>x3</artifactId>
<versioning>
<release>2.0.0</release>
<versions>
<version>2.0.0</version>
</versions>
<lastUpdated>20200929205724</lastUpdated>
</versioning>
</metadata>

View File

@ -1 +0,0 @@
47ffb77b88155d037480604e508371ff

View File

@ -1 +0,0 @@
9c238e70383b552aaaf3161eaeee8ed238d90ff8

View File

@ -15,7 +15,7 @@ import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import javax.swing.border.TitledBorder;
import PamUtils.PamAudioFileFilter;
import Acquisition.pamAudio.PamAudioFileFilter;
import PamView.dialog.PamDialog;
public class CheckWavFileHeaders extends PamDialog {

View File

@ -47,6 +47,8 @@ import wavFiles.ByteConverter;
import Acquisition.filedate.FileDate;
import Acquisition.filedate.FileDateDialogStrip;
import Acquisition.filedate.FileDateObserver;
import Acquisition.pamAudio.PamAudioFileManager;
import Acquisition.pamAudio.PamAudioFileFilter;
import Acquisition.pamAudio.PamAudioSystem;
import PamController.PamControlledUnitSettings;
import PamController.PamController;
@ -54,7 +56,6 @@ import PamController.PamSettingManager;
import PamController.PamSettings;
import PamDetection.RawDataUnit;
import PamModel.SMRUEnable;
import PamUtils.PamAudioFileFilter;
import PamUtils.PamCalendar;
import PamUtils.PamFileChooser;
import PamView.dialog.PamLabel;
@ -408,7 +409,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
// acquisitionDialog.NotifyChange();
if (file.isFile() && !file.isHidden() && acquisitionDialog != null) {
try {
AudioInputStream audioStream = PamAudioSystem.getAudioInputStream(file);
AudioInputStream audioStream = PamAudioFileManager.getInstance().getAudioInputStream(file);
// // Get additional information from the header if it's a wav file.
// if (WavFileInputStream.class.isAssignableFrom(audioStream.getClass())) {
@ -537,6 +538,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
}
public File getCurrentFile() {
System.out.println("fileInputParameters: " + fileInputParameters);
if (fileInputParameters.recentFiles == null) return null;
if (fileInputParameters.recentFiles.size() < 1) return null;
String fileName = fileInputParameters.recentFiles.get(0);
@ -559,8 +561,11 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
public boolean prepareInputFile() {
File currentFile = getCurrentFile();
// System.out.printf("*********************************** Opening file %s\n", currentFile.getName());
if (currentFile == null) return false;
if (currentFile == null) {
System.out.println("The current file was null");
return false;
}
System.out.printf("*********************************** Opening file %s\n", currentFile.getName());
try {
@ -568,7 +573,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
audioStream.close();
}
audioStream = PamAudioSystem.getAudioInputStream(currentFile);
audioStream = PamAudioFileManager.getInstance().getAudioInputStream(currentFile);
if (audioStream == null) {
return false;
@ -645,7 +650,8 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
String audioFileStr = getCurrentFile()==null? "Null File": getCurrentFile().getAbsolutePath();
System.err.println("FileInputSystem: runFileAnalysis: AudioFilr format is null: " + audioFileStr);
System.err.println("FileInputSystem: runFileAnalysis: AudioFile format is null: " + audioFileStr);
return false;
}

View File

@ -28,11 +28,12 @@ import Acquisition.layoutFX.DAQSettingsPane;
import Acquisition.layoutFX.FolderInputPane;
import javafx.application.Platform;
import pamguard.GlobalArguments;
import Acquisition.pamAudio.PamAudioFileManager;
import Acquisition.pamAudio.PamAudioFileFilter;
import Acquisition.pamAudio.PamAudioSystem;
import PamController.PamControlledUnitSettings;
import PamController.PamController;
import PamController.PamSettings;
import PamUtils.PamAudioFileFilter;
import PamUtils.PamCalendar;
import PamUtils.PamFileChooser;
import PamUtils.PamFileFilter;
@ -429,6 +430,8 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings{
File aFile = files[0];
setNewFile(aFile.getAbsolutePath());
}
/*
* The file chooser is returning sub classes of File which are not
* serialisable, so we can't use them. We need to convert their
@ -505,7 +508,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings{
if (file.isFile() && !file.isHidden() && acquisitionDialog != null) {
//Hidden files should not be used in analysis...
try {
audioStream = PamAudioSystem.getAudioInputStream(file);
audioStream = PamAudioFileManager.getInstance().getAudioInputStream(file);
AudioFormat audioFormat = audioStream.getFormat();
fileSamples = audioStream.getFrameLength();
acquisitionDialog.setSampleRate(audioFormat.getSampleRate());
@ -568,6 +571,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings{
@Override
public File getCurrentFile() {
//System.out.println("All files: " + allFiles);
if (allFiles != null && allFiles.size() > currentFile) {
return allFiles.get(currentFile);
}

View File

@ -10,6 +10,7 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.AudioFormat.Encoding;
@ -25,10 +26,11 @@ import org.jflac.metadata.StreamInfo;
import org.jflac.util.ByteData;
import wavFiles.ByteConverter;
import Acquisition.pamAudio.PamAudioFileManager;
import Acquisition.pamAudio.PamAudioFileFilter;
import Acquisition.pamAudio.PamAudioSystem;
import PamDetection.RawDataUnit;
import PamUtils.FileParts;
import PamUtils.PamAudioFileFilter;
import PamUtils.PamCalendar;
import PamUtils.PamFileFilter;
import PamUtils.PamUtils;
@ -150,7 +152,7 @@ public class RonaInputSystem extends FolderInputSystem {
audioStreams[i].close();
}
audioStreams[i] = PamAudioSystem.getAudioInputStream(findChannelFile(currentFile, i, 2));
audioStreams[i] = PamAudioFileManager.getInstance().getAudioInputStream(findChannelFile(currentFile, i, 2));
audioFormat = audioStreams[i].getFormat();

View File

@ -5,7 +5,7 @@ import java.util.ArrayList;
import Acquisition.AudioFileFuncs;
import Acquisition.FolderInputSystem;
import Acquisition.WavFileFuncs;
import PamUtils.PamAudioFileFilter;
import Acquisition.pamAudio.PamAudioFileFilter;
import javafx.geometry.Insets;
import javafx.application.Platform;
import javafx.beans.property.SimpleDoubleProperty;

View File

@ -11,10 +11,9 @@ import org.controlsfx.glyphfont.Glyph;
import Acquisition.FileInputParameters;
import Acquisition.FolderInputParameters;
import Acquisition.FolderInputSystem;
import Acquisition.pamAudio.PamAudioFileFilter;
import PamController.PamController;
import PamController.PamFolders;
import PamController.SettingsPane;
import PamUtils.PamAudioFileFilter;
import PamUtils.PamCalendar;
import PamUtils.worker.PamWorker;
import PamUtils.worker.filelist.FileListData;
@ -24,7 +23,6 @@ import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
@ -48,7 +46,6 @@ import pamViewFX.fxNodes.PamComboBox;
import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.PamProgressBar;
import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
/**
* Pane for the folder input of the sound acquisition.
@ -413,7 +410,7 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
for (int i=0; i<filesArr.length; i++) {
filesArr[i] = files.get(i);
}
folderInputSystem.getFolderInputParameters().setSelectedFiles(filesArr);
folderInputSystem.makeSelFileList();
// folderInputSystem.makeSelFileList(folderInputSystem.getFolderInputParameters().getSelectedFiles());
@ -626,7 +623,7 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
return;
}
System.out.println("File list worker: " + worker );
//System.out.println("File list worker: " + worker );
//must ensure this is on the FX thread
//Platform.runLater(()->{
this.progressBar.progressProperty().bind(worker.getPamWorkProgress().getProgressProperty());

View File

@ -2,31 +2,22 @@ package Acquisition.offlineFuncs;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.AudioFormat.Encoding;
import org.jflac.FLACDecoder;
import org.jflac.PCMProcessor;
import org.jflac.metadata.Metadata;
import org.jflac.metadata.StreamInfo;
import org.jflac.sound.spi.FlacAudioFileReader;
import org.jflac.util.ByteData;
import Acquisition.filedate.FileDate;
import Acquisition.pamAudio.PamAudioSystem;
import Acquisition.pamAudio.PamAudioFileManager;
import Acquisition.pamAudio.PamAudioFileLoader;
import Acquisition.pamAudio.PamAudioFileFilter;
import PamController.OfflineFileDataStore;
import PamDetection.RawDataUnit;
import PamUtils.PamAudioFileFilter;
import PamUtils.PamCalendar;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamRawDataBlock;
import PamguardMVC.dataOffline.OfflineDataLoadInfo;
import dataMap.OfflineDataMap;
import dataMap.filemaps.FileDataMapPoint;
@ -37,18 +28,13 @@ import wavFiles.ByteConverter;
/**
* This has been split off from OfflineFileServer so that OfflineFileServer can be used with
* other file types.
* @author dg50
* @author Doug Gillespie
*
*/
public class OfflineWavFileServer extends OfflineFileServer<FileDataMapPoint> {
private FileDate fileDate;
private ByteConverter byteConverter;
private AudioInputStream audioInputStream;
private AudioFormat audioFormat;
public OfflineWavFileServer(OfflineFileDataStore offlineRawDataStore, FileDate fileDate) {
super(offlineRawDataStore);
this.fileDate = fileDate;
@ -109,7 +95,10 @@ public class OfflineWavFileServer extends OfflineFileServer<FileDataMapPoint> {
continue;
}
}
file = mapPoint.getSoundFile();/*
file = mapPoint.getSoundFile();
//TODO - this should be integrated into the PamAudioFileManager.
/*
* Now need to open file file as an input stream (what a bore !)
*/
AudioInputStream audioStream;
@ -139,7 +128,7 @@ public class OfflineWavFileServer extends OfflineFileServer<FileDataMapPoint> {
}
else {
try {
audioStream = PamAudioSystem.getAudioInputStream(file);
audioStream = PamAudioFileManager.getInstance().getAudioInputStream(file);
if (audioStream == null) {
it.remove();
continue;
@ -166,302 +155,7 @@ public class OfflineWavFileServer extends OfflineFileServer<FileDataMapPoint> {
}
private boolean loadWavData(PamDataBlock dataBlock, OfflineDataLoadInfo offlineDataLoadInfo,
ViewLoadObserver loadObserver) {
// Debug.out.println("OfflineFileServer: Load Wav Data: " + offlineDataLoadInfo.getCurrentObserver().getObserverName() );
OfflineDataMap<FileDataMapPoint> dataMap = getDataMap();
Iterator<FileDataMapPoint> mapIt = dataMap.getListIterator();
FileDataMapPoint mapPoint = findFirstMapPoint(mapIt, offlineDataLoadInfo.getStartMillis(), offlineDataLoadInfo.getEndMillis());
if (openSoundFile(mapPoint.getSoundFile()) == false) {
System.out.println("Could not open .wav sound file " + mapPoint.getSoundFile().getAbsolutePath());
return false;
}
File soundFile;
byteConverter = ByteConverter.createByteConverter(audioFormat);
long currentTime = mapPoint.getStartTime();
long prevFileEnd = mapPoint.getEndTime();
boolean fileGap = false;
int newSamples;
double[][] doubleData;
int nChannels = audioFormat.getChannels();
int blockSamples = Math.max((int) audioFormat.getSampleRate() / 10, 1000);
int frameSize = audioFormat.getFrameSize();
if (frameSize < 0) {
frameSize = audioFormat.getChannels()*audioFormat.getSampleSizeInBits()/8;
}
if (frameSize <= 0) {
System.out.println("The frame size is less than zero " + mapPoint.getSoundFile().getAbsolutePath());
return false;
}
byte[] inputBuffer = new byte[blockSamples * frameSize];
int bytesRead = 0;
long totalSamples = 0;
// long fileSamples = 0;
long millisecondsGaps = 0;
long ms;
RawDataUnit newDataUnit;
long skipped = 0;
if (currentTime < offlineDataLoadInfo.getStartMillis()) {
// need to fast forward in current file.
long skipBytes = (long) (((offlineDataLoadInfo.getStartMillis()-currentTime)*audioFormat.getSampleRate()*audioFormat.getFrameSize())/1000.);
try {
skipped = audioInputStream.skip(skipBytes);
// Debug.out.println("Skipped " + skipped);
} catch (IOException e) {
/**
* The datamap point may be longer than the actual file here ? In any case, with the
* NEMO data which is 5 mins per hour, this get's hit for the file before the
* file we want every time !
*/
// System.out.println("End of audio file " + mapPoint.getSoundFile().getName());
e.printStackTrace();
}
currentTime = offlineDataLoadInfo.getStartMillis();
}
ms = currentTime;
while (ms < offlineDataLoadInfo.getEndMillis() && currentTime < offlineDataLoadInfo.getEndMillis()) {
if (offlineDataLoadInfo.cancel) {
//add the position we got to
offlineDataLoadInfo.setLastLoadInfo(new AquisitionLoadPoint(ms, bytesRead));
break;
}
try {
bytesRead = audioInputStream.read(inputBuffer);
} catch (IOException e) {
e.printStackTrace();
}
if (bytesRead <= 0) {
skipped = 0 ; //reset ot zero because were not skipping anyu bytes here.
/*
* that's the end of that file, so get the next one if there
* is one, if not then break.
*/
if (mapIt.hasNext() == false) {
break;
}
mapPoint = mapIt.next();
fileGap = (mapPoint.getStartTime() - prevFileEnd) > 1000;
// if (fileGap) {
// System.out.println(String.format("Sound file gap %3.3fs from %s to %s",
// (double) (mapPoint.getStartTime()-prevFileEnd) / 1000.,
// PamCalendar.formatTime(prevFileEnd), PamCalendar.formatTime(mapPoint.getStartTime())));
// }
prevFileEnd = mapPoint.getEndTime();
if (!fileGap) { // don't carry on if there is a file gap
if (openSoundFile(mapPoint.getSoundFile()) == false) {
break;
}
// try again to read data.
try {
bytesRead = audioInputStream.read(inputBuffer);
} catch (IOException e) {
e.printStackTrace();
}
if (bytesRead <= 0) {
break;
}
}
}
newSamples = bytesRead / frameSize;
doubleData = new double[nChannels][newSamples];
int convertedSamples = byteConverter.bytesToDouble(inputBuffer, doubleData, bytesRead);
ms = getOfflineRawDataStore().getParentProcess().absSamplesToMilliseconds(totalSamples);
ms = currentTime + (long)(totalSamples * 1000 / (double) audioFormat.getSampleRate());
for (int ichan = 0; ichan < nChannels; ichan++) {
newDataUnit = new RawDataUnit(ms, 1 << ichan, totalSamples, newSamples);
newDataUnit.setFileSamples(totalSamples + skipped / frameSize); //set the number samples into the wav file.
newDataUnit.setRawData(doubleData[ichan], true);
//System.out.println("New wav data: " + PamCalendar.formatDateTime(newDataUnit.getTimeMilliseconds()));
getRawDataBlock().addPamData(newDataUnit);
}
if (fileGap) {
currentTime = mapPoint.getStartTime();
totalSamples = 0;
// fileSamples = 0;
}
totalSamples += newSamples;
// fileSamples += newSamples;
}
// System.out.println("Finished loading wav: " + offlineDataLoadInfo.getCurrentObserver().getObserverName() );
return false;
}
private boolean loadFlacData(PamDataBlock dataBlock, OfflineDataLoadInfo offlineDataLoadInfo,
ViewLoadObserver loadObserver) {
// System.out.println(String.format("Load flac data from "));
/*
* Only seem able to read whole flac files - so read the whole file
* and just output samples of interest to data units. A bit crude,
* but will probably not be too slow.
*/
OfflineDataMap<FileDataMapPoint> dataMap = this.getDataMap();
Iterator<FileDataMapPoint> mapIt = dataMap.getListIterator();
FileDataMapPoint mapPoint;
File soundFile;
mapPoint = findFirstMapPoint(mapIt, offlineDataLoadInfo.getStartMillis(), offlineDataLoadInfo.getEndMillis());
if (mapPoint == null) {
return false;
}
while (mapPoint != null) {
// AudioInputStream inputStream;
// try {
// inputStream = new FlacAudioFileReader().getAudioInputStream(mapPoint.getSoundFile());
// } catch (UnsupportedAudioFileException | IOException e1) {
// // TODO Auto-generated catch block
// e1.printStackTrace();
// }
FileInputStream fileStream;
try {
fileStream = new FileInputStream(mapPoint.getSoundFile());
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
}
FLACDecoder flacDecoder = new FLACDecoder(fileStream);
// Metadata metaData[] = null;
// try {
// metaData = flacDecoder.readMetadata();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
flacDecoder.addPCMProcessor(new FlacPCM(mapPoint, dataBlock, fileStream,
offlineDataLoadInfo, loadObserver));
// StreamInfo streamInfo = flacDecoder.getStreamInfo(); // returns null !
try {
flacDecoder.decode();
} catch (IOException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
return false;
}
if (mapIt.hasNext() == false) {
break;
}
mapPoint = mapIt.next();
if (mapPoint.getStartTime() > offlineDataLoadInfo.getEndMillis()) {
break;
}
}
return true;
}
/**
* Only seem to be able to
* @author doug
*
*/
private class FlacPCM implements PCMProcessor {
private FileInputStream fileStream;
private int frameSize;
private long fileSamples;
private int nChannels;
private FileDataMapPoint mapPoint;
private int totalSamples;
private int sampleRate;
private ViewLoadObserver loadObserver;
private PamRawDataBlock dataBlock;
private OfflineDataLoadInfo offlineDataLoadInfo;
long ms=-1;
public FlacPCM(FileDataMapPoint mapPoint, PamDataBlock dataBlock, FileInputStream fileStream, OfflineDataLoadInfo offlineDataLoadInfo, ViewLoadObserver loadObserver) {
this.mapPoint = mapPoint;
this.dataBlock = (PamRawDataBlock) dataBlock;
this.fileStream = fileStream;
this.loadObserver = loadObserver;
this.offlineDataLoadInfo=offlineDataLoadInfo;
// System.out.printf("New FLAC decoder %s working from %s to %s\n", offlineDataLoadInfo.toString(),
// PamCalendar.formatDBDateTime(offlineDataLoadInfo.getStartMillis()),
// PamCalendar.formatDBDateTime(offlineDataLoadInfo.getEndMillis()));
}
@Override
public void processPCM(ByteData byteData) {
if (offlineDataLoadInfo.cancel) {
try {
fileStream.close();
ms = Math.max(offlineDataLoadInfo.getStartMillis(), ms);
offlineDataLoadInfo.setLastLoadInfo(new AquisitionLoadPoint(ms, -1));
} catch (IOException e) {
e.printStackTrace();
}
return;
}
ms = mapPoint.getStartTime() + (long)totalSamples * 1000L / (long)sampleRate;
// System.out.println(String.format("PCM data at %s samps %d (load %s - %s)", PamCalendar.formatTime2(ms, 3), totalSamples,
// PamCalendar.formatTime2(dataStart, 3), PamCalendar.formatTime2(dataEnd, 3)));
if (ms > offlineDataLoadInfo.getEndMillis()) {
try {
fileStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return;
}
int newSamples = byteData.getLen() / frameSize;
if (ms >= offlineDataLoadInfo.getStartMillis()) {
double[][] doubleData = new double[nChannels][newSamples];
byteConverter.bytesToDouble(byteData.getData(), doubleData, byteData.getLen());
RawDataUnit newDataUnit = null;
for (int ichan = 0; ichan < nChannels; ichan++) {
newDataUnit = new RawDataUnit(ms, 1 << ichan, totalSamples, newSamples);
newDataUnit.setRawData(doubleData[ichan]);
dataBlock.addPamData(newDataUnit);
// GetOutputDataBlock().addPamData(pamDataUnit);
}
}
// System.out.println(String.format("new samps %d at %s", newSamples, PamCalendar.formatTime(ms, 3)));
totalSamples += newSamples;
}
@Override
public void processStreamInfo(StreamInfo streamInfo) {
frameSize = streamInfo.getChannels() * streamInfo.getBitsPerSample() / 8;
byteConverter = ByteConverter.createByteConverter(streamInfo.getBitsPerSample() / 8, false, Encoding.PCM_SIGNED);
fileSamples = streamInfo.getTotalSamples();
nChannels = streamInfo.getChannels();
sampleRate = streamInfo.getSampleRate();
}
}
private boolean openSoundFile(File soundFile) {
try {
audioInputStream = PamAudioSystem.getAudioInputStream(soundFile);
if (audioInputStream == null) return false;
audioFormat = audioInputStream.getFormat();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
public boolean loadData(PamDataBlock dataBlock, OfflineDataLoadInfo offlineLoadDataInfo, ViewLoadObserver loadObserver) {
@ -482,34 +176,17 @@ public class OfflineWavFileServer extends OfflineFileServer<FileDataMapPoint> {
if (mapPoint == null) {
return false;
}
if (mapPoint.getSoundFile().getName().toLowerCase().endsWith(".flac")) {
return loadFlacData(dataBlock, offlineLoadDataInfo, loadObserver);
PamAudioFileLoader audioFile = PamAudioFileManager.getInstance().getAudioLoader(mapPoint.getSoundFile());
if (audioFile==null) {
System.err.println("OfflineWavFileServer: could not find audio loader for mapped sound file: " + mapPoint.getSoundFile());
return false;
}
// if (mapPoint.getSoundFile().getName().toLowerCase().endsWith(".wav")) {
if (isStandardAudio(mapPoint.getSoundFile().getName())) {
return loadWavData(dataBlock, offlineLoadDataInfo, loadObserver);
}
return true;
return audioFile.loadAudioData(this, dataBlock, offlineLoadDataInfo, loadObserver);
}
private String[] standardAudioTypes = {".wav", ".aif", ".aiff"};
/**
* Is it a standard aif or wav audio file which can be opened with the standard reader ?
* @param fileName
* @return
*/
private boolean isStandardAudio(String fileName) {
if (fileName == null) {
return false;
}
fileName = fileName.toLowerCase();
for (int i = 0; i < standardAudioTypes.length; i++) {
if (fileName.endsWith(standardAudioTypes[i])) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,236 @@
package Acquisition.pamAudio;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.AudioFormat.Encoding;
import org.jflac.FLACDecoder;
import org.jflac.PCMProcessor;
import org.jflac.metadata.StreamInfo;
import org.jflac.sound.spi.FlacAudioFileReader;
import org.jflac.util.ByteData;
import Acquisition.offlineFuncs.AquisitionLoadPoint;
import PamDetection.RawDataUnit;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamRawDataBlock;
import PamguardMVC.dataOffline.OfflineDataLoadInfo;
import dataMap.OfflineDataMap;
import dataMap.filemaps.FileDataMapPoint;
import dataMap.filemaps.OfflineFileServer;
import pamScrollSystem.ViewLoadObserver;
import wavFiles.ByteConverter;
/**
* Opens a Flac compressed audio files.
*
* @author Jamie Macaulay, Doug Gillespie
*
*/
public class FlacAudioFile implements PamAudioFileLoader {
/**
* Get the file extensions associated with loading these data.
*/
private ArrayList<String> fileExtensions;
public FlacAudioFile() {
fileExtensions = new ArrayList<String>(Arrays.asList(new String[]{".flac"}));
}
@Override
public ArrayList<String> getFileExtensions() {
return fileExtensions;
}
@Override
public String getName() {
return "FLAC";
}
@Override
public AudioInputStream getAudioStream(File soundFile) {
if (soundFile != null && isFlacFile(soundFile)) {
try {
return new FlacAudioFileReader().getAudioInputStream(soundFile);
}
catch (UnsupportedAudioFileException | IOException e) {
System.err.println("Could not open flac file: " + soundFile.getName());
return null;
}
}
return null;
}
@Override
public boolean loadAudioData(OfflineFileServer offlineFileServer, PamDataBlock dataBlock, OfflineDataLoadInfo offlineDataLoadInfo,
ViewLoadObserver loadObserver) {
// System.out.println(String.format("Load flac data from "));
/*
* Only seem able to read whole flac files - so read the whole file
* and just output samples of interest to data units. A bit crude,
* but will probably not be too slow.
*/
OfflineDataMap<FileDataMapPoint> dataMap = offlineFileServer.getDataMap();
Iterator<FileDataMapPoint> mapIt = dataMap.getListIterator();
FileDataMapPoint mapPoint;
File soundFile;
mapPoint = offlineFileServer.findFirstMapPoint(mapIt, offlineDataLoadInfo.getStartMillis(), offlineDataLoadInfo.getEndMillis());
if (mapPoint == null) {
return false;
}
while (mapPoint != null) {
// AudioInputStream inputStream;
// try {
// inputStream = new FlacAudioFileReader().getAudioInputStream(mapPoint.getSoundFile());
// } catch (UnsupportedAudioFileException | IOException e1) {
// // TODO Auto-generated catch block
// e1.printStackTrace();
// }
FileInputStream fileStream;
try {
fileStream = new FileInputStream(mapPoint.getSoundFile());
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
}
FLACDecoder flacDecoder = new FLACDecoder(fileStream);
// Metadata metaData[] = null;
// try {
// metaData = flacDecoder.readMetadata();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
flacDecoder.addPCMProcessor(new FlacPCM(mapPoint, dataBlock, fileStream,
offlineDataLoadInfo, loadObserver));
// StreamInfo streamInfo = flacDecoder.getStreamInfo(); // returns null !
try {
flacDecoder.decode();
} catch (IOException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
return false;
}
if (mapIt.hasNext() == false) {
break;
}
mapPoint = mapIt.next();
if (mapPoint.getStartTime() > offlineDataLoadInfo.getEndMillis()) {
break;
}
}
return true;
}
/**
* Only seem to be able to
* @author doug
*
*/
private class FlacPCM implements PCMProcessor {
private FileInputStream fileStream;
private int frameSize;
private long fileSamples;
private int nChannels;
private FileDataMapPoint mapPoint;
private int totalSamples;
private int sampleRate;
private ViewLoadObserver loadObserver;
private PamRawDataBlock dataBlock;
private OfflineDataLoadInfo offlineDataLoadInfo;
long ms=-1;
private ByteConverter byteConverter;
public FlacPCM(FileDataMapPoint mapPoint, PamDataBlock dataBlock, FileInputStream fileStream, OfflineDataLoadInfo offlineDataLoadInfo, ViewLoadObserver loadObserver) {
this.mapPoint = mapPoint;
this.dataBlock = (PamRawDataBlock) dataBlock;
this.fileStream = fileStream;
this.loadObserver = loadObserver;
this.offlineDataLoadInfo=offlineDataLoadInfo;
// System.out.printf("New FLAC decoder %s working from %s to %s\n", offlineDataLoadInfo.toString(),
// PamCalendar.formatDBDateTime(offlineDataLoadInfo.getStartMillis()),
// PamCalendar.formatDBDateTime(offlineDataLoadInfo.getEndMillis()));
}
@Override
public void processPCM(ByteData byteData) {
if (offlineDataLoadInfo.cancel) {
try {
fileStream.close();
ms = Math.max(offlineDataLoadInfo.getStartMillis(), ms);
offlineDataLoadInfo.setLastLoadInfo(new AquisitionLoadPoint(ms, -1));
} catch (IOException e) {
e.printStackTrace();
}
return;
}
ms = mapPoint.getStartTime() + (long)totalSamples * 1000L / (long)sampleRate;
// System.out.println(String.format("PCM data at %s samps %d (load %s - %s)", PamCalendar.formatTime2(ms, 3), totalSamples,
// PamCalendar.formatTime2(dataStart, 3), PamCalendar.formatTime2(dataEnd, 3)));
if (ms > offlineDataLoadInfo.getEndMillis()) {
try {
fileStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return;
}
int newSamples = byteData.getLen() / frameSize;
if (ms >= offlineDataLoadInfo.getStartMillis()) {
double[][] doubleData = new double[nChannels][newSamples];
byteConverter.bytesToDouble(byteData.getData(), doubleData, byteData.getLen());
RawDataUnit newDataUnit = null;
for (int ichan = 0; ichan < nChannels; ichan++) {
newDataUnit = new RawDataUnit(ms, 1 << ichan, totalSamples, newSamples);
newDataUnit.setRawData(doubleData[ichan]);
dataBlock.addPamData(newDataUnit);
// GetOutputDataBlock().addPamData(pamDataUnit);
}
}
// System.out.println(String.format("new samps %d at %s", newSamples, PamCalendar.formatTime(ms, 3)));
totalSamples += newSamples;
}
@Override
public void processStreamInfo(StreamInfo streamInfo) {
frameSize = streamInfo.getChannels() * streamInfo.getBitsPerSample() / 8;
byteConverter = ByteConverter.createByteConverter(streamInfo.getBitsPerSample() / 8, false, Encoding.PCM_SIGNED);
fileSamples = streamInfo.getTotalSamples();
nChannels = streamInfo.getChannels();
sampleRate = streamInfo.getSampleRate();
}
}
private static boolean isFlacFile(File file) {
String name = file.getName();
if (name.length() < 5) {
return false;
}
String end = name.substring(name.length()-5).toLowerCase();
return (end.equals(".flac"));
}
}

View File

@ -0,0 +1,52 @@
package Acquisition.pamAudio;
import java.io.File;
import java.util.ArrayList;
import javax.sound.sampled.AudioInputStream;
import PamguardMVC.PamDataBlock;
import PamguardMVC.dataOffline.OfflineDataLoadInfo;
import dataMap.filemaps.OfflineFileServer;
import pamScrollSystem.ViewLoadObserver;
/**
* Interface for PAMGuard opening a sound file.
*
* @author Jamie Macaulay
*
*/
public interface PamAudioFile {
/**
* Get file extensions associated with the file type
* @return a list of the file extensions (e.g.".wav")
*/
public ArrayList<String> getFileExtensions();
/**
* Get the name of the file.
* @return the name of the file
*/
public String getName();
/**
* Get the audio stream for the file
* @return the audio input stream.
*/
public AudioInputStream getAudioStream(File soundFile);
/**
* Load a section of audio data.
* @param dataBlock - the data block.
* @param offlineFileServer - the offline file server.
* @param offlineDataLoadInfo - the offline data load info.
* @return true if the file has been loaded
*/
boolean loadAudioData(OfflineFileServer offlineFileServer, PamDataBlock dataBlock,
OfflineDataLoadInfo offlineDataLoadInfo, ViewLoadObserver loadObserver);
}

View File

@ -0,0 +1,87 @@
package Acquisition.pamAudio;
import java.io.File;
import org.apache.commons.io.FilenameUtils;
import PamUtils.PamFileFilter;
/**
* The file filter for audio files compatible with PAMGuard.
* <p>
* All file extensions from all PamAudioFileLoaders in PamAudioManager are
* accepted by the file filter. The file filter will aslo discard compressed
* audio files if there exists a raw audio file of the same name.
*
* @author Jamie Macaulay
*
*/
public class PamAudioFileFilter extends PamFileFilter {
private PamAudioFileManager pamAudioFileManager;
public PamAudioFileFilter(PamAudioFileManager pamAudioFileManager) {
/**
* PamfileFilter converts everything to lower case, so no need to have upper and lower versions of
* each ending.
*/
super("Audio Files", ".wav");
this.pamAudioFileManager = pamAudioFileManager;
//add all the file types.
for (int i=0; i<pamAudioFileManager.getAudioFileLoaders().size(); i++) {
for (int j=0; j<pamAudioFileManager.getAudioFileLoaders().get(i).getFileExtensions().size(); j++) {
if (!pamAudioFileManager.getAudioFileLoaders().get(i).getFileExtensions().get(j).equals(".wav")){
// already added .wav but add all other file extensions.
addFileType(pamAudioFileManager.getAudioFileLoaders().get(i).getFileExtensions().get(j));
}
};
}
}
public PamAudioFileFilter() {
this(PamAudioFileManager.getInstance());
}
@Override
public boolean accept(File f) {
//System.out.println("Accept?: " + super.accept(f) + " " + f.getName() );
if (super.accept(f)) {
//need to do an extra check here. Is there a .wav file or other raw wav file
//that has the same name as another file type? If so we do not want both a compressed
//and uncompressed file to be read - instead ignore the compressed file and only accept
//the wav file.
if (pamAudioFileManager.isExtension(f, pamAudioFileManager.getRawFileLoader()) || f.isDirectory()) {
//if a raw file then all OK.
//System.out.println("Accepted file 1: " + f.getName());
return true;
}
String blankFileName = FilenameUtils.removeExtension(f.getAbsolutePath());
//System.out.println("Blank file 1: " + blankFileName);
File rawfile;
for (int i=0; i<pamAudioFileManager.getRawFileLoader().getFileExtensions().size(); i++) {
rawfile = new File(blankFileName + pamAudioFileManager.getRawFileLoader().getFileExtensions().get(i));
//System.out.println("Raw file 1: " + blankFileName);
if (rawfile.exists()) {
//the raw file will have been picked up by the file filter already or subsequently. So do not
//use the other file.
return false;
}
}
//System.out.println("Accepted file 2: " + f.getName());
return true;
}
else return false;
}
}

View File

@ -0,0 +1,52 @@
package Acquisition.pamAudio;
import java.io.File;
import java.util.ArrayList;
import javax.sound.sampled.AudioInputStream;
import PamguardMVC.PamDataBlock;
import PamguardMVC.dataOffline.OfflineDataLoadInfo;
import dataMap.filemaps.OfflineFileServer;
import pamScrollSystem.ViewLoadObserver;
/**
* Interface for PAMGuard opening a sound file.
*
* @author Jamie Macaulay
*
*/
public interface PamAudioFileLoader {
/**
* Get file extensions associated with the file type
* @return a list of the file extensions (e.g.".wav")
*/
public ArrayList<String> getFileExtensions();
/**
* Get the name of the file.
* @return the name of the file
*/
public String getName();
/**
* Get the audio stream for the file
* @return the audio input stream.
*/
public AudioInputStream getAudioStream(File soundFile);
/**
* Load a section of audio data.
* @param dataBlock - the data block.
* @param offlineFileServer - the offline file server.
* @param offlineDataLoadInfo - the offline data load info.
* @return true if the file has been loaded
*/
public boolean loadAudioData(OfflineFileServer offlineFileServer, PamDataBlock dataBlock,
OfflineDataLoadInfo offlineDataLoadInfo, ViewLoadObserver loadObserver);
}

View File

@ -0,0 +1,173 @@
package Acquisition.pamAudio;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.UnsupportedAudioFileException;
import org.codehaus.plexus.util.FileUtils;
/**
* Central class for opening sound files.
* <p>
* PamAudioFieManager holds a list of PamAudioFile classes. Each PamAudioFile
* can open a certain type of sound file e.g. flac or raw wav files.
* PamAudioFieManager provides fucntions around the list to open files, provide
* file filters etc.
*
* @author Jamie Macaulay
*
*/
public class PamAudioFileManager {
/**
* Instance of the PamAudioFieManager.
*/
private static PamAudioFileManager pamAudioFileManager;
/**
* The pam audio file types.
*/
private ArrayList<PamAudioFileLoader> pamAudioFileTypes;
/**
* The default file loader for raw files. A reference to this is kept so that
* file loaders can preferentially select raw files over compressed file if they
* have the same name e.g. if using a folder of uncompressed SoundTrap data that
* contains both .sud and .wav files then only .wav files should be read.
*/
private WavAudioFile rawFileLoader;
public PamAudioFileManager() {
pamAudioFileTypes = new ArrayList<PamAudioFileLoader>();
/***** Add new audio file types here *****/
pamAudioFileTypes.add(rawFileLoader = new WavAudioFile());
pamAudioFileTypes.add(new FlacAudioFile());
pamAudioFileTypes.add(new SudAudioFile());
}
/**
* Get the audio file loader for a file.
*
* @param soundFile - the sound file
* @return the audio file loader.
*/
public PamAudioFileLoader getAudioLoader(File soundFile) {
for (int i = 0; i < pamAudioFileTypes.size(); i++) {
if (isExtension(soundFile, pamAudioFileTypes.get(i))) {
return pamAudioFileTypes.get(i);
}
}
return null;
}
/**
* Check if a file has an extension supported by a PamAudioFile.
*
* @param file
* @param pamAudioFile
*/
public boolean isExtension(File file, PamAudioFileLoader pamAudioFile) {
for (int i = 0; i < pamAudioFile.getFileExtensions().size(); i++) {
if (isSoundFile(file, pamAudioFile.getFileExtensions().get(i))) {
return true;
}
}
return false;
}
public boolean isSoundFile(File soundFile, String soundExtension) {
String extension = FileUtils.getExtension(soundFile.getName());
//System.out.println("Sound Extension: " + soundExtension + " File extension: " + extension);
return (soundExtension.equals(extension) || soundExtension.equals("." + extension));
}
/**
* Open an audio input stream. If the file is a Wav file, then it will attempt
* to read the file with PAMGuards bespoke audio stream reader. This includes
* support for wav files which are > 2GByte in size and also works for floating
* point 32 bit files (which the Java one doesn't). If that fails, or if its not
* a wav file, then the standard java AudioInputStream is used.
*
* @param file file to open
* @return a new audio input stream
* @throws UnsupportedAudioFileException thrown if it can't understand the audio
* format.
* @throws IOException
*/
public AudioInputStream getAudioInputStream(File file) throws UnsupportedAudioFileException, IOException {
// if (file != null && isWavFile(file) && file.length() > largeFileSize) {
if (file.exists() == false) {
System.err.println("PamAudioFileManager: the input file was null");
return null;
}
AudioInputStream stream = null;
for (int i = 0; i < pamAudioFileTypes.size(); i++) {
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);
if (pamAudioFileTypes != null) {
break;
}
}
}
if (stream == null) {
// have a punt at opening as a default audiostream
//System.out.println("Try default stream for: " +file.getName() );
stream = new WavAudioFile().getAudioStream(file);
}
if (stream == null) {
System.err.println("PamAudioFileManager: unable to open an AudioStream for " + file.getName());
}
return stream;
}
/**
* Get the instance of the PamAudioManager
*/
public static PamAudioFileManager getInstance() {
if (pamAudioFileManager == null) {
pamAudioFileManager = new PamAudioFileManager();
}
return pamAudioFileManager;
}
/**
* Get the audio file filter
*
* @return the audio file filter.
*/
public PamAudioFileFilter getAudioFileFilter() {
return new PamAudioFileFilter(this);
}
/**
* Get the current audio file
*
* @return a list oif the current audio loaders.
*/
public ArrayList<PamAudioFileLoader> getAudioFileLoaders() {
return this.pamAudioFileTypes;
}
/**
* Get the default file loader for raw files.
* @return the default file loader for raw files.
*/
public WavAudioFile getRawFileLoader() {
return rawFileLoader;
}
}

View File

@ -10,7 +10,13 @@ import javax.sound.sampled.UnsupportedAudioFileException;
//import org.kc7bfi.jflac.sound.spi.FlacAudioFileReader;
import org.jflac.sound.spi.FlacAudioFileReader;
/**
* Now replaced with PamAudioFileManager.
*
* @author Jamie Macaulay
*
*/
@Deprecated
public class PamAudioSystem {
private static final long largeFileSize = 01L<<31;
@ -42,7 +48,7 @@ public class PamAudioSystem {
return new FlacAudioFileReader().getAudioInputStream(file);
}
catch (UnsupportedAudioFileException e) {
}
}
else if (file != null && isSudFile(file)) {
@ -50,14 +56,15 @@ public class PamAudioSystem {
return new SudAudioFileReader().getAudioInputStream(file);
}
catch (UnsupportedAudioFileException e) {
//e.printStackTrace();
}
}
try {
return AudioSystem.getAudioInputStream(file);
return AudioSystem.getAudioInputStream(file);
}
catch (Exception e) {
System.out.println("Error in audio file " + file.getName() + ": " + e.getMessage());
e.printStackTrace();
return null;
}
}
@ -93,10 +100,10 @@ public class PamAudioSystem {
*/
private static boolean isSudFile(File file) {
String name = file.getName();
if (name.length() < 5) {
if (name.length() < 4) {
return false;
}
String end = name.substring(name.length()-5).toLowerCase();
String end = name.substring(name.length()-4).toLowerCase();
return (end.equals(".sud"));
}

View File

@ -0,0 +1,63 @@
package Acquisition.pamAudio;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
* Opens a .sud audio file.
* <p>
* Sud files contain X3 compressed audio data. The sud
* file reader opens files, creating a map of the file and saving
* the map as a.sudx file so it can be read more rapidly when the file
* is next accessed.
* <p>
* The SudioAudioInput stream fully implements AudioInputStream and so
* sud files can be accessed using much of the same code as .wav files.
*
* @author Jamie Macaulay
*
*/
public class SudAudioFile extends WavAudioFile {
public SudAudioFile() {
super();
fileExtensions = new ArrayList<String>(Arrays.asList(new String[]{".sud"}));
}
@Override
public String getName() {
return "SUD";
}
@Override
public AudioInputStream getAudioStream(File soundFile) {
if (soundFile.exists() == false) {
System.err.println("The sud file does not exist: " + soundFile);
return null;
}
if (soundFile != null) {
try {
return new SudAudioFileReader().getAudioInputStream(soundFile);
}
// don't do anything and it will try the built in Audiosystem
catch (UnsupportedAudioFileException e) {
System.err.println("Could not open sud file: not a supported file " + soundFile.getName());
e.printStackTrace();
} catch (IOException e) {
System.err.println("Could not open sud file: IO Exception: " + soundFile.getName());
e.printStackTrace();
}
}
return null;
}
}

View File

@ -2,6 +2,7 @@ package Acquisition.pamAudio;
import java.io.File;
import java.io.IOException;
import org.pamguard.x3.sud.*;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.UnsupportedAudioFileException;
@ -13,11 +14,41 @@ import javax.sound.sampled.UnsupportedAudioFileException;
*
*/
public class SudAudioFileReader {
/**
* The current sud audio input stream
*/
SudAudioInputStream sudAudioInputStream;
/**
* Parameters for opening .sud files.
*/
SudParams sudParams;
public SudAudioFileReader() {
sudParams = new SudParams();
//set up the sud params for default. i.e. just read files and
//don't save any decompressed or meta data.
sudParams.saveWav = false;
sudParams.saveMeta = false;
sudParams.zeroPad = true;
}
/**
* Get the audio input streamn.
* @param file - the .sud file to open.
* @return the sud AudioStream.
* @throws UnsupportedAudioFileException
* @throws IOException
*/
public AudioInputStream getAudioInputStream(File file) throws UnsupportedAudioFileException, IOException {
// TODO Auto-generated method stub
return null;
try {
sudAudioInputStream = SudAudioInputStream.openInputStream(file, sudParams, false);
} catch (Exception e) {
e.printStackTrace();
}
return sudAudioInputStream;
}
}

View File

@ -0,0 +1,250 @@
package Acquisition.pamAudio;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import org.codehaus.plexus.util.FileUtils;
import Acquisition.offlineFuncs.AquisitionLoadPoint;
import PamDetection.RawDataUnit;
import PamguardMVC.PamDataBlock;
import PamguardMVC.dataOffline.OfflineDataLoadInfo;
import dataMap.OfflineDataMap;
import dataMap.filemaps.FileDataMapPoint;
import dataMap.filemaps.OfflineFileServer;
import pamScrollSystem.ViewLoadObserver;
import wavFiles.ByteConverter;
/**
* Wav audio file - opens any raw audio file.
* <p>
* This should be used a standard class for opening audio files
*
* @author Jamie Macaulay, Doug Gillepsie
*
*/
public class WavAudioFile implements PamAudioFileLoader {
/**
* The audio input stream of the last loaded file.
*/
private AudioInputStream audioInputStream;
/**
* The audioformat of the last laoded file.
*/
private AudioFormat audioFormat;
/**
* Get the file extensions associated with loading these data.
*/
protected ArrayList<String> fileExtensions;
public WavAudioFile() {
fileExtensions = new ArrayList<String>(Arrays.asList(new String[]{".wav", ".aif", ".aiff"}));
}
@Override
public ArrayList<String> getFileExtensions() {
return fileExtensions;
}
@Override
public String getName() {
return "WAV";
}
@Override
public boolean loadAudioData(OfflineFileServer offlineFileServer, PamDataBlock dataBlock, OfflineDataLoadInfo offlineDataLoadInfo, ViewLoadObserver loadObserver) {
// Debug.out.println("OfflineFileServer: Load Wav Data: " + offlineDataLoadInfo.getCurrentObserver().getObserverName() );
OfflineDataMap<FileDataMapPoint> dataMap = offlineFileServer.getDataMap();
Iterator<FileDataMapPoint> mapIt = dataMap.getListIterator();
FileDataMapPoint mapPoint = offlineFileServer.findFirstMapPoint(mapIt, offlineDataLoadInfo.getStartMillis(), offlineDataLoadInfo.getEndMillis());
if (openSoundFile(mapPoint.getSoundFile()) == false) {
System.out.println("Could not open .wav sound file " + mapPoint.getSoundFile().getAbsolutePath());
return false;
}
File soundFile;
ByteConverter byteConverter = ByteConverter.createByteConverter(audioFormat);
long currentTime = mapPoint.getStartTime();
long prevFileEnd = mapPoint.getEndTime();
boolean fileGap = false;
int newSamples;
double[][] doubleData;
int nChannels = audioFormat.getChannels();
int blockSamples = Math.max((int) audioFormat.getSampleRate() / 10, 1000);
int frameSize = audioFormat.getFrameSize();
if (frameSize < 0) {
frameSize = audioFormat.getChannels()*audioFormat.getSampleSizeInBits()/8;
}
if (frameSize <= 0) {
System.out.println("The frame size is less than zero " + mapPoint.getSoundFile().getAbsolutePath());
return false;
}
byte[] inputBuffer = new byte[blockSamples * frameSize];
int bytesRead = 0;
long totalSamples = 0;
// long fileSamples = 0;
long millisecondsGaps = 0;
long ms;
RawDataUnit newDataUnit;
long skipped = 0;
if (currentTime < offlineDataLoadInfo.getStartMillis()) {
// need to fast forward in current file.
long skipBytes = (long) (((offlineDataLoadInfo.getStartMillis()-currentTime)*audioFormat.getSampleRate()*audioFormat.getFrameSize())/1000.);
try {
//System.out.println("Skipped " + skipped+ " " + skipBytes + " " + audioInputStream.available());
skipped = audioInputStream.skip(skipBytes);
//System.out.println("Offline " + (offlineDataLoadInfo.getStartMillis()-currentTime) + " ms : frame size: " + audioFormat.getFrameSize());
} catch (IOException e) {
/**
* The datamap point may be longer than the actual file here ? In any case, with the
* NEMO data which is 5 mins per hour, this get's hit for the file before the
* file we want every time !
*/
// System.out.println("End of audio file " + mapPoint.getSoundFile().getName());
e.printStackTrace();
}
currentTime = offlineDataLoadInfo.getStartMillis();
}
ms = currentTime;
while (ms < offlineDataLoadInfo.getEndMillis() && currentTime < offlineDataLoadInfo.getEndMillis()) {
if (offlineDataLoadInfo.cancel) {
//add the position we got to
offlineDataLoadInfo.setLastLoadInfo(new AquisitionLoadPoint(ms, bytesRead));
break;
}
try {
if (inputBuffer.length<audioInputStream.available()) {
bytesRead = audioInputStream.read(inputBuffer);
}
else {
bytesRead = 0; //force new file to load.
}
} catch (IOException e) {
e.printStackTrace();
}
if (bytesRead <= 0) {
skipped = 0 ; //reset ot zero because were not skipping anyu bytes here.
/*
* that's the end of that file, so get the next one if there
* is one, if not then break.
*/
if (mapIt.hasNext() == false) {
break;
}
mapPoint = mapIt.next();
fileGap = (mapPoint.getStartTime() - prevFileEnd) > 1000;
// if (fileGap) {
// System.out.println(String.format("Sound file gap %3.3fs from %s to %s",
// (double) (mapPoint.getStartTime()-prevFileEnd) / 1000.,
// PamCalendar.formatTime(prevFileEnd), PamCalendar.formatTime(mapPoint.getStartTime())));
// }
prevFileEnd = mapPoint.getEndTime();
if (!fileGap) { // don't carry on if there is a file gap
if (openSoundFile(mapPoint.getSoundFile()) == false) {
break;
}
// try again to read data.
try {
bytesRead = audioInputStream.read(inputBuffer);
} catch (IOException e) {
e.printStackTrace();
}
if (bytesRead <= 0) {
break;
}
}
}
newSamples = bytesRead / frameSize;
doubleData = new double[nChannels][newSamples];
int convertedSamples = byteConverter.bytesToDouble(inputBuffer, doubleData, bytesRead);
ms = offlineFileServer.getOfflineRawDataStore().getParentProcess().absSamplesToMilliseconds(totalSamples);
ms = currentTime + (long)(totalSamples * 1000 / (double) audioFormat.getSampleRate());
for (int ichan = 0; ichan < nChannels; ichan++) {
newDataUnit = new RawDataUnit(ms, 1 << ichan, totalSamples, newSamples);
newDataUnit.setFileSamples(totalSamples + skipped / frameSize); //set the number samples into the wav file.
newDataUnit.setRawData(doubleData[ichan], true);
//System.out.println("New wav data: " + PamCalendar.formatDateTime(newDataUnit.getTimeMilliseconds()));
offlineFileServer.getRawDataBlock().addPamData(newDataUnit);
}
if (fileGap) {
currentTime = mapPoint.getStartTime();
totalSamples = 0;
// fileSamples = 0;
}
totalSamples += newSamples;
// fileSamples += newSamples;
}
// System.out.println("Finished loading wav: " + offlineDataLoadInfo.getCurrentObserver().getObserverName() );
return false;
}
/**
* Open a sound file.
* @param soundFile
* @return
*/
private boolean openSoundFile(File soundFile) {
audioInputStream = getAudioStream(soundFile);
if (audioInputStream == null) return false;
audioFormat = audioInputStream.getFormat();
return true;
}
@Override
public AudioInputStream getAudioStream(File soundFile) {
if (soundFile.exists() == false) return null;
if (soundFile != null && isSoundFile(soundFile)) {
try {
return WavFileInputStream.openInputStream(soundFile);
}
catch (UnsupportedAudioFileException | IOException e) {
e.printStackTrace();
// don't do anything and it will try the built in Audiosystem
System.err.println("Could not open wav file: trying default audio stream: " + soundFile.getName());
}
}
try {
return AudioSystem.getAudioInputStream(soundFile);
}
catch (Exception e) {
System.out.println("Error in audio file " + soundFile.getName() + ": " + e.getMessage());
e.printStackTrace();
return null;
}
}
public boolean isSoundFile(File soundFile) {
String extension = FileUtils.getExtension(soundFile.getName());
return (extension.equals(".wav"));
}
}

View File

@ -33,8 +33,8 @@ import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import Acquisition.pamAudio.PamAudioFileFilter;
import PamDetection.RawDataUnit;
import PamUtils.PamAudioFileFilter;
import PamUtils.PamFileChooser;

View File

@ -0,0 +1,221 @@
package Localiser.algorithms.timeDelayLocalisers.bearingLoc;
import Localiser.DelayMeasurementParams;
import PamController.SettingsPane;
import fftFilter.FFTFilterParams;
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import pamViewFX.fxNodes.PamButton;
import pamViewFX.fxNodes.PamGridPane;
import pamViewFX.fxNodes.PamSpinner;
import pamViewFX.fxNodes.pamDialogFX.PamDialogFX;
import pamViewFX.fxNodes.utilityPanes.SimpleFilterPaneFX;
public class DelayOptionsPaneFX extends SettingsPane<DelayMeasurementParams> {
private CheckBox filterBearings, envelopeBearings, useLeadingEdge, upSample;
private PamButton filterSettings;
private Label filterDescription;
/**
* The current delay measurement parameters.
*/
private DelayMeasurementParams delayMeasurementParams;
/**
* Check box for restricting samples.
*/
private CheckBox restrictSamples;
/**
* Restrict the number of samples.
*/
private TextField restrictSamplesField;
private PamSpinner<Integer> upSampleSpinner;
private SimpleFilterPaneFX simpleFilterPane = new SimpleFilterPaneFX();
public DelayOptionsPaneFX() {
super(null);
// TODO Auto-generated constructor stub
}
public Pane createDelayOptionsPane() {
int gridy=0;
PamGridPane mainPanel = new PamGridPane();
// mainPanel.setBorder(new TitledBorder("Delay measurement options"));
mainPanel.add(filterBearings = new CheckBox("Filter data before measurement"), 0,gridy);
PamGridPane.setColumnSpan(filterBearings, 2);
filterBearings.setOnAction((action)->{
enableControls();
});
gridy++;
mainPanel.add(filterSettings = new PamButton("Settings"), 0,gridy);
filterSettings.setOnAction((action)->{
FFTFilterParams newParams = simpleFilterPane.getParams(delayMeasurementParams.delayFilterParams);
if (newParams != null) {
delayMeasurementParams.delayFilterParams = newParams.clone();
describeFilter();
}
});
gridy++;
mainPanel.add(filterDescription = new Label(" "), 0,gridy);
gridy++;
mainPanel.add(upSample = new CheckBox("Up sample data x2"), 0,gridy);
upSample.setTooltip(new Tooltip("Up sampling data to a higher frequency can improve timing accuracy for narrow band clicks (i.e. harbour porpoise)"));
gridy++;
//SpinnerListModel spinnerModel = new SpinnerListModel(Arrays.asList(new Integer[] {2,3,4})); //restrict the spinenr options.
mainPanel.add(upSampleSpinner = new PamSpinner<Integer>(2,4,2,1), 0,gridy);
upSampleSpinner.valueProperty().addListener((obsval, oldVa, newVal)->{
upSample.setText("Up sample data x" + this.upSampleSpinner.getValue());
});
gridy++;
mainPanel.add(envelopeBearings = new CheckBox("Use waveform envelope"), 0, gridy);
gridy++;
mainPanel.add(new Label(" "), 0, gridy);
gridy++;
mainPanel.add(new Label(" "), 0, gridy);
gridy++;
mainPanel.add(useLeadingEdge = new CheckBox("Use envelope leading edge only"), 0, gridy);
gridy++;
PamGridPane.setColumnSpan(useLeadingEdge, 2);
envelopeBearings.setOnAction((action)->{
enableControls();
});
envelopeBearings.setOnAction((action)->{
enableControls();
});
PamGridPane.setColumnSpan(envelopeBearings, 2);
//restrict
mainPanel.add(restrictSamples = new CheckBox("Restrict length"), 0, gridy);
gridy++;
PamGridPane.setColumnSpan(restrictSamples, 2);
restrictSamples.setOnAction((action)->{
enableControls();
});
mainPanel.add(restrictSamplesField = new TextField(), 2, gridy);
restrictSamples.setTooltip(new Tooltip("In environments where echoes are an issue restricting inital samples of detections "
+ "(e.g. click snippets) is a simple but effective way to increase the accuracy of time delay calculations. "
+ "WARNING: Remember that this must cover the potential time delay in grouped detections "));
filterBearings.setTooltip(new Tooltip("Filter data prior to bearing measurement to imporve accuracy"));
filterSettings.setTooltip(new Tooltip("Setup filter options"));
envelopeBearings.setTooltip(new Tooltip("Using the envelope can provide more accurate bearings for some narrowband pulses"));
filterDescription.setTooltip(new Tooltip("Current filter settings"));
useLeadingEdge.setTooltip(new Tooltip("For long pulses, or where there are echoes, restrict the calculation to the leading edge of the envelope"));
BorderPane pane = new BorderPane();
pane.setCenter(mainPanel);
return pane;
}
private void enableControls() {
filterSettings.setDisable(!filterBearings.isSelected());
filterDescription.setDisable(!filterBearings.isSelected());
useLeadingEdge.setDisable(!envelopeBearings.isSelected());
restrictSamplesField.setDisable(!restrictSamples.isSelected());
if (!envelopeBearings.isSelected()) {
// useLeadingEdge.setSelected(false);
}
}
private void describeFilter() {
if (delayMeasurementParams == null || delayMeasurementParams.delayFilterParams == null) {
filterDescription.setText("No filter");
return;
}
filterDescription.setText(delayMeasurementParams.delayFilterParams.toString());
}
@Override
public void setParams(DelayMeasurementParams delayMeasurementParams) {
this.delayMeasurementParams = delayMeasurementParams;
filterBearings.setSelected(delayMeasurementParams.filterBearings);
upSample.setSelected(delayMeasurementParams.getUpSample() > 1);
envelopeBearings.setSelected(delayMeasurementParams.envelopeBearings);
useLeadingEdge.setSelected(delayMeasurementParams.useLeadingEdge);
restrictSamples.setSelected(delayMeasurementParams.useRestrictedBins);
restrictSamplesField.setText(String.format("%d", delayMeasurementParams.restrictedBins));
upSample.setText("Up sample data x" + this.upSampleSpinner.getValue());
enableControls();
describeFilter();
}
@Override
public DelayMeasurementParams getParams(DelayMeasurementParams delayMeasurementParams) {
delayMeasurementParams.delayFilterParams = this.delayMeasurementParams.delayFilterParams;
delayMeasurementParams.filterBearings = filterBearings.isSelected();
delayMeasurementParams.setUpSample(upSample.isSelected() ? ((Integer) this.upSampleSpinner.getValue()).intValue() : 1);
delayMeasurementParams.envelopeBearings = envelopeBearings.isSelected();
delayMeasurementParams.useLeadingEdge = useLeadingEdge.isSelected() && delayMeasurementParams.envelopeBearings;
delayMeasurementParams.useRestrictedBins=this.restrictSamples.isSelected();
try {
delayMeasurementParams.restrictedBins=Integer.valueOf(this.restrictSamplesField.getText());
}
catch(Exception e) {
PamDialogFX.showWarning(null, "Delay measurement settings", "The entry in the samples text field is invalid.");
return null;
}
if (delayMeasurementParams.useRestrictedBins && delayMeasurementParams.restrictedBins<10) {
PamDialogFX.showWarning(null, "Delay measurement settings", "The entry in the samples text field is invalid. It must be >= 10");
return null;
}
if (delayMeasurementParams.filterBearings && delayMeasurementParams.delayFilterParams == null) {
PamDialogFX.showWarning(null, "Delay measurement settings", "Filter parameters have not been set");
return null;
}
return null;
}
@Override
public String getName() {
return "Delay Measurment Params";
}
@Override
public Node getContentNode() {
// TODO Auto-generated method stub
return null;
}
@Override
public void paneInitialized() {
// TODO Auto-generated method stub
}
}

File diff suppressed because it is too large Load Diff

View File

@ -765,6 +765,7 @@ final public class PamModel implements PamModelInterface, PamSettings {
mi.addDependency(new PamDependency(ClickDetection.class, "clickDetector.ClickControl"));
mi.setToolTipText("Classifies clicks based on an ideal template to match and a template to reject. "
+ "An example of this is to classify beaked whale clicks in an environment with dolphin clicks");
mi.addGUICompatabilityFlag(PamGUIManager.FX);
mi.setModulesMenuGroup(classifierGroup);

View File

@ -1,5 +1,7 @@
package PamUtils;
import PamUtils.PamFileFilter;
public class PamAudioFileFilter extends PamFileFilter {
public PamAudioFileFilter() {

View File

@ -33,7 +33,7 @@ public class PamFileFilter extends javax.swing.filechooser.FileFilter implements
private String prefix = null;
private boolean acceptFolders = true;
protected boolean acceptFolders = true;
public PamFileFilter(String description, String defExtension) {

View File

@ -6,6 +6,7 @@ import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import Acquisition.pamAudio.PamAudioFileManager;
import Acquisition.pamAudio.PamAudioSystem;
import PamController.PamGUIManager;
import javafx.beans.property.BooleanProperty;
@ -64,7 +65,7 @@ public class WavFileType extends File {
*/
private AudioFormat getAudioFormat(File file) {
try {
AudioInputStream audioStream = PamAudioSystem.getAudioInputStream(file);
AudioInputStream audioStream = PamAudioFileManager.getInstance().getAudioInputStream(file);
AudioFormat audioFormat = audioStream.getFormat();

View File

@ -2,7 +2,7 @@ package PamUtils.worker.filelist;
import java.io.File;
import PamUtils.PamAudioFileFilter;
import Acquisition.pamAudio.PamAudioFileFilter;
/**
* Worker which extracts acoustic files from a folder.

View File

@ -120,8 +120,8 @@ public class binaryUIDFunctions {
}
}
} catch (Exception e) {
System.out.println("Error reading binary UID data from log file");
e.printStackTrace();
System.out.println("Error reading binary UID data from log file" + logFileData);
// e.printStackTrace();
}
// try (BufferedReader br = new BufferedReader(new FileReader(logFileData))) {
@ -531,10 +531,12 @@ public class binaryUIDFunctions {
out.close();
}
} catch (TransformerException e) {
e.printStackTrace();
System.err.println(e.getMessage());
// e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
System.err.println(e.getMessage());
// e.printStackTrace();
return false;
}
return true;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -561,3 +561,15 @@
-fx-icon-color: black;
}
/********************************************
* *
* Spinner *
* *
*********************************************/
.spinner {
-fx-pref-width: 100px;
}

View File

@ -977,4 +977,13 @@
-fx-icon-color: black;
}
/********************************************
* *
* Spinner *
* *
*********************************************/
.spinner {
-fx-pref-width: 100px;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,779 @@
{
-color-dark: #010409;
-color-light: #ffffff;
-color-base-0: #f0f6fc;
-color-base-1: #c9d1d9;
-color-base-2: #b1bac4;
-color-base-3: #8b949e;
-color-base-4: #6e7681;
-color-base-5: #484f58;
-color-base-6: #30363d;
-color-base-7: #21262d;
-color-base-8: #161b22;
-color-base-9: #0d1117;
-color-accent-0: #cae8ff;
-color-accent-1: #a5d6ff;
-color-accent-2: #79c0ff;
-color-accent-3: #58a6ff;
-color-accent-4: #388bfd;
-color-accent-5: #1f6feb;
-color-accent-6: #1158c7;
-color-accent-7: #0d419d;
-color-accent-8: #0c2d6b;
-color-accent-9: #051d4d;
-color-success-0: #aff5b4;
-color-success-1: #7ee787;
-color-success-2: #56d364;
-color-success-3: #3fb950;
-color-success-4: #2ea043;
-color-success-5: #238636;
-color-success-6: #196c2e;
-color-success-7: #0f5323;
-color-success-8: #033a16;
-color-success-9: #04260f;
-color-warning-0: #f8e3a1;
-color-warning-1: #f2cc60;
-color-warning-2: #e3b341;
-color-warning-3: #d29922;
-color-warning-4: #bb8009;
-color-warning-5: #9e6a03;
-color-warning-6: #845306;
-color-warning-7: #693e00;
-color-warning-8: #4b2900;
-color-warning-9: #341a00;
-color-danger-0: #ffdcd7;
-color-danger-1: #ffc1ba;
-color-danger-2: #ffa198;
-color-danger-3: #ff7b72;
-color-danger-4: #f85149;
-color-danger-5: #da3633;
-color-danger-6: #b62324;
-color-danger-7: #8e1519;
-color-danger-8: #67060c;
-color-danger-9: #490202;
-color-fg-default: #c9d1d9;
-color-fg-muted: #8b949e;
-color-fg-subtle: #6e7681;
-color-fg-emphasis: #ffffff;
-color-bg-default: #0d1117;
-color-bg-overlay: #0d1117;
-color-bg-subtle: #161b22;
-color-bg-inset: #010409;
-color-border-default: #30363d;
-color-border-muted: #21262d;
-color-border-subtle: rgba(240, 246, 252, 0.1);
-color-shadow-default: #010409;
-color-neutral-emphasis-plus: #6e7681;
-color-neutral-emphasis: #6e7681;
-color-neutral-muted: rgba(110, 118, 129, 0.4);
-color-neutral-subtle: rgba(110, 118, 129, 0.1);
-color-accent-fg: #58a6ff;
-color-accent-emphasis: #1f6feb;
-color-accent-muted: rgba(56, 139, 253, 0.4);
-color-accent-subtle: rgba(56, 139, 253, 0.15);
-color-warning-fg: #d29922;
-color-warning-emphasis: #9e6a03;
-color-warning-muted: rgba(187, 128, 9, 0.4);
-color-warning-subtle: rgba(187, 128, 9, 0.15);
-color-success-fg: #3fb950;
-color-success-emphasis: #238636;
-color-success-muted: rgba(46, 160, 67, 0.4);
-color-success-subtle: rgba(46, 160, 67, 0.15);
-color-danger-fg: #f85149;
-color-danger-emphasis: #da3633;
-color-danger-muted: rgba(248, 81, 73, 0.4);
-color-danger-subtle: rgba(248, 81, 73, 0.15);
-color-chart-1: #f3622d;
-color-chart-2: #fba71b;
-color-chart-3: #57b757;
-color-chart-4: #41a9c9;
-color-chart-5: #4258c9;
-color-chart-6: #9a42c8;
-color-chart-7: #c84164;
-color-chart-8: #888888;
-color-chart-1-alpha70: rgba(243, 98, 45, 0.7);
-color-chart-2-alpha70: rgba(251, 167, 27, 0.7);
-color-chart-3-alpha70: rgba(87, 183, 87, 0.7);
-color-chart-4-alpha70: rgba(65, 169, 201, 0.7);
-color-chart-5-alpha70: rgba(66, 88, 201, 0.7);
-color-chart-6-alpha70: rgba(154, 66, 200, 0.7);
-color-chart-7-alpha70: rgba(200, 65, 100, 0.7);
-color-chart-8-alpha70: rgba(136, 136, 136, 0.7);
-color-chart-1-alpha20: rgba(243, 98, 45, 0.2);
-color-chart-2-alpha20: rgba(251, 167, 27, 0.2);
-color-chart-3-alpha20: rgba(87, 183, 87, 0.2);
-color-chart-4-alpha20: rgba(65, 169, 201, 0.2);
-color-chart-5-alpha20: rgba(66, 88, 201, 0.2);
-color-chart-6-alpha20: rgba(154, 66, 200, 0.2);
-color-chart-7-alpha20: rgba(200, 65, 100, 0.2);
-color-chart-8-alpha20: rgba(136, 136, 136, 0.2);
-fx-pambackground: rgba(238,238,238);
-fx-darkbackground: -color-bg-default;
-fx-darkbackground-trans: rgba(13, 17, 23,0.90);
-fx-highlight: -color-base-6;
-fx-highlight_border: -color-button-fg;
-fx-text: -color-fg-default;
-fx-border_col: -color-border-default;
-fx-icon_col: -color-fg-default;
}
.root {
-fx-background-color:-fx-darkbackground;
-fx-font-size: 12px;
-fx-background-radius: inherit;
-fx-background-insets: inherit;
-fx-padding: 5px 5px 5px 5px;
}
/*******************************************************************************
* *
* Panes *
* *
******************************************************************************/
.pane {
-fx-background-color: -fx-darkbackground;
}
.pane-trans{
-fx-background-color: -fx-darkbackground-trans;
}
.pane-opaque {
-fx-background-color: -fx-pambackground;
}
/*for plot panes*/
.pane-plot {
-fx-background-color: -fx-plotbackground;
}
.button {
-color-button-bg: -color-bg-subtle;
-color-button-fg: -color-fg-default;
-color-button-border: -color-border-default;
-color-button-bg-hover: -color-base-6;
-color-button-fg-hover: -color-button-fg;
-color-button-border-hover: -color-button-border;
-color-button-bg-focused: -color-button-bg;
-color-button-fg-focused: -color-button-fg;
-color-button-border-focused: -color-accent-emphasis;
-color-button-bg-pressed: -color-bg-subtle;
-color-button-fg-pressed: -color-button-fg;
-color-button-border-pressed: transparent;
-fx-background-color: -color-button-border, -color-button-bg;
-fx-background-insets: 0, 1px;
-fx-background-radius: 4px;
-fx-graphic-text-gap: 6px;
-fx-text-fill: -color-button-fg;
-fx-alignment: CENTER;
-fx-padding: 8px 12px 8px 12px;
}
.menu-button,
.split-menu-button {
-color-button-bg: -color-bg-subtle;
-color-button-fg: -color-fg-default;
-color-button-border: -color-border-default;
-color-button-bg-hover: -color-base-6;
-color-button-fg-hover: -color-button-fg;
-color-button-border-hover: -color-button-border;
-color-button-bg-focused: -color-button-bg;
-color-button-fg-focused: -color-button-fg;
-color-button-border-focused: -color-accent-emphasis;
-color-button-bg-pressed: -color-bg-subtle;
-color-button-fg-pressed: -color-button-fg;
-color-button-border-pressed: transparent;
-fx-background-color: -color-button-border, -color-button-bg;
-fx-background-insets: 0, 1px;
-fx-background-radius: 4px;
-fx-graphic-text-gap: 6px;
-fx-text-fill: -color-button-fg;
-fx-alignment: CENTER;
-fx-padding: 0;
-fx-alignment: CENTER_LEFT;
}
.menu-button.accent,
.split-menu-button.accent {
-color-button-bg: -color-accent-emphasis;
-color-button-fg: -color-fg-emphasis;
-color-button-border: -color-accent-emphasis;
-color-button-bg-hover: -color-accent-emphasis;
-color-button-fg-hover: -color-fg-emphasis;
-color-button-border-hover: -color-accent-emphasis;
-color-button-bg-focused: -color-accent-6;
-color-button-fg-focused: -color-fg-emphasis;
-color-button-border-focused: -color-accent-emphasis;
-color-button-bg-pressed: -color-accent-emphasis;
-color-button-fg-pressed: -color-fg-emphasis;
-color-button-border-pressed: transparent;
}
.menu-button.accent.button-outlined,
.split-menu-button.accent.button-outlined {
-color-button-bg: -color-bg-default;
-color-button-fg: -color-accent-fg;
-color-button-bg-hover: -color-accent-emphasis;
-color-button-fg-hover: -color-fg-emphasis;
}
.menu-button.accent.flat,
.split-menu-button.accent.flat {
-color-button-fg: -color-accent-fg;
-color-button-bg-hover: -color-accent-subtle;
}
.menu-button.success,
.split-menu-button.success {
-color-button-bg: -color-success-emphasis;
-color-button-fg: -color-fg-emphasis;
-color-button-border: -color-success-emphasis;
-color-button-bg-hover: -color-success-emphasis;
-color-button-fg-hover: -color-fg-emphasis;
-color-button-border-hover: -color-success-emphasis;
-color-button-bg-focused: -color-success-6;
-color-button-fg-focused: -color-fg-emphasis;
-color-button-border-focused: -color-success-emphasis;
-color-button-bg-pressed: -color-success-emphasis;
-color-button-fg-pressed: -color-fg-emphasis;
-color-button-border-pressed: transparent;
}
.menu-button.success.button-outlined,
.split-menu-button.success.button-outlined {
-color-button-bg: -color-bg-default;
-color-button-fg: -color-success-fg;
-color-button-bg-hover: -color-success-emphasis;
-color-button-fg-hover: -color-fg-emphasis;
}
.menu-button.success.flat,
.split-menu-button.success.flat {
-color-button-fg: -color-success-fg;
-color-button-bg-hover: -color-success-subtle;
}
.menu-button.danger,
.split-menu-button.danger {
-color-button-bg: -color-danger-emphasis;
-color-button-fg: -color-fg-emphasis;
-color-button-border: -color-danger-emphasis;
-color-button-bg-hover: -color-danger-emphasis;
-color-button-fg-hover: -color-fg-emphasis;
-color-button-border-hover: -color-danger-emphasis;
-color-button-bg-focused: -color-danger-6;
-color-button-fg-focused: -color-fg-emphasis;
-color-button-border-focused: -color-danger-emphasis;
-color-button-bg-pressed: -color-danger-emphasis;
-color-button-fg-pressed: -color-fg-emphasis;
-color-button-border-pressed: transparent;
}
.menu-button.danger.button-outlined,
.split-menu-button.danger.button-outlined {
-color-button-bg: -color-bg-default;
-color-button-fg: -color-danger-fg;
-color-button-bg-hover: -color-danger-emphasis;
-color-button-fg-hover: -color-fg-emphasis;
}
.menu-button.danger.flat,
.split-menu-button.danger.flat {
-color-button-fg: -color-danger-fg;
-color-button-bg-hover: -color-danger-subtle;
}
.menu-button.flat,
.split-menu-button.flat {
-color-button-bg: transparent;
-color-button-fg: -color-fg-default;
-color-button-border: transparent;
-color-button-bg-hover: -color-bg-subtle;
-color-button-fg-hover: -color-button-fg;
-color-button-border-hover: -color-bg-subtle;
-color-button-bg-focused: -color-button-bg;
-color-button-fg-focused: -color-button-fg;
-color-button-border-focused: -color-button-bg;
-color-button-bg-pressed: -color-button-bg;
-color-button-fg-pressed: -color-button-fg;
-color-button-border-pressed: transparent;
}
.toggle-button {
-color-button-bg: -color-bg-subtle;
-color-button-fg: -color-fg-default;
-color-button-border: -color-border-default;
-color-button-bg-hover: -color-base-6;
-color-button-fg-hover: -color-button-fg;
-color-button-border-hover: -color-button-border;
-color-button-bg-focused: -color-button-bg;
-color-button-fg-focused: -color-button-fg;
-color-button-border-focused: -color-accent-emphasis;
-color-button-bg-pressed: -color-bg-subtle;
-color-button-fg-pressed: -color-button-fg;
-color-button-border-pressed: transparent;
-fx-background-color: -color-button-border, -color-button-bg;
-fx-background-insets: 0, 1px;
-fx-background-radius: 4px;
-fx-graphic-text-gap: 6px;
-fx-text-fill: -color-button-fg;
-fx-alignment: CENTER;
-color-button-bg-selected: -color-accent-emphasis;
-color-button-fg-selected: -color-fg-emphasis;
-fx-padding: 8px 12px 8px 12px;
}
.list-view {
-color-cell-bg: -color-bg-default;
-color-cell-fg: -color-fg-default;
-color-cell-bg-selected: -color-base-6;
-color-cell-fg-selected: -color-fg-default;
-color-cell-bg-odd: -color-bg-subtle;
-color-cell-border: -color-border-default;
-fx-border-color: -color-cell-border;
-fx-border-width: 1px;
-fx-border-radius: 0;
}
.table-view {
-color-cell-bg: -color-bg-default;
-color-cell-fg: -color-fg-default;
-color-cell-bg-selected: -color-base-6;
-color-cell-fg-selected: -color-fg-default;
-color-cell-bg-odd: -color-bg-subtle;
-color-cell-border: -color-border-default;
-fx-border-color: -color-cell-border;
-fx-border-width: 1px;
-fx-border-radius: 0;
-color-header-bg: -color-bg-subtle;
-color-header-fg: -color-fg-default;
}
.titled-pane > .title > .text {
-fx-font-size: 1em;
}
.tree-view {
-color-cell-bg: -color-bg-default;
-color-cell-fg: -color-fg-default;
-color-cell-bg-selected: -color-base-6;
-color-cell-fg-selected: -color-fg-default;
-color-cell-bg-odd: -color-bg-subtle;
-color-cell-border: -color-border-default;
-fx-border-color: -color-cell-border;
-fx-border-width: 1px;
-fx-border-radius: 0;
}
.tree-table-view {
-color-cell-bg: -color-bg-default;
-color-cell-fg: -color-fg-default;
-color-cell-bg-selected: -color-base-6;
-color-cell-fg-selected: -color-fg-default;
-color-cell-bg-odd: -color-bg-subtle;
-color-cell-border: -color-border-default;
-fx-border-color: -color-cell-border;
-fx-border-width: 1px;
-fx-border-radius: 0;
-color-header-bg: -color-bg-subtle;
-color-header-fg: -color-fg-default;
}
.list-view:focused > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected,
.tree-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-cell:filled:selected,
.table-view:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled:selected,
.tree-table-view:focused > .virtual-flow > .clipped-container > .sheet > .tree-table-row-cell:filled:selected {
-color-cell-fg: -color-cell-fg-selected;
-fx-background-color: -color-cell-border, -color-cell-bg-selected;
}
/*******************************************************************************
* *
* ikonli icons *
* *
******************************************************************************/
#module-pane .ikonli-font-icon {
-fx-icon-color: black;
}
.titled-pane {
-fx-background-color: -color-bg-default;
-fx-text-fill: -color-fg-default;
-fx-effect: none;
}
/****************************************************************
ScrollPane
****************************************************************/
.scroll-pane {
-fx-background: #0d1117;
-fx-background-color: transparent;
}
.scroll-pane > .viewport {
-fx-background-color: transparent;
}
.scroll-pane-dark {
-fx-background: -fx-darkbackground;
-fx-background-color: -fx-darkbackground;
}
/*******************************************************************************
* *
* Hiding Tab *
* *
******************************************************************************/
#hide-tab {
-fx-background-color: transparent;
-fx-border-radius: 5 5 0 0;
-fx-background-radius: 5 5 0 0;
-fx-border-color: -fx-border_col;
}
#show-tab {
-fx-background-color: transparent;
-fx-border-radius: 5 5 0 0;
-fx-background-radius: 5 5 0 0;
-fx-border-color: -fx-border_col;
}
#hide-tab-highlight {
-fx-background-color: -fx-highlight;
-fx-border-radius: 5 5 0 0;
-fx-background-radius: 5 5 0 0;
-fx-border-color: -fx-highlight_border;
}
/*******************************************************************************
* *
* Button *
* *
******************************************************************************/
/*.button{
-fx-text-fill: white;
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
-fx-border-radius: 5;
-fx-background-radius:6;
-fx-padding: 3 6 6 6;
}*/
/*.button:hover{
-fx-background-color: -fx-highlight;
-fx-border-color: -fx-highlight_border;
}
.button:selected{
-fx-border-color: -fx-highlight;
}
*/
/**
* Button for closing a hiding panel. Right indicates bottoms points towards the right, closing a hiding panel
* on the right hand side of the screen. These buttons have a transparent background and rounded corners.
*/
/** top-left, top-right, bottom-right, and bottom-left corners, in that order. */
.close-button-right{
-fx-background-color: transparent;
-fx-background-radius: 0 10 10 0;
-fx-border-color: transparent;
-fx-border-radius: 0 10 10 0;
}
.close-button-left{
-fx-background-color: transparent;
-fx-background-radius: 10 0 0 10;
-fx-border-color: transparent;
-fx-border-radius: 10 0 0 10;
}
.close-button-top{
-fx-background-color: transparent;
-fx-background-radius: 10 10 0 0;
-fx-border-color: transparent;
-fx-border-radius: 10 10 0 0;
}
.close-button-bottom{
-fx-background-color: transparent;
-fx-background-radius: 0 0 10 10;
-fx-border-color: transparent;
-fx-border-radius: 0 0 10 10;
}
.close-button-bottom-trans{
-fx-border-color: transparent;
-fx-background-color: transparent;
-fx-background-radius: 0 0 10 10;
-fx-border-radius: 0 0 10 10;
}
.close-button-left-trans{
-fx-border-color: transparent;
-fx-background-color: transparent;
-fx-background-radius: 10 0 0 10;
-fx-border-radius: 10 0 0 10;
}
.close-button-right-trans{
-fx-border-color: transparent;
-fx-background-color: transparent;
-fx-background-radius: 0 10 10 0;
-fx-border-radius: 0 10 10 0;
}
.square-button{
-fx-background-radius: 0 0 0 0;
-fx-border-radius: 0 0 0 0;
}
.square-button-trans{
-fx-background-color: transparent;
-fx-border-color: transparent;
-fx-background-radius: 0 0 0 0;
-fx-border-radius: 0 0 0 0;
}
.module-hide-top{
-fx-border-color: transparent;
-fx-background-radius: 5 5 0 0;
-fx-border-radius: 5 5 0 0;
}
.module-hide-bottom{
-fx-border-color: transparent;
-fx-background-radius: 0 0 5 5;
-fx-border-radius: 0 0 5 5;
}
.delete-button:hover{
-fx-background-color: rgba(1,0,0,0.7);
}
/*******************************************************************************
* *
* Pop over *
* *
******************************************************************************/
.popover {
-fx-background-color: -fx-darkbackground;
-fx-background-radius: 5;
-fx-border-radius: 5;
}
.popover > .content {
-fx-background-color: -fx-darkbackground;
-fx-background-radius: 5;
-fx-border-radius: 5;
}
.popover > .arrow {
-fx-background-color: -fx-darkbackground;
-fx-background-radius: 5;
-fx-border-radius: 5;
}
/*weird way to do it but need this to colour the arrow*/
.popover > .border {
/*-fx-stroke: linear-gradient(to bottom, rgba(0,0,0, .3), rgba(0, 0, 0, .7)) ;*/
-fx-stroke-width: 0.5;
-fx-fill: -fx-darkbackground; /* instead -fx-background-color */
}
/*******************************************************************************
* *
* SplitMenuButton *
* *
******************************************************************************/
.split-menu-button{
-fx-text-fill: -fx-text;
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
-fx-border-radius: 5;
}
.split-menu-button:hover{
/*-fx-border-color: -fx-highlight_border;*/
}
.split-menu-button .label {
-fx-text-fill: white;
-fx-background-color: -fx-darkbackground;
-fx-border-radius: 5;
}
.split-menu-button .label:hover {
-fx-background-color: -fx-highlight;
}
.split-menu-button .arrow-button {
-fx-text-fill: -fx-text;
-fx-background-color: -fx-darkbackground;
-fx-border-radius: 5;
}
.split-menu-button .arrow-button:hover {
-fx-background-color: -fx-highlight;
}
/**********/
.menu-item {
-fx-background-color: -color-bg-default;
-fx-padding: 8px 12px 8px 12px;
}
.menu-item > .graphic-container {
-fx-padding: 0 6px 0 0;
}
.menu-item > .label {
-fx-padding: 0 1em 0 0;
-fx-text-fill: -color-fg-default;
}
.menu-item > .left-container {
-fx-padding: 0 1em 0 0;
}
.menu-item > .right-container {
-fx-padding: 0 0 0 0.5em;
}
.menu-item:focused {
-fx-background-color: -color-base-7, -color-base-7;
}
.menu-item:disabled {
-fx-opacity: 0.4;
-fx-background-color: -color-bg-default;
}
/********************************************
* *
* Spinner *
* *
*********************************************/
.spinner {
-fx-pref-width: 120px;
}
.dialog-pane > .content {
-fx-padding: 1em 1em 1em 1em;
}
/*******************************************************************************
* *
* Hiding Pane *
* *
******************************************************************************/
/**
* Button for closing a hiding panel. Right indicates bottoms points towards the right, closing a hiding panel
* on the right hand side of the screen. These buttons have a transparent background and rounded corners.
*/
/** top-left, top-right, bottom-right, and bottom-left corners, in that order. */
.close-button-right{
-fx-background-color: transparent;
-fx-background-radius: 0 10 10 0;
-fx-border-radius: 0 10 10 0;
}
.close-button-right:hover {
-fx-background-color: -fx-highlight;
}
.close-button-left{
-fx-background-color: transparent;
-fx-background-radius: 10 0 0 10;
-fx-border-radius: 10 0 0 10;
}
.close-button-left:hover {
-fx-background-color: -fx-highlight;
}
.close-button-top{
-fx-background-color: transparent;
-fx-background-radius: 10 10 0 0;
-fx-border-radius: 10 10 0 0;
}
.close-button-bottom {
-fx-background-color: transparent;
-fx-background-radius: 0 0 10 10;
-fx-border-radius: 0 0 10 10;
}
.close-button-bottom:hover {
-fx-background-color: -fx-highlight;
}
.close-button-bottom-grey{
-fx-border-color: transparent;
-fx-background-radius: 0 0 10 10;
-fx-border-radius: 0 0 10 10;
}
.close-button-left-trans{
-fx-border-color: transparent;
-fx-background-color: transparent;
-fx-background-radius: 10 0 0 10;
-fx-border-radius: 10 0 0 10;
}
.close-button-left-trans:focused {
-fx-border-color: transparent;
-fx-background-color: transparent;
-fx-background-radius: 10 0 0 10;
-fx-border-radius: 10 0 0 10;
}
.close-button-right-trans{
-fx-border-color: transparent;
-fx-background-color: transparent;
-fx-background-radius: 0 10 10 0;
-fx-border-radius: 0 10 10 0;
}
.close-button-right-trans:focused {
-fx-border-color: transparent;
-fx-background-color: transparent;
-fx-background-radius: 0 10 10 0;
-fx-border-radius: 0 10 10 0;
}
.menu-square-button {
-fx-border-color: -fx_border_col;
-fx-background-color: transparent;
-fx-background-radius: 0 0 0 0;
-fx-border-radius: 0 0 0 0;
}

View File

@ -0,0 +1,12 @@
package audioMoth;
import PamController.PamControlledUnit;
public class AudioMothControl extends PamControlledUnit {
public AudioMothControl(String unitType, String unitName) {
super(unitType, unitName);
// TODO Auto-generated constructor stub
}
}

View File

@ -6,7 +6,7 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.attribute.BasicFileAttributes;
import PamUtils.PamAudioFileFilter;
import Acquisition.pamAudio.PamAudioFileFilter;
import PamUtils.PamCalendar;
public class TestFileDates {

View File

@ -28,11 +28,11 @@ public class BTDisplayParameters implements Serializable, Cloneable, ManagedPara
public static final String[] angleTypeNames = {"Relative to array", "Relative to vessel", "Relative to north"};
/**
* Rotation options for angles.
* Rotation options for angles. These should match the above angleTypeNames.
*/
static public final int ROTATE_TOARRAY = 0; // no rotation, raw angles relative to the array
static public final int ROTATE_PITCHROLL = 1; // fix pitch and roll, but leave the heading relative to the array
static public final int ROTATE_HEADPITCHROLL = 2; // rotate by heading pitch and roll.
static public final int ROTATE_TOVESSEL = 1; // fix pitch and roll, but leave the heading relative to the array
static public final int ROTATE_TONORTH = 2; // rotate by heading pitch and roll.
// main BT display

View File

@ -1642,16 +1642,26 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
double[] rotAngles = new double[3];
rotAngles[1] = Math.toRadians(oll.getPitch());
rotAngles[2] = Math.toRadians(oll.getRoll());
if (rType == BTDisplayParameters.ROTATE_HEADPITCHROLL) {
if (rType == BTDisplayParameters.ROTATE_TOVESSEL) {
// use head as well as pitch and roll.
rotAngles[0] = Math.toRadians(oll.getHeading());
PamVector[] vr = loc.getWorldVectors();
if (vr != null && vr.length > 0) {
return vr[0];
}
// rotAngles[0] = Math.toRadians(oll.getHeading());
}
if (rotAngles[0] == 0 && rotAngles[1] == 0 && rotAngles[2] == 0) {
return v;
else if (rType == BTDisplayParameters.ROTATE_TONORTH) {
PamVector[] vr = loc.getRealWorldVectors();
if (vr != null && vr.length > 0) {
return vr[0];
}
}
PamQuaternion pq = new PamQuaternion(rotAngles[0], rotAngles[1], rotAngles[2]);
PamVector v2 = PamVector.rotateVector(v, pq);
return v2;
// if (rotAngles[0] == 0 && rotAngles[1] == 0 && rotAngles[2] == 0) {
// return v;
// }
// PamQuaternion pq = new PamQuaternion(rotAngles[0], rotAngles[1], rotAngles[2]);
// PamVector v2 = PamVector.rotateVector(v, pq);
return v;
}
private double angleFromYPos(int yPos) {

View File

@ -226,7 +226,7 @@ public class SweepClassifier implements ClickIdentifier , PamSettings {
return clickDetector;
}
protected int getNextFreeCode(int currCode) {
public int getNextFreeCode(int currCode) {
int newCode = currCode;
while (codeTaken(++newCode));
return newCode;
@ -277,7 +277,7 @@ public class SweepClassifier implements ClickIdentifier , PamSettings {
* Set the params for the sweep classifier.
* @params the sweep classifier params to set.
*/
public void setSeepClassifierParams(SweepClassifierParameters sweepClassifierParameters) {
public void setSweepClassifierParams(SweepClassifierParameters sweepClassifierParameters) {
this.sweepClassifierParameters=sweepClassifierParameters;
}

View File

@ -106,7 +106,10 @@ public class ClickParameters implements Serializable, Cloneable, ManagedParamete
*/
public int backgroundIntervalMillis = 5000;
public int clickClassifierType = ClickClassifierManager.CLASSIFY_BASIC;
/**
* The type of classifier to use - CLASSIFY_SWEEP is the default.
*/
public int clickClassifierType = ClickClassifierManager.CLASSIFY_BETTER;
public boolean runEchoOnline = false;

View File

@ -6,6 +6,7 @@ import java.text.ParseException;
import clickDetector.ClickControl;
import clickDetector.ClickParameters;
import clickDetector.layoutFX.clickClassifiers.ClickClassifyPaneFX;
import javafx.geometry.HPos;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Node;
@ -14,12 +15,14 @@ import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.util.StringConverter;
import net.synedra.validatorfx.Validator;
import PamController.PamController;
import PamController.SettingsPane;
import PamDetection.RawDataUnit;
@ -43,8 +46,8 @@ import pamViewFX.fxNodes.utilityPanes.GroupedSourcePaneFX;
* @author Jamie Macaulay
*/
public class ClickSettingsPane extends SettingsPane<ClickParameters>{
public static double PREF_SPINNER_WIDTH = 100;
public static double PREF_SPINNER_WIDTH = 140;
/**
* Group source pane for the click settings pane.
@ -160,25 +163,35 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
private Tab tdoaTab;
/**
* The default pane width
* The main holder pane.
*/
public static double paneWidth=500;
private PamBorderPane mainPane;
/**
* The default pane height.
*/
public static double paneHeigt=800;
public static double PREF_PANE_HEIGHT=850;
/**
* The main holder pane.
* The default pane width
*/
private PamBorderPane mainPane;
public static double PREF_PANE_WIDTH=550;
/**
* Validator which checks for errors
*/
private Validator clickValidator;
public ClickSettingsPane(ClickControl clickControl){
super(null);
this.clickControl=clickControl;
mainPane= new PamBorderPane();
clickValidator = new Validator();
pamTabbedPane=new PamTabPane();
pamTabbedPane.setAddTabButton(false);
pamTabbedPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
@ -187,49 +200,49 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
PamVBox detectionPane=new PamVBox();
detectionPane.setSpacing(20);
detectionPane.getChildren().add(createClickDetectionPane());
PamHBox holder=new PamHBox();
holder.setSpacing(20);
holder.getChildren().addAll(createClickLengthPane(), createClickTriggerPane());
detectionPane.getChildren().add(holder);
detectionPane.getChildren().add(createTriggerGraph());
//add everything to tabs.
pamTabbedPane.getTabs().add(new Tab("Click Detection", detectionPane));
clickDelayPane=createDelayPane();
pamTabbedPane.getTabs().add(tdoaTab=new Tab("Click TDOA", clickDelayPane.getContentNode()));
pamTabbedPane.getTabs().add(tdoaTab=new Tab("TDOA and Echoes", clickDelayPane.getContentNode()));
tdoaTab.setOnSelectionChanged((event)->{
if (pamTabbedPane.getSelectionModel().getSelectedItem()==tdoaTab){
System.out.println("clickDelayPane: "+clickDelayPane);
//System.out.println("clickDelayPane: "+clickDelayPane);
//need to update the tab with a copy of the current click params.
clickDelayPane.setParams(clickClassificationPane.getParams(clickParameters.clone()));
}
});
//pre filter pane.
preFilter=new FilterPaneFX(Orientation.VERTICAL);
pamTabbedPane.getTabs().add(new Tab("Pre Filter", preFilter.getContentNode()));
//trigger pane
triggerFilter=new FilterPaneFX(Orientation.VERTICAL);
pamTabbedPane.getTabs().add(new Tab("Trigger Filter", triggerFilter.getContentNode()));
//echo detection pane.
echoDetection= new ClickEchoPane(clickControl);
pamTabbedPane.getTabs().add(new Tab("Echo Detection", echoDetection.getContentNode()));
// //echo detection pane.
// echoDetection= new ClickEchoPane(clickControl);
// pamTabbedPane.getTabs().add(new Tab("Echo Detection", echoDetection.getContentNode()));
/***Note: FX does not implment click train detection in click detector****/
//classifiaction pane.
pamTabbedPane.getTabs().add(new Tab("Click Classification", clickClassificationPane=new ClickClassifyPaneFX(clickControl)));
pamTabbedPane.getTabs().add(new Tab("Classification", clickClassificationPane=new ClickClassifyPaneFX(clickControl)));
//want a slightly bigger pane as a lot going on in this dialog.
//Note JavaFX 8u61 + has auto DPI scaling so this is really the size of a dialog on a standard HD monitor of
//reasonable size, rather than actual pixels
mainPane.setPrefSize(paneWidth, paneHeigt);
mainPane.setPrefSize(PREF_PANE_WIDTH, PREF_PANE_HEIGHT);
//addTabListeners();
mainPane.setCenter(new PamBorderPane(pamTabbedPane));
@ -267,16 +280,17 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
//channels, groups and trigger are all in one pane to make it easy not to make mistakes
sourcePane=createClickSourcePane(); //create the source pane.
GridPane.setColumnSpan(sourcePane.getDataBlockBox(), 4);
GridPane.setColumnSpan(sourcePane.getDataBlockBox(), 2);
//now create trigger pane. The trigger pane is added to the source pane.
Label triggerLabel = new Label("Trigger Channels");
PamGuiManagerFX.titleFont2style(triggerLabel);
sourcePane.getSourcePane().add(triggerLabel,1,2);
triggerChannels=new Pane();
sourcePane.getSourcePane().add(triggerChannels,1,3);
GridPane.setHalignment(triggerChannels, HPos.RIGHT);
createTriggerChannels();
//sourcePane.getSourcePane().add(createClickTriggerPane(), 2, 3);
@ -285,7 +299,18 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
// pamTabbedPane.getTabs().add(new Tab("Click Echoes", createEchoPane()));
// pamTabbedPane.getTabs().add(new Tab("Click Delays", createDelayPane()));
sourcePane.setPrefWidth(paneWidth);
ColumnConstraints col1 = new ColumnConstraints();
col1.setHgrow(Priority.ALWAYS);
ColumnConstraints col2 = new ColumnConstraints();
col2.setHgrow(Priority.SOMETIMES);
col2.setHalignment(HPos.RIGHT);
sourcePane.getSourcePane().getColumnConstraints().addAll(col1, col2);
PamHBox.setHgrow(sourcePane.getChannelPane(), Priority.NEVER);
//sourcePane.setMinWidth(PREF_PANE_WIDTH);
sourcePane.getSourcePane().setPrefWidth(PREF_PANE_WIDTH);
return sourcePane;
}
@ -317,7 +342,7 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
maxClickLength.setEditable(true);
maxClickLength.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
maxClickLength.setPrefWidth(PREF_SPINNER_WIDTH);
lengthPane.add(maxClickLength,1,1);
lengthPane.add(new Label("samples"),2,1);
@ -326,7 +351,7 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
preSampleSpinner=new PamSpinner<Integer>(0, 10000000, 100, 20);
preSampleSpinner.setEditable(true);
preSampleSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
preSampleSpinner.setPrefWidth(PREF_SPINNER_WIDTH);
//preSampleSpinner.setPrefWidth(PREF_SPINNER_WIDTH);
lengthPane.add(preSampleSpinner,1,2);
lengthPane.add(new Label("samples"),2,2);
@ -336,7 +361,8 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
postSampleSpinner=new PamSpinner<Integer>(0, 10000000, 100, 20);
postSampleSpinner.setEditable(true);
postSampleSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
postSampleSpinner.setPrefWidth(PREF_SPINNER_WIDTH);
//postSampleSpinner.setPrefWidth(PREF_SPINNER_WIDTH);
lengthPane.add(postSampleSpinner,1,3);
lengthPane.add(new Label("samples"),2,3);
@ -360,13 +386,24 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
else selectNoChannels();
});
//create a list of trigger boxes
//create a list of trigger boxesc
for (int i=0; i<triggerBoxes.length; i++){
triggerBoxes[i]=new CheckBox(("Channel "+i));
final int n=i;
triggerBoxes[i].setOnAction((action)->{
selectionChanged(n);
clickValidator.validate(); //make sure all nodes are resrt when one channel is ticked.
});
clickValidator.createCheck()
.dependsOn(("trigger " + n), triggerBoxes[i].selectedProperty())
.withMethod(c -> {
if (!isATriggerSelected() ) {
c.error("At least one trigger channel needs to be selected for the module to work");
}
})
.decorates(triggerBoxes[n])
.immediate();
}
populateTriggerPane();
@ -406,7 +443,7 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
threshold.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
threshold.getValueFactory().valueProperty().addListener((obs, before, after)->{
clickParameters.dbThreshold=after;
clickTriggerGraph.updateWaveformGraph(this.clickParameters);
clickTriggerGraph.updateGraphFilter();
});
triggerBox.add(threshold,1,0);
triggerBox.add(new Label("dB"),2,0);
@ -420,7 +457,7 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
longFilter.getValueFactory().valueProperty().addListener((obs, before, after)->{
clickParameters.longFilter=after;
clickTriggerGraph.setLongFilter(clickParameters.longFilter);
clickTriggerGraph.updateWaveformGraph(this.clickParameters);
clickTriggerGraph.updateGraphFilter();
});
triggerBox.add(longFilter,1,1);
longFilter.setPrefWidth(PREF_SPINNER_WIDTH);
@ -444,11 +481,14 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
shortFilter.getValueFactory().valueProperty().addListener((obs, before, after)->{
clickParameters.shortFilter=after;
clickTriggerGraph.setShortFilter(clickParameters.shortFilter);
clickTriggerGraph.updateWaveformGraph(this.clickParameters);
clickTriggerGraph.updateGraphFilter();
});
shortFilter.setPrefWidth(PREF_SPINNER_WIDTH);
triggerBox.add(shortFilter,1,3);
//forces the grid pane to be larger - grid panes can be a little funny.
shortFilter.setMinWidth(PREF_SPINNER_WIDTH);
triggerPane.add(triggerBox,0,1);
//triggerPane.setGridLinesVisible(true);
@ -456,7 +496,7 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
return triggerPane;
}
private Pane createTriggerGraph() {
//trigger graph
Label graphLabel = new Label("Filter Graph");
@ -469,9 +509,9 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
PamVBox triggerGraph = new PamVBox();
triggerGraph.setSpacing(5);
triggerGraph.getChildren().addAll(graphLabel, clickTriggerGraph);
return triggerGraph;
}
/**
@ -525,7 +565,7 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
}
/**
* Get the current channle bitmap.
* Get the current channels bitmap.
* @return integer channel bitmap
*/
private int getChannels(){
@ -538,6 +578,32 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
}
return channels;
}
/**
* Get the number of selected trigger channels.
* @return the number of selected trigger channels.
*/
private int getNSelectedTrigger() {
int channels=getChannels();
int n=0;
//now add correct trigger children again
for (int i = 0; i < Math.min(PamConstants.MAX_CHANNELS, triggerBoxes.length); i++) {
if ((channels & 1<<i) != 0 && triggerBoxes[i].isSelected()){
n++;
};
}
return n;
}
/**
* Check whether at least one trigger channel is selected.
* @return true of a trigger channel is selected.
*/
private boolean isATriggerSelected() {
return getNSelectedTrigger()>0;
}
/**
* Create trigger channels
@ -555,6 +621,8 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
triggerChannels.getChildren().add(selectAll);
for (int i = 0; i < Math.min(PamConstants.MAX_CHANNELS, triggerBoxes.length); i++) {
if ((channels & 1<<i) != 0){
//triggerBoxes[i] = new CheckBox("Channel " + i);
triggerChannels.getChildren().add(triggerBoxes[i]);
triggerBoxes[i].layoutYProperty().unbind();
triggerBoxes[i].layoutYProperty().bind(sourcePane.getChannelBoxes()[i].layoutYProperty());
@ -603,14 +671,14 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
return null;
}
// clickParameters.rawDataSource = rawDataBlock.toString();
// clickParameters.channelBitmap = sourcePane.getChannelList();
// clickParameters.channelGroups = sourcePane.getChannelGroups();
// clickParameters.groupingType = sourcePane.getGrouping();
// clickParameters.rawDataSource = rawDataBlock.toString();
// clickParameters.channelBitmap = sourcePane.getChannelList();
// clickParameters.channelGroups = sourcePane.getChannelGroups();
// clickParameters.groupingType = sourcePane.getGrouping();
//sets the params for source pane.
sourcePane.getParams(clickParameters.getGroupedSourceParameters());
// if (sourcePanel.getParams() == false) return false;
try {
clickParameters.dbThreshold = Double.valueOf(threshold.getValue());
@ -669,6 +737,8 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
return null;
}
}
clickParameters = clickClassificationPane.getParams(clickParameters);
}
catch (Exception e){
@ -696,12 +766,12 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
else {
sourcePane.setSourceIndex(0);
}
sourcePane.setParams(clickParameters.getGroupedSourceParameters());
// sourcePane.setGrouping(clickParameters.groupingType);
// sourcePane.setChannelGroups(clickParameters.channelGroups);
// sourcePane.setChannelList(clickParameters.channelBitmap);
// sourcePane.setGrouping(clickParameters.groupingType);
// sourcePane.setChannelGroups(clickParameters.channelGroups);
// sourcePane.setChannelList(clickParameters.channelBitmap);
//click length pane
minClickSep.getValueFactory().setValue(clickParameters.minSep);

View File

@ -1,15 +1,25 @@
package clickDetector.layoutFX;
import clickDetector.ClickParameters;
import java.util.ArrayList;
import PamUtils.PamArrayUtils;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.ChoiceBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamStackPane;
import pamViewFX.fxNodes.pamChart.PamLineChart;
import simulatedAcquisition.sounds.ClickSound;
import simulatedAcquisition.sounds.ClickSound.WINDOWTYPE;
import simulatedAcquisition.sounds.SimSignal;
import rawDeepLearningClassifier.layoutFX.exampleSounds.ExampleSound;
import rawDeepLearningClassifier.layoutFX.exampleSounds.ExampleSoundFactory;
import rawDeepLearningClassifier.layoutFX.exampleSounds.ExampleSoundFactory.ExampleSoundCategory;
import rawDeepLearningClassifier.layoutFX.exampleSounds.ExampleSoundFactory.ExampleSoundType;
import javafx.application.Platform;
/**
* Graph which shows a click and associated trigger functions
@ -17,28 +27,22 @@ import simulatedAcquisition.sounds.SimSignal;
*
*/
public class ClickTriggerGraph extends PamBorderPane {
public final static int PORPOISE_CLICK=0;
public final static int SPERM_WHALE=1;
private int currentClick=PORPOISE_CLICK;
private NumberAxis xAxis;
private NumberAxis yAxis;
/**
* The long filter
*/
private double longFilter=0.00001;
/**
* The short filter
*/
private double shortFilter=0.01;
/*
* Random noise added to the click and surrounding snippet.
*/
@ -48,48 +52,33 @@ public class ClickTriggerGraph extends PamBorderPane {
private int freq2;
public static final int PREF_GRAPH_WIDTH = 400;
/**
* The example sound factory.
*/
private ExampleSoundFactory exampleSoundFactory;
private Series<Number, Number> signalLevelSeries;
private Series<Number, Number> noiseLevelSeries;
Task<Integer> task;
private double[] waveform;
public ClickTriggerGraph(){
this.exampleSoundFactory = new ExampleSoundFactory();
this.setCenter(createWaveformGraph());
this.setPrefWidth(400);
//FIXME - seems to a resize bug in high DPI displays. Seems fixed in 8u60.
this.waveform=generateClickWaveform(currentClick, noise);
generateClickWaveform(ExampleSoundType.PORPOISE_CLICK, noise);
}
/**
* Update graph. Delete current data series and create new one.
*/
public void updateWaveformGraph(ClickParameters clickParameters){
// System.out.println(" Graph width: xAxis: "+xAxis.widthProperty().get());
// System.out.println(" Graph width: this: "+this.widthProperty().get());
// System.out.println(" Graph width: plotChart: "+plotChart.widthProperty().get());
// System.out.println(" xAxisLayout:: "+xAxis.layoutXProperty().get());
// System.out.println(" plotLayout:: "+plotChart.layoutXProperty().get());
Series<Number, Number> waveformSeries = new Series<Number, Number>();
Series<Number, Number> signalLevelSeries = new Series<Number, Number>();
Series<Number, Number> noiseLevelSeries = new Series<Number, Number>();
double[] signalLevel=calcFilter(waveform, shortFilter);
double[] noiseLevel=calcFilter(waveform, longFilter);
for (int i=0; i<waveform.length; i++){
waveformSeries.getData().add(new Data<Number, Number>(i, waveform[i]));
signalLevelSeries.getData().add(new Data<Number, Number>(i, signalLevel[i]));
noiseLevelSeries.getData().add(new Data<Number, Number>(i, noiseLevel[i]));
}
plotChart.getData().removeAll(plotChart.getData());
plotChart.getData().addAll(waveformSeries,signalLevelSeries,noiseLevelSeries);
}
public double[] calcFilter(double[] waveform, double alpha){
double[] filterVals=new double[waveform.length];
for (int i=0; i<waveform.length; i++){
@ -97,55 +86,15 @@ public class ClickTriggerGraph extends PamBorderPane {
else filterVals[i]=alpha*Math.abs(waveform[i])+(1-alpha)*filterVals[i-1];
}
return filterVals;
}
/**
* Generate a click waveform with some added noise.
* @param type - the type of click e.g. ClickTriggerGraph.PORPOISE_CLICK.
* @param noise. 0 to 1. 1 means max noise amplitude will be same as maximum click amplitude.
* @return click and noise waveform.
*/
private double[] generateClickWaveform(int type, double noise){
SimSignal clickSound;
int sR;
double length;
double freq;
switch (type){
//TODO - add more types of clicks.
case PORPOISE_CLICK:
clickSound=new ClickSound("Porpoise", freq=140000, freq2=140000, length=0.00015, WINDOWTYPE.HANN);
sR=500000;
break;
case SPERM_WHALE:
clickSound=(new ClickSound("Beaked Whale", 30000, 60000, length = 0.3e-3, WINDOWTYPE.HANN));
sR=192000;
break;
default:
clickSound=new ClickSound("Porpoise", freq=140000, freq2=140000, length=0.00015, WINDOWTYPE.HANN);
sR=500000;
break;
}
//now need to work out how many noise samples to add. Use the length of the click
int nNoiseSamples=(int) (2*length*sR);
double[] waveform=new double[3*nNoiseSamples];
int n=0;
for (int i=0; i<3*nNoiseSamples; i++){
double noiseSample=noise*(Math.random()-0.5);
double[] signal=clickSound.getSignal(0,sR,0);
if (i>nNoiseSamples && n <signal.length){
waveform[i]=signal[n]+noiseSample;
n=n+1;
}
else waveform[i]=noiseSample;
}
return waveform;
}
public LineChart<Number, Number> createWaveformGraph(){
public Pane createWaveformGraph(){
StackPane stackPane = new PamStackPane();
xAxis=new NumberAxis();
xAxis.setMaxWidth(Double.MAX_VALUE);
xAxis.setLabel("Sample");
@ -154,20 +103,39 @@ public class ClickTriggerGraph extends PamBorderPane {
yAxis=new NumberAxis(-1,1,0.2);
yAxis.setLabel("Amplitude");
yAxis.setAutoRanging(false);
plotChart=new PamLineChart<Number, Number>(xAxis, yAxis);
plotChart.setMaxWidth(Double.MAX_VALUE);
plotChart.setAnimated(false);
plotChart.setLegendVisible(false);
plotChart.setCreateSymbols(false);
plotChart.getStyleClass().add("thin-chart");
//plotChart.getXAxis().setSide(Side.BOTTOM);
return plotChart;
ChoiceBox<ExampleSoundType> waveformChoice = new ChoiceBox<ExampleSoundType>();
ArrayList<ExampleSoundType> exampleSounds = exampleSoundFactory.getExampleSoundTypes(ExampleSoundCategory.ODONTOCETES_CLICKS, ExampleSoundCategory.BAT);
for (int i=0; i<exampleSounds.size(); i++) {
waveformChoice.getItems().add(exampleSounds.get(i));
}
waveformChoice.setOnAction((action)->{
generateClickWaveform(waveformChoice.getSelectionModel().getSelectedItem(), noise);
updateGraphWaveform() ;
updateGraphFilter();
});
waveformChoice.getSelectionModel().select(ExampleSoundType.PORPOISE_CLICK);
waveformChoice.setPrefWidth(180);
StackPane.setAlignment(waveformChoice, Pos.TOP_RIGHT);
stackPane.getChildren().addAll(plotChart, waveformChoice);
return stackPane;
}
public double getLongFilter() {
return longFilter;
}
@ -176,6 +144,131 @@ public class ClickTriggerGraph extends PamBorderPane {
this.longFilter = longFilter;
}
/**
* Update the waveform of the species.
*/
public synchronized void updateGraphWaveform() {
plotChart.getData().clear();
Series<Number, Number> waveformSeries = new Series<Number, Number>();
for (int i=0; i<waveform.length; i++){
waveformSeries.getData().add(new Data<Number, Number>(i, waveform[i]));
}
plotChart.getData().add(waveformSeries);
}
/**
* Update graph. Delete current data series and create new one.
*/
public synchronized void updateGraphFilter(){
if (waveform.length<500) {
if (task!=null) {
task.cancel(true);
}
//no need to do on separate thread.
plotChart.getData().remove(signalLevelSeries);
plotChart.getData().remove(noiseLevelSeries);
plotChart.getData().add(signalLevelSeries = calcSeries(waveform, shortFilter));
plotChart.getData().add(noiseLevelSeries = calcSeries(waveform, longFilter));
}
else {
if (task!=null) {
if (task.isRunning()) {
return;
}
}
/***
* FIXME
* This is a little ridiculous but there are two bugs in JavaFX
* 1) The line chart is super slow
* 2) If you get a freeze in the FX application thread then your trigger the spinner button multiple times.
*
* Doing this on a thread gets rid of the issue but is not a particular nice solution.
*/
task = new Task<Integer>() {
@Override protected Integer call() throws Exception {
Series<Number, Number> signalLevelSeries1 = calcSeries(waveform, shortFilter);
Series<Number, Number> noiseLevelSeries2 = calcSeries(waveform, longFilter);
Platform.runLater(()->{
// if (shortFilter!=shortFilter1 || forceChange) {
plotChart.getData().remove(signalLevelSeries);
plotChart.getData().add(signalLevelSeries1);
signalLevelSeries = signalLevelSeries1;
// }
// if (shortFilter!=shortFilter1 || forceChange) {
plotChart.getData().remove(noiseLevelSeries);
plotChart.getData().add(noiseLevelSeries2);
noiseLevelSeries = noiseLevelSeries2;
// }
});
return 0;
}
};
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
}
}
private Series<Number, Number> calcSeries(double[] waveform, double alpha){
Series<Number, Number> signalLevelSeries1 = new Series<Number, Number>();
double[] signalLevel=calcFilter(waveform, alpha);
for (int i=0; i<waveform.length; i++){
signalLevelSeries1.getData().add(new Data<Number, Number>(i, signalLevel[i]));
}
return signalLevelSeries1;
}
/**
* Generate a click waveform with some added noise.
* @param type - the type of click e.g. ClickTriggerGraph.PORPOISE_CLICK.
* @param noise. 0 to 1. 1 means max noise amplitude will be same as maximum click amplitude.
* @return click and noise waveform.
*/
private void generateClickWaveform(ExampleSoundType selectedItem, double noise) {
ExampleSound sound = this.exampleSoundFactory.getExampleSound(selectedItem);
double sR = sound.getSampleRate();
//System.out.println("Waveform: " + sound.getWave().length + " " + selectedItem);
double[] clickWave = PamArrayUtils.divide( sound.getWave(), PamArrayUtils.max( sound.getWave()));
//now need to work out how many noise samples to add. Use the length of the click
int nNoiseSamples=Math.min((int) (clickWave.length), sound.getWave().length >2000? 0 : 100);
double[] waveform=new double[2*nNoiseSamples + clickWave.length];
int n=0;
double[] signal=clickWave;
for (int i=0; i<waveform.length; i++){
double noiseSample=noise*(Math.random()-0.5);
if (i>nNoiseSamples && n<clickWave.length){
waveform[i]=signal[n]+noiseSample;
n=n+1;
}
else waveform[i]=noiseSample;
}
this.waveform=waveform;
//System.out.println("Waveform: " + waveform.length);
}
public double getShortFilter() {
return shortFilter;
}
@ -185,6 +278,6 @@ public class ClickTriggerGraph extends PamBorderPane {
}
}

View File

@ -18,6 +18,7 @@ import clickDetector.ClickClassifiers.basic.BasicClickIdentifier;
/**
* Pane for the basic click classifier.
*
* @author Jamie Macaulay
*
*/
@ -319,4 +320,13 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX {
return clickClassifiers;
}
/**
* Get the flip pane. One side shows the table, the other shows the currently selected classifier settings.
* @return the flip pane.
*/
public PamFlipPane getFlipPane() {
return flipPane;
}
}

View File

@ -23,10 +23,13 @@ import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.PamStackPane;
import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxNodes.hidingPane.HidingPane;
import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
/**
* Pane which allows users to select click classifiers. Rather than opening endless dialogs click settings are
* handled by sliding panes.
* <p>
* Note that this is a copy...ish of the swing frameowrk - wouldn't od things this way usually.
* @author Jamie Macaulay
*
*/
@ -43,7 +46,7 @@ public class ClickClassifyPaneFX extends PamStackPane {
private ClickControl clickControl;
private CheckBox runOnlineCheckBox;
private PamToggleSwitch runOnlineCheckBox;
private CheckBox discardClicksCheckBox;
@ -120,16 +123,16 @@ public class ClickClassifyPaneFX extends PamStackPane {
classifierComboBox.getItems().add(clickControl.getClassifierManager().getClassifierName(i));
classifierComboBox.setOnAction((action)->{
//get the current click identifier.
System.out.println("ClickClassifyPaneFX:setOnAction: " +classifierComboBox.getSelectionModel().getSelectedIndex());
//System.out.println("ClickClassifyPaneFX:setOnAction: " +classifierComboBox.getSelectionModel().getSelectedIndex());
currentClickIdentifier=clickControl.getClassifierManager().
getClassifier(classifierComboBox.getSelectionModel().getSelectedIndex());
getClassifier(classifierComboBox.getSelectionModel().getSelectedIndex());
//change the centre pane to classifier specific pane
setCenterPane();
});
}
runOnlineCheckBox=new CheckBox("Run Classifier");
discardClicksCheckBox=new CheckBox("Discdard Classified Clicks");
runOnlineCheckBox=new PamToggleSwitch("Run Classifier");
//discardClicksCheckBox=new CheckBox("Discdard Classified Clicks");
PamHBox pamHBox=new PamHBox();
pamHBox.setAlignment(Pos.CENTER);
@ -168,6 +171,9 @@ public class ClickClassifyPaneFX extends PamStackPane {
//System.out.println("ClickClassifyPaneFX:setParams(): " +classifierComboBox.getSelectionModel().getSelectedIndex());
classifierComboBox.getSelectionModel().select(clickParameters.clickClassifierType);
//System.out.println("ClickClassifyPaneFX: setParams: get selected classifier is: " + clickParameters.clickClassifierType);
//set classifier parameters
if (currentClickIdentifier!=null && currentClickIdentifier.getClassifierPane()!=null) {
this.currentClickIdentifier.getClassifierPane().setParams();
@ -180,6 +186,8 @@ public class ClickClassifyPaneFX extends PamStackPane {
//System.out.println("ClickClassifyPaneFX:getParams(): " +classifierComboBox.getSelectionModel().getSelectedIndex());
clickParameters.clickClassifierType=classifierComboBox.getSelectionModel().getSelectedIndex();
//System.out.println("ClickClassifyPaneFX: getParams: get selected classifier is: " + clickParameters.clickClassifierType);
if (currentClickIdentifier != null && currentClickIdentifier.getClassifierPane() != null) {
currentClickIdentifier.getClassifierPane().getParams();
}

View File

@ -38,6 +38,14 @@ public class SweepClassifierPaneFX extends BasicIdentifierPaneFX {
@Override
public void setClassifierPane(ClickTypeProperty clickTypeProperty){
SweepClassifierSetPaneFX sweepPane=new SweepClassifierSetPaneFX(sweepClickClassifier);
//make it so the title of the pane is the same as the name as the classifier
getFlipPane().getAdvLabel().textProperty().unbind();
getFlipPane().getAdvLabel().textProperty().bind( sweepPane.getNameTextProperty());
sweepPane.classifierItemRow = sweepClickClassifier.getSweepClassifierParams().getSetRow((SweepClassifierSet) clickTypeProperty.getClickType());
sweepPane.setParams(clickTypeProperty);
super.getClickTypeHolder().setCenter(sweepPane.getContentNode());
@ -52,14 +60,20 @@ public class SweepClassifierPaneFX extends BasicIdentifierPaneFX {
@Override
public void setParams() {
sweepIdParameters = sweepClickClassifier.getSweepClassifierParams().clone();
//change the table
tableDataChanged();
}
@Override
public boolean getParams() {
sweepClickClassifier.setSeepClassifierParams(sweepIdParameters);
// System.out.println("Sweep classifier getParams: " + sweepIdParameters);
if (sweepIdParameters==null) sweepIdParameters = new SweepClassifierParameters();
sweepClickClassifier.setSweepClassifierParams(sweepIdParameters);
//remove all classifiers and add whatever is in the table.
sweepClickClassifier.getSweepClassifierParams().removeAll();

View File

@ -3,6 +3,7 @@ package clickDetector.layoutFX.clickClassifiers;
import fftFilter.FFTFilterParams;
import fftManager.FFTLengthModeled;
import javafx.beans.property.StringProperty;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
@ -30,9 +31,13 @@ import pamViewFX.fxNodes.picker.SymbolPicker;
import pamViewFX.fxNodes.utilityPanes.FreqBandPane;
import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
import pamViewFX.fxNodes.utilityPanes.SimpleFilterPaneFX;
import pamViewFX.fxNodes.utilsFX.PamUtilsFX;
import pamViewFX.PamGuiManagerFX;
import net.synedra.validatorfx.Validator;
import PamController.SettingsPane;
import PamView.PamSymbol;
import PamView.symbol.SymbolData;
import clickDetector.ClickClassifiers.basicSweep.CodeHost;
import clickDetector.ClickClassifiers.basicSweep.SweepClassifier;
import clickDetector.ClickClassifiers.basicSweep.SweepClassifierSet;
@ -95,7 +100,11 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
*/
private AmplitudeBlock amplitudeBlock;
PamBorderPane mainPane = new PamBorderPane();
private PamBorderPane mainPane = new PamBorderPane();
private Validator validator = new Validator();
public int classifierItemRow;
public SweepClassifierSetPaneFX(SweepClassifier sweepClassifier){
super(null);
@ -325,6 +334,14 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
*/
private Label lengthMS;
private ComboBox<String> lengthTypeBox;
private CheckBox restrictLength;
private ColorPicker lineColourPicker;
private ColorPicker fillColourPicker;
OptionsBox() {
super("General Options", false);
this.getHolderPane().setCenter(createOptionsPane());
@ -334,6 +351,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
//create the general options
private Node createOptionsPane(){
PamGridPane pamGridPane=new PamGridPane();
pamGridPane.setHgap(5);
pamGridPane.setVgap(5);
@ -343,25 +361,54 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
nameField=new TextField();
nameField.setPrefColumnCount(10);
pamGridPane.add(nameField, 0, 0);
PamGridPane.setColumnSpan(nameField, 2);
pamGridPane.add(nameField, 1, 0);
PamGridPane.setColumnSpan(nameField, 8);
PamGridPane.setHgrow(nameField, Priority.ALWAYS);
pamGridPane.add(new Label("Code"), 3, 0);
validator.createCheck()
.dependsOn("speciesname", nameField.textProperty())
.withMethod(c -> {
String userName = c.get("speciesname");
if (userName == null || userName.length()<=0) {
c.error("The classifier must have a name");
}
})
.decorates(nameField)
.immediate();
;
pamGridPane.add(new Label("Code"), 0, 1);
codeSpinner=new PamSpinner<Integer> (0, 500, 0, 1);
codeSpinner=new PamSpinner<Integer> (1, 500, 0, 1);
codeSpinner.setEditable(true);
//codeSpinner.setPrefWidth(150);
codeSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
pamGridPane.add(codeSpinner, 1, 0);
pamGridPane.add(codeSpinner, 1, 1);
// pamGridPane.add(new Label("Symbol"), 0,1);
//create colour picker to allow users to change symbol colour.
symbolPicker=new SymbolPicker();
pamGridPane.add(symbolPicker, 2, 0);
pamGridPane.add(symbolPicker, 3,1);
pamGridPane.add(new Label("Symbol"), 3,0);
pamGridPane.add(new Label("Symbol"), 2,1);
lineColourPicker = new ColorPicker();
lineColourPicker.setStyle("-fx-color-label-visible: false ;");
lineColourPicker.setOnAction((action)->{
symbolPicker.setLineColour(lineColourPicker.getValue());
});
pamGridPane.add(lineColourPicker, 4, 1);
fillColourPicker = new ColorPicker();
fillColourPicker.setStyle("-fx-color-label-visible: false ;");
fillColourPicker.setOnAction((action)->{
symbolPicker.setFillColour(fillColourPicker.getValue());
});
pamGridPane.add(fillColourPicker, 5, 1);
// //create a button to allow users to change symbol shape.
// symbolColour=new ColorPicker();
@ -371,35 +418,46 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
// });
//channel options
pamGridPane.add(new Label("Channels"), 0,1);
pamGridPane.add(new Label("Channels"), 0,2);
channelsBox = new ComboBox<String>();
for (int i = 0; i < 3; i++) {
channelsBox.getItems().add(SweepClassifierSet.getChannelOptionsName(i));
}
pamGridPane.add(channelsBox, 1,1);
pamGridPane.add(channelsBox, 1,2);
PamGridPane.setColumnSpan(channelsBox, 7);
PamGridPane.setColumnSpan(channelsBox,8 );
//restrict parameter to click centre
PamHBox clickCenterBox=new PamHBox();
clickCenterBox.setSpacing(5);
clickCenterBox.getChildren().add(new CheckBox("Analyse click "));
clickCenterBox.getChildren().add(restrictLength = new CheckBox("Trim click"));
clickLengthSpinner=new PamSpinner<Integer>(4,102400,128,32);
clickLengthSpinner.setEditable(true);
//clickLengthSpinner.setPrefWidth(150);
clickLengthSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
clickLengthSpinner.valueProperty().addListener((obsVal, oldVal, newVal)->{
setLengthLabel();
});
clickCenterBox.getChildren().add(clickLengthSpinner);
clickCenterBox.getChildren().add(new Label("samples"));
Label samplesLabel =new Label("samples");
clickCenterBox.getChildren().add(samplesLabel);
clickCenterBox.getChildren().add(lengthMS=new Label("()"));
clickCenterBox.getChildren().add(new Label("around click center."));
clickCenterBox.getChildren().add(lengthTypeBox = new ComboBox<String>());
lengthTypeBox.getItems().add("around click center");
lengthTypeBox.getItems().add("from start of click");
clickCenterBox.setAlignment(Pos.CENTER_LEFT);
PamGridPane.setColumnSpan(clickCenterBox, 4);
PamGridPane.setHgrow(clickCenterBox, Priority.ALWAYS);
pamGridPane.add(clickCenterBox, 0,2);
restrictLength.setOnAction((action)->{
lengthTypeBox.setDisable(!restrictLength.isSelected());
clickLengthSpinner.setDisable(!restrictLength.isSelected());
samplesLabel.setDisable(!restrictLength.isSelected());
lengthMS.setDisable(!restrictLength.isSelected());
});
// //column constraints
// ColumnConstraints col1 = new ColumnConstraints();
@ -414,14 +472,16 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
// col4.setPercentWidth(35);
//
// pamGridPane.getColumnConstraints().addAll(col1, col2, col3,col4);
return pamGridPane;
PamVBox holder = new PamVBox();
holder.setSpacing(5);
holder.getChildren().addAll(pamGridPane,clickCenterBox);
return holder;
}
@Override
public int getCode() {
// TODO Auto-generated method stub
return codeSpinner.getValue();
}
@ -441,29 +501,99 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
float sr = sweepClassifier.getClickDetector().getSampleRate();
lengthMS.setText(String.format("(%.2f ms)", fftLength * 1000 / sr));
}
/**
* Set the length in seconds.
*/
private void setLengthLabel() {
float sr = sweepClassifier.getClickDetector().getSampleRate();
lengthMS.setText(String.format("(%.2f ms)", clickLengthSpinner.getValue() * 1000 / sr));
}
@Override
protected void setParams() {
nameField.setText(sweepClassifierSet.getName());
codeSpinner.getValueFactory().setValue(sweepClassifierSet.getSpeciesCode());
if (sweepClassifierSet == null) {
//symbolViewer.setSymbol(null);
symbolPicker.getSelectionModel().select(0);
nameField.setText("");
setCode(sweepClassifier.getNextFreeCode(0));
}
else {
symbolPicker.setSymbol(sweepClassifierSet.symbol == null? null : sweepClassifierSet.symbol.getSymbol());
nameField.setText(sweepClassifierSet.getName());
setCode(sweepClassifierSet.getSpeciesCode());
}
if (sweepClassifierSet == null) {
return;
}
lengthTypeBox.getSelectionModel().select(sweepClassifierSet.restrictedBinstype);
channelsBox.getSelectionModel().select(sweepClassifierSet.channelChoices);
clickLengthSpinner.getValueFactory().setValue(sweepClassifierSet.restrictedBins);
restrictLength.setSelected(sweepClassifierSet.restrictLength);
setFFTLength(sweepClassifierSet.restrictedBins);
// nameField.setText(sweepClassifierSet.getName());
// codeSpinner.getValueFactory().setValue(sweepClassifierSet.getSpeciesCode());
// channelsBox.getSelectionModel().select(sweepClassifierSet.channelChoices);
//
// //length stuff
// clickLengthSpinner.getValueFactory().setValue(sweepClassifierSet.restrictedBins);
}
@Override
protected boolean getParams() {
sweepClassifierSet.setName(nameField.getText());
sweepClassifierSet.setSpeciesCode(codeSpinner.getValue());
sweepClassifierSet.channelChoices=channelsBox.getSelectionModel().getSelectedIndex();
sweepClassifierSet.restrictedBins=clickLengthSpinner.getValue();
if (this.symbolPicker.getValue()==null) {
return showWarning("You must pick a symbol");
}
SymbolData symbolData = new SymbolData(this.symbolPicker.getValue().getSymbol(), 10,10,true,
PamUtilsFX.fxToAWTColor(this.lineColourPicker.getValue()), PamUtilsFX.fxToAWTColor(this.fillColourPicker.getValue()));
sweepClassifierSet.symbol= new PamSymbol(symbolData);
if (sweepClassifierSet.getName().length() <= 0) {
return showWarning("You must enter a name for this type of click");
}
sweepClassifierSet.setSpeciesCode(getCode());
if (sweepClassifier.codeDuplicated(sweepClassifierSet, classifierItemRow) ||
sweepClassifierSet.getSpeciesCode() <= 0){
return showWarning("You must enter a unique positive integer species code");
}
if (sweepClassifierSet.symbol == null) {
return showWarning("You must select a symbol");
}
sweepClassifierSet.channelChoices = channelsBox.getSelectionModel().getSelectedIndex();
sweepClassifierSet.restrictLength = restrictLength.isSelected();
sweepClassifierSet.restrictedBinstype = lengthTypeBox.getSelectionModel().getSelectedIndex();
try {
sweepClassifierSet.restrictedBins = clickLengthSpinner.getValue();
}
catch (NumberFormatException e) {
return showWarning("Invalid Restricted length value");
}
return true;
// sweepClassifierSet.setName(nameField.getText());
// sweepClassifierSet.setSpeciesCode(codeSpinner.getValue());
// sweepClassifierSet.channelChoices=channelsBox.getSelectionModel().getSelectedIndex();
// sweepClassifierSet.restrictedBins=clickLengthSpinner.getValue();
}
@Override
protected void disbleControls(boolean enable) {
// TODO Auto-generated method stub
}
public TextField getNameLabel() {
return this.nameField;
}
}
@ -1111,4 +1241,15 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
}
public StringProperty getNameTextProperty() {
return optionBox.getNameLabel().textProperty();
}
private boolean showWarning(String string) {
PamDialogFX.showWarning(string);
return false;
}
}

View File

@ -9,10 +9,7 @@ import clickTrainDetector.classification.CTClassifier;
import clickTrainDetector.classification.CTClassifierParams;
import clickTrainDetector.classification.CTClassifierType;
import clickTrainDetector.classification.bearingClassifier.BearingClassifier;
import clickTrainDetector.classification.bearingClassifier.BearingClassifierParams;
import clickTrainDetector.classification.idiClassifier.IDIClassification;
import clickTrainDetector.classification.idiClassifier.IDIClassifier;
import clickTrainDetector.classification.simplechi2classifier.Chi2CTClassification;
import clickTrainDetector.classification.simplechi2classifier.Chi2ThresholdClassifier;
import clickTrainDetector.classification.templateClassifier.CTTemplateClassifier;
import clickTrainDetector.layout.classification.CTClassifierGraphics;

View File

@ -342,7 +342,7 @@ public abstract class OfflineFileServer<TmapPoint extends FileDataMapPoint> impl
return "Sound Files";
}
protected TmapPoint findFirstMapPoint(Iterator<TmapPoint> mapIterator, long startMillis, long endMillis) {
public TmapPoint findFirstMapPoint(Iterator<TmapPoint> mapIterator, long startMillis, long endMillis) {
TmapPoint mapPoint, prevMapPoint = null;
while (mapIterator.hasNext()) {
mapPoint = mapIterator.next();

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import PamController.PamController;
import PamModel.PamModuleInfo;
import atlantafx.base.theme.PrimerDark;
import dataModelFX.ConnectionNodeParams.PAMConnectionNodeType;
import dataModelFX.connectionNodes.ModuleIconFactory;
import javafx.beans.property.ObjectProperty;
@ -12,6 +13,7 @@ import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Button;
import javafx.scene.control.Tooltip;
import javafx.scene.image.ImageView;
import javafx.scene.input.ClipboardContent;
@ -72,7 +74,9 @@ public class DataModelModulePane extends PamBorderPane {
private PamScrollPane createPane(){
moduleSelectPane=new PamScrollPane();
moduleSelectPane.getStylesheets().add(PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getSlidingDialogCSS());
moduleSelectPane.getStylesheets().add(PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getSlidingDialogCSS());
moduleSelectPane.setPrefWidth(250);
moduleSelectPane.getStyleClass().add("scroll-pane-dark");

View File

@ -16,6 +16,7 @@ import pamViewFX.fxNodes.connectionPane.StandardConnectionNode;
import pamViewFX.fxNodes.connectionPane.StandardConnectionPlug;
import pamViewFX.fxNodes.connectionPane.structures.ConnectionGroupStructure;
import pamViewFX.fxNodes.connectionPane.structures.ConnectionStructure;
import pamViewFX.fxStyles.PamStylesManagerFX;
import javafx.beans.property.ObjectProperty;
import javafx.geometry.Orientation;
import javafx.scene.control.SplitPane;

View File

@ -71,7 +71,7 @@ public class ModuleProcessDiagram extends PamBorderPane {
public ModuleProcessDiagram (PamControlledUnit pamControlledUnit){
this.getStylesheets().add(PamController.getInstance().getGuiManagerFX().getPamSettingsCSS());
//this.getStylesheets().add(PamController.getInstance().getGuiManagerFX().getPamSettingsCSS());
this.pamControlledUnit=pamControlledUnit;
createUpdateTimer();
createControlDataModel();
@ -81,7 +81,7 @@ public class ModuleProcessDiagram extends PamBorderPane {
private void createControlDataModel(){
this.setMinWidth(100);
this.setPrefWidth(USE_COMPUTED_SIZE);
this.setStyle("-fx-background-color: -fx-darkbackground");
//this.setStyle("-fx-background-color: -fx-darkbackground");
this.populateDataModel();
}

View File

@ -158,7 +158,7 @@ public class TDDisplayFX extends PamBorderPane {
/**
* The height of the control pane.
*/
final static double controlPaneHeight=63;
final static double CONTROL_PANE_HEIGHT=80;
/**
@ -238,7 +238,7 @@ public class TDDisplayFX extends PamBorderPane {
//create top hiding panel.
controlPane=new TDControlPaneFX(tdControl,this);
controlPane.setParams(tdParametersFX);
controlPane.setPrefHeight(controlPaneHeight);
controlPane.setPrefHeight(CONTROL_PANE_HEIGHT);
hidingControlPane=new HidingPane(Side.TOP, controlPane, this, false );
hidingControlPane.showHidePane(tdParametersFX.showControl);

View File

@ -272,7 +272,7 @@ public class TDGraphFX extends PamBorderPane {
* blocks.
*/
tdAxisSelPane = new TDDataSelPaneFX(this);
tdAxisSelPane.setPrefWidth(250);
tdAxisSelPane.setPrefWidth(280);
// put pane inside a scroll pane for graph resizing
PamScrollPane scrollPane = new PamScrollPane(tdAxisSelPane);
// scrollPane.setFitToWidth(true);

View File

@ -498,7 +498,7 @@
plotted on the time-based display by adding Click detections to the
display and then using the right</p>
<p align="center">
<img width="940" height="500" src="resources/clicktrain_TDFx.png">
<img width="940" height="500" src="resources/clicktrain_TDFX.png">
</p>
<p>

View File

@ -7,11 +7,14 @@ import java.util.ArrayList;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import PamController.PamControlledUnit;
import PamController.PamControlledUnitGUI;
import PamController.PamControlledUnitSettings;
import PamController.PamControllerInterface;
import PamController.PamGUIManager;
import PamController.PamSettingManager;
import PamController.PamSettings;
import PamController.SettingsPane;
import PamView.WrapperControlledGUISwing;
import PamView.symbol.SymbolData;
import PamguardMVC.PamDataBlock;
import clickDetector.ClickClassifiers.ClickTypeProvider;
@ -66,6 +69,17 @@ public class MTClassifierControl extends PamControlledUnit implements PamSetting
* The offline process.
*/
private MTOfflineProcess mtOfflineProcess;
/**
* The JavaFX graphics
*/
private MTControlGUI matchedClickGUIFX;
/**
* The swing graphics - in this case the graphics are JavaFX so this calls a swing wrapper
* to hold the JavaFX graphics.
*/
private PamControlledUnitGUI matchedClickGUIGUISwing;
public MTClassifierControl(String unitName) {
@ -379,6 +393,33 @@ public class MTClassifierControl extends PamControlledUnit implements PamSetting
return mtOfflineProcess;
}
public void setMTParams(MatchedTemplateParams newParams) {
this.matchedTemplateParams = newParams;
}
/**
* Get the GUI for the PAMControlled unit. This has multiple GUI options which
* are instantiated depending on the view type.
*
* @param flag. The GUI type flag defined in PAMGuiManager.
* @return the GUI for the PamControlledUnit unit.
*/
public PamControlledUnitGUI getGUI(int flag) {
if (flag == PamGUIManager.FX) {
if (matchedClickGUIFX == null) {
matchedClickGUIFX = new MTControlGUI(this);
}
return matchedClickGUIFX;
}
if (flag == PamGUIManager.SWING) {
if (matchedClickGUIGUISwing == null) {
matchedClickGUIGUISwing = new WrapperControlledGUISwing(this);
}
return matchedClickGUIGUISwing;
}
return null;
}

View File

@ -0,0 +1,74 @@
package matchedTemplateClassifer;
import PamController.PamControlledUnitGUI;
import PamController.PamController;
import PamController.PamControllerInterface;
import PamController.PamGUIManager;
import PamController.SettingsPane;
import PamView.WrapperControlledGUISwing;
import pamViewFX.PamControlledGUIFX;
import rawDeepLearningClassifier.DLControl;
import rawDeepLearningClassifier.DLControlGUI;
import rawDeepLearningClassifier.RawDLParams;
/**
* The JavaFX GUI for the Matched click classifier control...
* @author Jamie Macaulay
*
*/
public class MTControlGUI extends PamControlledGUIFX {
/**
* The dl control.
*/
private MTClassifierControl mtControl;
public MTControlGUI(MTClassifierControl dlcontrol) {
this.mtControl = dlcontrol;
}
/**
* The settings pane contains ALL possible setting for the module in one placed.
* Settings panes can be divided into tabs for more space etc.
*
* @param <T>
* @return a Pane containing controls to change settings for module.
*/
public SettingsPane<?> getSettingsPane(){
mtControl.getSettingsPane().setParams(mtControl.getMTParams());
return mtControl.getSettingsPane();
}
@Override
public void updateParams() {
MatchedTemplateParams newParams=mtControl.getSettingsPane().getParams(mtControl.getMTParams());
if (newParams!=null) {
mtControl.setMTParams(newParams);
}
//setup the controlled unit.
mtControl.setupControlledUnit();
}
@Override
public void notifyGUIChange(int changeType) {
switch (changeType) {
case PamController.INITIALIZATION_COMPLETE:
break;
case PamControllerInterface.CHANGED_PROCESS_SETTINGS:
//data source may have potentially changed. e.g. by a datamodelfx Need to set in params.
//System.out.println("FFTControl: CHANGED_PROCESS_SETTINGS : " +fftProcess.getParentDataBlock());
if (mtControl.getParentDataBlock()!=null){
mtControl.getMTParams().dataSourceName = mtControl.getParentDataBlock().getDataName();
}
else mtControl.getMTParams().dataSourceName = "";
break;
}
}
}

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import PamController.PamController;
import PamDetection.RawDataUnit;
import PamUtils.complex.ComplexArray;
import PamView.symbol.PamSymbolManager;
import PamguardMVC.PamDataBlock;
@ -12,8 +13,10 @@ import PamguardMVC.PamInstantProcess;
import PamguardMVC.PamObservable;
import PamguardMVC.RawDataHolder;
import Spectrogram.WindowFunction;
import clickDetector.ClickDetection;
import clickDetector.ClickLength;
import clickDetector.ClickClassifiers.basicSweep.SweepClassifierSet;
import clipgenerator.ClipDataUnit;
import fftManager.FastFFT;
import matchedTemplateClassifer.annotation.MatchedClickAnnotation;
import matchedTemplateClassifer.annotation.MatchedClickAnnotationType;
@ -485,6 +488,21 @@ public class MTProcess extends PamInstantProcess {
public BeskopeClassifierManager getBespokeClassifierManager() {
return bespokeClassifierManager;
}
/**
* A list of data block class types which are compatible as parent data blocks
* for the PamProcess. This can return null, e.g. in the case of Acquisition
* process.
*
* @return a list of PamDataBlock sub class types which can be used as parent
* data blocks for the process.
*/
@Override
public ArrayList getCompatibleDataUnits(){
return new ArrayList<Class<? extends PamDataUnit>>(Arrays.asList(ClickDetection.class));
}
// /**
// * Get the parent click data block.

View File

@ -9,9 +9,10 @@ import java.net.Socket;
import javax.swing.JComponent;
import javax.swing.Timer;
import x3.CRC16;
import x3.X3FrameDecode;
import x3.X3FrameHeader;
import org.pamguard.x3.x3.CRC16;
import org.pamguard.x3.x3.X3FrameDecode;
import org.pamguard.x3.x3.X3FrameHeader;
import networkTransfer.NetworkObject;
import networkTransfer.receive.BuoyStatusDataUnit;
import networkTransfer.receive.NetworkDataUser;

View File

@ -13,12 +13,15 @@ import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxNodes.internalNode.PamInternalPane;
import pamViewFX.fxNodes.pamDialogFX.PamDialogFX;
import pamViewFX.fxNodes.pamDialogFX.PamSettingsDialogFX;
import pamViewFX.fxStyles.PamAtlantaStyle;
import pamViewFX.fxStyles.PamStylesManagerFX;
import pamViewFX.pamTask.PamTaskUpdate;
import userDisplayFX.UserDisplayNodeFX;
import PamModel.PamModel;
import PamModel.PamModuleInfo;
import PamView.PamViewInterface;
import atlantafx.base.theme.PrimerDark;
import atlantafx.base.theme.PrimerLight;
import dataMap.layoutFX.DataMapPaneFX;
import PamController.PAMControllerGUI;
import PamController.PamControlledUnit;
@ -28,6 +31,7 @@ import PamController.PamGUIManager;
import PamController.PamSettingManager;
import PamController.PamSettings;
import dataModelFX.DataModelPaneFX;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
@ -134,11 +138,11 @@ public class PamGuiManagerFX implements PAMControllerGUI, PamSettings {
public PamGuiManagerFX(PamController pamController, Object stage) {
this.pamController=pamController;
pamGuiSettings= new PAMGuiFXSettings();
primaryStage= (Stage) stage;
primaryStage.setOnCloseRequest(e->{
@ -159,19 +163,22 @@ public class PamGuiManagerFX implements PAMControllerGUI, PamSettings {
*/
private void start(Stage primaryStage) {
PamStylesManagerFX.getPamStylesManagerFX().setCurStyle(new PamAtlantaStyle());
//add stage
stages.add(primaryView = new PamGuiFX(primaryStage, this));
//create new data model.
dataModelFX=stages.get(0).addDataModelTab();
scene = new Scene(stages.get(0));
scene.getStylesheets().add(getPamCSS());
// Application.setUserAgentStylesheet(new PrimerDark().getUserAgentStylesheet());
// stages.get(0).prefWidthProperty().bind(scene.widthProperty());
// stages.get(0).prefHeightProperty().bind(scene.heightProperty());
primaryStage.setScene(scene);
// scene.getStylesheets().add(pamCSS);
scene.getStylesheets().add(getPamCSS());
//need to add this for material design icons and fontawesome icons
// scene.getStylesheets().addAll(GlyphsStyle.DEFAULT.getStylePath());
@ -458,7 +465,7 @@ public class PamGuiManagerFX implements PAMControllerGUI, PamSettings {
TabSelectionPane tabSelectionPane=new TabSelectionPane(stages.get(0));
PamSettingsDialogFX<?> settingsDialog=new PamSettingsDialogFX(tabSelectionPane);
settingsDialog.getDialogPane().getStylesheets().add(PamController.getInstance().getGuiManagerFX().getPamSettingsCSS());
settingsDialog.getDialogPane().getStylesheets().add(PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getDialogCSS());
settingsDialog.initStyle(StageStyle.UNDECORATED);
// ChoiceDialog<String> dialog = new ChoiceDialog<>(tabStrings.get(1), tabStrings);
@ -485,7 +492,7 @@ public class PamGuiManagerFX implements PAMControllerGUI, PamSettings {
* Get CSS for PAMGUARD setting 'look and feel' for sliding dialogs
* @return the CSS for settings feels.
*/
public String getPamSettingsCSS() {
public String getPamSettingsCSS() {//return new PrimerDark().getUserAgentStylesheet();
// return getClass().getResource("/Resources/css/pamSettingsCSS.css").toExternalForm();
return PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getSlidingDialogCSS();
}
@ -495,6 +502,7 @@ public class PamGuiManagerFX implements PAMControllerGUI, PamSettings {
* @return the standard CSS fro PAMGUARD.
*/
public String getPamCSS() {
//return new PrimerLight().getUserAgentStylesheet();
// return getClass().getResource("/Resources/css/pamCSS.css").toExternalForm();
return PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getGUICSS();
}
@ -503,8 +511,9 @@ public class PamGuiManagerFX implements PAMControllerGUI, PamSettings {
* Get CSS for PAMGUARD GUI standard 'look and feel' for regular dialogs
* @return the standard CSS fro PAMGUARD.
*/
public String getPamDialogCSS() {
return PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getSlidingDialogCSS();
public String getPamDialogCSS() {//return new PrimerDark().getUserAgentStylesheet();
return PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getDialogCSS();
}
@ -644,7 +653,7 @@ public class PamGuiManagerFX implements PAMControllerGUI, PamSettings {
mainPane.getChildren().addAll(title, namePane);
dialog.getDialogPane().setContent(mainPane);
dialog.getDialogPane().getStylesheets().add(PamController.getInstance().getGuiManagerFX().getPamSettingsCSS());
dialog.getDialogPane().getStylesheets().add(this.getPamDialogCSS());
//add listener to prevent close request if the dialog
final Button btOk = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);

View File

@ -166,6 +166,8 @@ public class PamGuiTabFX extends PamTabFX {
//create a new GUI frame.
PamGuiFX pamGUIFX=new PamGuiFX(tabPane, newStage, pamGui.getPamGuiManagerFX());
pamGUIFX.getStylesheets().add(pamGui.getPamGuiManagerFX().getPamCSS());
//need to add PamGUIFX to list in PamGUIManagerFX.
pamGui.getPamGuiManagerFX().getPamGuiFXList().add(pamGUIFX);
newStage.setOnCloseRequest(e->{

View File

@ -18,50 +18,50 @@ public class PamSpinner<T> extends Spinner<T>{
* Default widths are way off in JavaFX for spinners.
*/
// private static final double PAMSPINNER_PREF_WIDTH = USE_COMPUTED_SIZE;
private static final double PAMSPINNER_PREF_WIDTH = 100;
//private static final double PAMSPINNER_PREF_WIDTH = 100;
public PamSpinner() {
super();
this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
//this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
// TODO Auto-generated constructor stub
}
public PamSpinner(double min, double max, double initialValue, double amountToStepBy) {
super(min, max, initialValue, amountToStepBy);
this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
//this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
addDefocusConverter();
}
public PamSpinner(double min, double max, double initialValue) {
super(min, max, initialValue);
this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
//this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
addDefocusConverter();
}
public PamSpinner(int min, int max, int initialValue, int amountToStepBy) {
super(min, max, initialValue, amountToStepBy);
this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
//this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
addDefocusConverter();
}
public PamSpinner(int min, int max, int initialValue) {
super(min, max, initialValue);
this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
//this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
addDefocusConverter();
}
public PamSpinner(ObservableList<T> arg0) {
super(arg0);
this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
//this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
addDefocusConverter();
}
public PamSpinner(SpinnerValueFactory<T> arg0) {
super(arg0);
addDefocusConverter();
this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
//this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
}
/**

View File

@ -1,492 +0,0 @@
/**
* CSS for PAMGUARD settings panels. These are dark with clean white buttons and a cyan highlight them.
*
* Author: Jamie Macaulay;
**/
/*******************************************************************************
* *
* Declare colour variables *
* *
******************************************************************************/
* {
-fx-darkbackground: rgba(60,60,60,.90);
-fx-highlight: rgba(0,204,204,.75);
-fx-highlight_border: rgba(0,204,204,1);
-fx-text: white;
-fx-border_col: white;
}
/*******************************************************************************
* *
* Panes *
* *
******************************************************************************/
.root {
-fx-background-color: -fx-darkbackground;
-fx-padding: 10;
}
.pane {
-fx-background-color: -fx-darkbackground;
}
.border{
-fx-background-color: -fx-darkbackground;
}
.grid {
-fx-background-color: -fx-darkbackground;
}
.hBox {
-fx-background-color: -fx-darkbackground;
}
/*******************************************************************************
* *
* Hiding Tab *
* *
******************************************************************************/
#hide-tab {
-fx-background-color: transparent;
-fx-border-radius: 5 5 0 0;
-fx-background-radius: 5 5 0 0;
-fx-border-color: -fx-border_col;
}
#show-tab {
-fx-background-color: transparent;
-fx-border-radius: 5 5 0 0;
-fx-background-radius: 5 5 0 0;
-fx-border-color: -fx-border_col;
}
#hide-tab-highlight {
-fx-background-color: -fx-highlight;
-fx-border-radius: 5 5 0 0;
-fx-background-radius: 5 5 0 0;
-fx-border-color: -fx-highlight_border;
}
/*******************************************************************************
* *
* Label *
* *
******************************************************************************/
.label{
-fx-text-fill: -fx-text;
}
/*******************************************************************************
* *
* Slider *
* *
******************************************************************************/
.slider .axis {
-fx-fill: -fx-text;
-fx-stroke: -fx-text;
-fx-tick-label-fill: -fx-text;
-fx-text-fill: -fx-text;
-fx-tick-mark-stroke: -fx-text;
}
/*******************************************************************************
* *
* Dialog Pane *
* *
******************************************************************************/
.dialog-pane {
-fx-background-color: -fx-darkbackground;
}
/*******************************************************************************
* *
* Button *
* *
******************************************************************************/
.button{
-fx-text-fill: white;
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
-fx-border-radius: 5;
-fx-background-radius:6;
-fx-padding: 3 6 6 6;
}
.button:hover{
-fx-background-color: -fx-highlight;
-fx-border-color: -fx-highlight_border;
}
.button:selected{
-fx-border-color: -fx-highlight;
}
/**
* Button for closing a hiding panel. Right indicates bottoms points towards the right, closing a hiding panel
* on the right hand side of the screen. These buttons have a transparent background and rounded corners.
*/
/** top-left, top-right, bottom-right, and bottom-left corners, in that order. */
.close-button-right{
-fx-background-color: transparent;
-fx-background-radius: 0 10 10 0;
-fx-border-radius: 0 10 10 0;
}
.close-button-left{
-fx-background-color: transparent;
-fx-background-radius: 10 0 0 10;
-fx-border-radius: 10 0 0 10;
}
.close-button-top{
-fx-background-color: transparent;
-fx-background-radius: 10 10 0 0;
-fx-border-radius: 10 10 0 0;
}
.close-button-bottom{
-fx-background-color: transparent;
-fx-background-radius: 0 0 10 10;
-fx-border-radius: 0 0 10 10;
}
.close-button-bottom-grey{
-fx-border-color: transparent;
-fx-background-radius: 0 0 10 10;
-fx-border-radius: 0 0 10 10;
}
.close-button-left-trans{
-fx-border-color: transparent;
-fx-background-color: transparent;
-fx-background-radius: 10 0 0 10;
-fx-border-radius: 10 0 0 10;
}
.close-button-right-trans{
-fx-border-color: transparent;
-fx-background-color: transparent;
-fx-background-radius: 0 10 10 0;
-fx-border-radius: 0 10 10 0;
}
/*******************************************************************************
* *
* TextField *
* *
******************************************************************************/
.text-field {
-fx-border-color: transparent;
-fx-background-color: transparent;
-fx-border-color: -fx-border_col;
-fx-border-radius: 5;
-fx-text-fill: -fx-text;
}
.text-field:selected{
-fx-border-color: -fx-highlight;
}
.text-field:focused{
-fx-border-color: -fx-highlight;
}
/*******************************************************************************
* *
* MenuButton *
* *
******************************************************************************/
.menu-button{
-fx-text-fill: -fx-text;
-fx-background-color: -fx-darkbackground;
-fx-border-color: rgb(255, 255, 255);
-fx-border-radius: 5;
-fx-padding: 3 6 6 6;
}
/*******************************************************************************
* *
* SplitMenuButton *
* *
******************************************************************************/
.split-menu-button{
-fx-text-fill: -fx-text;
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
-fx-border-radius: 5;
}
.split-menu-button:hover{
-fx-border-color: -fx-highlight_border;
}
.split-menu-button .label {
-fx-text-fill: white;
-fx-background-color: -fx-darkbackground;
-fx-border-radius: 5;
}
.split-menu-button .label:hover {
-fx-background-color: -fx-highlight;
}
.split-menu-button .arrow-button {
-fx-text-fill: -fx-text;
-fx-background-color: -fx-darkbackground;
-fx-border-radius: 5;
}
.split-menu-button .arrow-button:hover {
-fx-background-color: -fx-highlight;
}
/*******************************************************************************
* *
* Radio Button *
* *
******************************************************************************/
.radio-button {
/* -fx-text-fill: rgb(255, 255, 255, 0.4);*/
-fx-text-fill: -fx-text;
/* -fx-effect: dropshadow(one-pass-box , rgba(0, 0, 0, 0.6), 0, 0.0 , 0 , 1 );*/
-fx-border-width: 0px;
}
/*******************************************************************************
* *
* Check Box *
* *
******************************************************************************/
.check-box {
/* -fx-text-fill: rgb(255, 255, 255, 0.4);*/
-fx-text-fill: -fx-text;
/* -fx-effect: dropshadow(one-pass-box , rgba(0, 0, 0, 0.6), 0, 0.0 , 0 , 1 );*/
-fx-border-width: 0px;
}
/*******************************************************************************
* *
* ComboBox *
* *
******************************************************************************/
.combo-box-base{
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
-fx-border-radius: 5;
-fx-padding: 3 6 6 6;
}
.choice-box{
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
-fx-border-radius: 5;
-fx-padding: 3 6 6 6;
}
/*******************************************************************************
* *
* MenuItem *
* *
******************************************************************************/
.menu-item .label {
-fx-text-fill: -fx-text;
/*Must be transpernt so that semi transparent colour is not added to smei transparent*/
-fx-background-color: transparent;
}
.menu-item:focused {
-fx-background-color: -fx-highlight;
}
.menu-item:focused .label {
-fx-text-fill: -fx-text;
/*Weird fix-must make transparent for correct colour to show*/
-fx-background-color: rgba(0,204,204,0);
}
.context-menu {
-fx-skin: "com.sun.javafx.scene.control.skin.ContextMenuSkin";
-fx-background-color: -fx-darkbackground;
-fx-background-insets: 0, 1, 2;
-fx-background-radius: 0 6 6 6, 0 5 5 5, 0 4 4 4;
/* -fx-padding: 0.666667em 0.083333em 0.666667em 0.083333em; 8 1 8 1 */
-fx-padding: 0.333333em 0.083333em 0.666667em 0.083333em; /* 4 1 8 1 */
}
/****************************************************************
ScrollPane
****************************************************************/
.scroll-pane {
-fx-background: transparent;
-fx-background-color: transparent;
}
/****************************************************************
ScrollBar
****************************************************************/
.scroll-bar {
-fx-background-color: -fx-darkbackground;
-fx-background-radius: 2em;
}
.scroll-bar:horizontal .track,
.scroll-bar:vertical .track {
-fx-background-color: transparent;
-fx-border-color:transparent;
-fx-background-radius: 2em;
}
.scroll-bar:vertical .track-background,
.scroll-bar:horizontal .track-background {
-fx-background-color: transparent;
-fx-background-insets: 0;
-fx-background-radius: 2em;
}
.scroll-bar:horizontal .thumb {
-fx-background-color: rgb(211,211,211);
-fx-background-insets: 4 0 4 0;
-fx-background-radius: 2em;
}
.scroll-bar:vertical .thumb {
-fx-background-color: rgb(211,211,211);
-fx-background-insets: 0 4 0 4;
-fx-background-radius: 2em;
}
.scroll-bar:horizontal .thumb:hover,
.scroll-bar:vertical .thumb:hover {
-fx-background-color: rgb(231,231,231);
}
.scroll-bar:horizontal .thumb:pressed,
.scroll-bar:vertical .thumb:pressed {
-fx-background-color: rgb(255,255,255);
}
.scroll-bar:vertical .increment-button, .scroll-bar:vertical .decrement-button {
-fx-background-color:transparent;
-fx-background-radius: 2em;
-fx-padding: 5;
}
.scroll-bar:horizontal .increment-button, .scroll-bar:horizontal .decrement-button {
-fx-background-color:transparent;
-fx-background-radius: 2em;
-fx-padding: 5;
}
.scroll-bar:horizontal .increment-arrow {
-fx-shape: "M 0 0 L 4 8 L 8 0 Z";
-fx-background-color: rgb(211,211,211);
-fx-padding: 0.25em;
-fx-rotate: -90;
}
.scroll-bar:vertical .increment-arrow {
-fx-background-color: rgb(211,211,211);
-fx-shape: "M 0 0 L 4 8 L 8 0 Z";
-fx-padding: 0.25em;
-fx-rotate: 0;
}
.scroll-bar:horizontal .decrement-arrow {
-fx-background-color: rgb(211,211,211);
-fx-shape: "M 0 0 L 4 8 L 8 0 Z";
-fx-padding: 0.25em;
-fx-rotate: 90;
}
.scroll-bar:vertical .decrement-arrow {
-fx-background-color: rgb(211,211,211);
-fx-shape: "M 0 0 L 4 8 L 8 0 Z";
-fx-padding: 0.25em;
-fx-rotate: -180;
}
.scroll-bar:vertical:focused,
.scroll-bar:horizontal:focused {
-fx-background-color: transparent,rgb(96,96,96),rgb(96,96,96);
}
/****************************************************************
Spinner
****************************************************************/
.spinner {
-fx-background: -fx-darkbackground;
-fx-background-color: -fx-darkbackground;
-fx-background-radius: 10;
-fx-border-radius: 10;
-fx-border-color: transparent;
}
.spinner .text-field {
-fx-background: -fx-darkbackground;
-fx-background-color: -fx-darkbackground;
-fx-border-radius: 0 0 0 0;
-fx-padding: 7 0 7 0;
-fx-border-color: transparent;
}
.spinner .increment-arrow-button {
-fx-text-fill: white;
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
-fx-border-radius: 5 5 0 0;
-fx-padding: 7 0 7 0;
}
.spinner .increment-arrow {
-fx-background-color: white;
}
.spinner .increment-arrow-button:hover {
-fx-background-color: -fx-highlight;
-fx-border-color: -fx-highlight_border;
-fx-background-radius: 6 6 0 0;
-fx-border-radius: 6 6 0 0;
}
.spinner .decrement-arrow-button {
-fx-text-fill: white;
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
-fx-border-radius: 0 0 6 6
}
.spinner .decrement-arrow {
-fx-background-color: white;
}
.spinner .decrement-arrow-button:hover {
-fx-background-color: -fx-highlight;
-fx-border-color: -fx-highlight_border;
-fx-background-radius: 0 0 6 6;
-fx-border-radius: 0 0 6 6;
}

View File

@ -2,6 +2,7 @@ package pamViewFX.fxNodes.pamDialogFX;
import java.util.Optional;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import pamViewFX.fxStyles.PamStylesManagerFX;
@ -25,11 +26,13 @@ public class PamSettingsDialogFX<T> extends PamDialogFX<T> {
this.settingsPane=settingsPane;
this.setTitle(settingsPane.getName());
this.setContent(settingsPane.getContentNode());
// if (PamController.getInstance().getGuiManagerFX()!=null){
// this.getDialogPane().getStylesheets().add(PamController.getInstance().getGuiManagerFX().getPamSettingsCSS());
// }
PamStylesManagerFX stylesManager = PamStylesManagerFX.getPamStylesManagerFX();
this.getDialogPane().getStylesheets().add(stylesManager.getCurStyle().getSlidingDialogCSS());
this.getDialogPane().getStylesheets().add(stylesManager.getCurStyle().getDialogCSS());
this.setOnShown((value)->{
settingsPane.paneInitialized();
});

View File

@ -1,5 +1,6 @@
package pamViewFX.fxNodes.picker;
import PamView.PamSymbol;
import PamView.PamSymbolType;
import javafx.geometry.Point2D;
import javafx.scene.canvas.Canvas;
@ -127,7 +128,7 @@ public class SymbolPicker extends ComboBox<PamSymbolFX> {
/**
* Set the symbol with a symbol type.
* @param symbol
* @param symbol - the symbol type.
*/
public void setValue(PamSymbolType symbol) {
for (int i=0; i<getItems().size(); i++){
@ -137,5 +138,16 @@ public class SymbolPicker extends ComboBox<PamSymbolFX> {
}
}
/**
* Set the symbol with a symbol type. Note, replicates setValue for convenience.
* @param symbol - the symbol type.
*/
public void setSymbol(PamSymbolType symbol) {
setValue(symbol);
}
}

View File

@ -3,13 +3,16 @@ package pamViewFX.fxNodes.utilityPanes;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import net.synedra.validatorfx.Validator;
import pamViewFX.PamGuiManagerFX;
import pamViewFX.fxNodes.PamGridPane;
import pamViewFX.fxNodes.PamHBox;
@ -50,6 +53,15 @@ public class GroupedSourcePaneFX extends SourcePaneFX {
*/
private PamGridPane sourcePane;
/**
* Holds channels and group settings.
*/
private PamVBox channelPanel;
/**
* Validator for channels
*/
private Validator channelValidator;
public GroupedSourcePaneFX(Class sourceType, boolean hasChannels, boolean includeSubClasses, boolean autoGrouping) {
@ -64,6 +76,8 @@ public class GroupedSourcePaneFX extends SourcePaneFX {
@Override
protected void createPanel() {
channelValidator = new Validator();
sourcePane=new PamGridPane();
sourcePane.setVgap(5);
sourcePane.setHgap(5);
@ -90,7 +104,7 @@ public class GroupedSourcePaneFX extends SourcePaneFX {
sourcePane.setMaxWidth(Double.MAX_VALUE);
//create pane to hold channels.
PamVBox channelPanel=new PamVBox();
channelPanel=new PamVBox();
channelPanel.setSpacing(5);
Label channelLabel = new Label("Channels");
@ -124,15 +138,39 @@ public class GroupedSourcePaneFX extends SourcePaneFX {
selectAll.setOnAction((action)->{
if (selectAll.isSelected()) selectAllChannels();
else selectNoChannels();
channelValidator.validate(); //makes sure any error signs are removed
});
//create check to show at least some check boxes need to be selected.
channelValidator.createCheck()
.dependsOn(("select all"), selectAll.selectedProperty())
.withMethod(c -> {
if (!isAChannelSelected() ) {
c.error("At least one channel needs to be selected for the module to work");
}
})
.decorates(selectAll)
.immediate();
;
//create a list of channels and combo boxes for groups.
if (isHasChannels()){
for (int i = 0; i < PamConstants.MAX_CHANNELS; i++){
channelBoxes[i] = new CheckBox("Channel " + i);
channelValidator.createCheck()
.dependsOn(("channel " + i), channelBoxes[i].selectedProperty())
.withMethod(c -> {
if (!isAChannelSelected() ) {
c.error("At least one channel needs to be selected for the module to work");
}
})
.decorates(channelBoxes[i])
.immediate();
;
//channelPanel.getChildren().add(channelBoxes[i]);
final int n=i;
channelBoxes[i].setOnAction((action)->{
selectionChanged(n);
channelValidator.validate(); //makes sure any error signs are removed.
});
groupList[i]=new ComboBox<Integer>();
//System.out.println("SourcePanel.java creatPanel"+i);
@ -149,82 +187,43 @@ public class GroupedSourcePaneFX extends SourcePaneFX {
PamHBox channelGroupPane=new PamHBox();
channelGroupPane.setSpacing(15);
channelGroupPane.getChildren().addAll(channelPanel, autoGroupPane);
channelGroupPane.setAlignment(Pos.TOP_LEFT);
sourcePane.add(channelGroupPane,0,3);
//create source comboBox.
this.setCenter(sourcePane);
// //old swing layout panels
// panel = new JPanel();
// JPanel sourcePanel = new JPanel();
// sourcePanel.setLayout(new BorderLayout());
// // add stuff to the panel.
// if (borderTitle != null) {
// sourcePanel.setBorder(new TitledBorder(borderTitle));
// }
// panel.setLayout(new BorderLayout());
//// panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
// sourcePanel.add(BorderLayout.CENTER, sourceList = new JComboBox());
// panel.add(BorderLayout.NORTH, sourcePanel);
// sourceList.addActionListener(this);
// if (hasChannels) {
// JPanel channelGroupPanel = new JPanel();
// channelGroupPanel.setLayout(new BorderLayout());
// channelGroupPanel.setBorder(new TitledBorder("Channel list and grouping"));
// JPanel channelPanel = new JPanel();
// JPanel autoGroupPanel = new JPanel();
// autoGroupPanel.setLayout(new BoxLayout(autoGroupPanel, BoxLayout.Y_AXIS));
// autoGroupPanel.add(new JLabel("Auto Grouping"));
// autoGroupPanel.add(allSingles = new JRadioButton("No grouping"));
// autoGroupPanel.add(allTogether = new JRadioButton("One group"));
// autoGroupPanel.add(userGrouped = new JRadioButton("User groups"));
// allSingles.addActionListener(new GroupAction(GROUP_SINGLES));
// allTogether.addActionListener(new GroupAction(GROUP_ALL));
// userGrouped.addActionListener(new GroupAction(GROUP_USER));
// ButtonGroup bg = new ButtonGroup();
// bg.add(allSingles);
// bg.add(allTogether);
// bg.add(userGrouped);
//// channelPanel.setLayout(new BoxLayout(channelPanel, BoxLayout.Y_AXIS));
// GridBagLayout layout;
//// channelPanel.setBorder(new TitledBorder("Channel list and grouping"));
// channelPanel.setLayout(layout = new GridBagLayout());
// GridBagConstraints c = new GridBagConstraints();
// c.gridwidth = 2;
// c.anchor = GridBagConstraints.WEST;
// c.gridx = c.gridy = 0;
// addComponent(channelPanel, autoGroupPanel, c);
//// addComponent(channelPanel, new JLabel("Channel list ..."), c);
// c.gridwidth = 1;
// c.insets = new Insets(0,5,0,5);
// c.gridy++;
// c.gridx = 0;
// addComponent(channelPanel, new JLabel("Channel"), c);
// c.gridx++;
// addComponent(channelPanel, new JLabel("Group"), c);
// groupList = new JComboBox[PamConstants.MAX_CHANNELS];
// channelBoxes = new JCheckBox[PamConstants.MAX_CHANNELS];
// for (int i = 0; i < PamConstants.MAX_CHANNELS; i++){
// channelBoxes[i] = new JCheckBox("Channel " + i);
// groupList[i] = new JComboBox();
// c.gridy ++;
// c.gridx = 0;
// addComponent(channelPanel, channelBoxes[i], c);
// c.gridx ++;
// addComponent(channelPanel, groupList[i], c);
//// channelPanel.add(channelBoxes[i]);
// channelBoxes[i].setVisible(false);
// groupList[i].setVisible(false);
// channelBoxes[i].addActionListener(new SelectionListener(i));
// }
// channelGroupPanel.add(BorderLayout.WEST, autoGroupPanel);
// channelGroupPanel.add(BorderLayout.CENTER, channelPanel);
// panel.add(BorderLayout.CENTER, channelGroupPanel);
// }
}
/**
* Get the validator for the channel. This can identify errors
* in
* @return
*/
public Validator getChannelValidator() {
return channelValidator;
}
/**
* Check if
* @return
*/
private boolean isAChannelSelected() {
int channels = 0;
PamDataBlock sb = getSource();
if (sb != null) {
// channels = sb.getChannelMap();
channels = sb.getSequenceMap();
}
int n=0;
//remove all channels from vertical box pane.
for (int i = 0; i < Math.min(PamConstants.MAX_CHANNELS, channelBoxes.length); i++) {
if ((channels & 1<<i) != 0 && this.channelBoxes[i].isSelected()) n++;
}
if (n==0) return false;
else return true;
}
@Override
protected void showChannels() {
@ -459,4 +458,12 @@ public class GroupedSourcePaneFX extends SourcePaneFX {
return channelListPane;
}
/**
* The pane that holds the channels and the group settings.
* @return the channel pane.
*/
public Pane getChannelPane() {
return channelPanel;
}
}

View File

@ -270,6 +270,7 @@ public class SourcePaneFX extends PamBorderPane {
}
/**
* Tell the pane the source has changed.
*/

View File

@ -39,7 +39,7 @@ public class SettingsFileDialogFX {
singleInstance = new SettingsFileDialogFX();
singleInstance.settingsDialog=new PamSettingsDialogFX(singleInstance.settingsFilePane);
// singleInstance.settingsDialog.getDialogPane().getStylesheets().add(singleInstance.getClass().getResource("/Resources/css/pamSettingsCSS.css").toExternalForm());
singleInstance.settingsDialog.getDialogPane().getStylesheets().add(PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getSlidingDialogCSS());
singleInstance.settingsDialog.getDialogPane().getStylesheets().add(PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getDialogCSS());
}
singleInstance.settingsFilePane.setParams(settingsFileData);

View File

@ -72,6 +72,9 @@ public class SettingsFilePane extends SettingsPane<SettingsFileData> {
browseButton.setOnAction((action)->{
browseFile(false);
});
browseButton.prefHeightProperty().bind(fileBox.heightProperty());
PamButton browseSaveButton = new PamButton();
// browseSaveButton.setGraphic(PamGlyphDude.createPamGlyph(MaterialDesignIcon.PLUS, Color.WHITE, PamGuiManagerFX.iconSize));
browseSaveButton.setGraphic(PamGlyphDude.createPamIcon("mdi2p-plus", Color.WHITE, PamGuiManagerFX.iconSize));
@ -82,6 +85,9 @@ public class SettingsFilePane extends SettingsPane<SettingsFileData> {
folderSelectPane.getChildren().addAll(fileBox, browseSaveButton, browseButton);
vBox.getChildren().add(folderSelectPane);
browseSaveButton.prefHeightProperty().bind(fileBox.heightProperty());
fileBox.prefHeightProperty().bind(browseButton.heightProperty());
// //option to show on start up.

View File

@ -10,6 +10,7 @@ import binaryFileStorage.BinaryStore;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamGridPane;
import pamViewFX.fxNodes.pamDialogFX.PamDialogFX;
import pamViewFX.fxStyles.PamStylesManagerFX;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.scene.Node;
@ -56,6 +57,8 @@ public class StorageOptionsPane extends SettingsPane<StorageParameters>{
PamGridPane gridPane=new PamGridPane();
Label l = new Label(" Binary Store ");
l.setTextAlignment(TextAlignment.CENTER);

View File

@ -0,0 +1,68 @@
package pamViewFX.fxStyles;
/*
* PAMGUARD - Passive Acoustic Monitoring GUARDianship.
* To assist in the Detection Classification and Localisation
* of marine mammals (cetaceans).
*
* Copyright (C) 2006
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* Class defining the default CSS Style sheets to use for JavaFX displays. This class can be extended and one or more methods overridden to
* specify new CSS styles. Style sheets can be specified for 3 different categories: sliding dialogs, regular dialogs, and all other components
* (incl. displays, etc). In addition, each category can have a style sheet to use for daytime mode and one to use for nighttime mode. The
* relative URI paths to the individual style sheets are specified as private fields, and accessed through public methods. The day/night switch
* is based on the name of the current PamColors colour scheme being used.
*
* @author Jamie Macaulay
*
*/
public class PamAtlantaStyle extends PamDefaultStyle {
/**
* Relative location of the CSS style sheet to be used for the Pamguard GUI (but not dialogs)
*/
//private String guiCSS = "/Resources/css/pamCSS.css";
//private String guiCSS = new NordDark().getUserAgentStylesheet();
protected String primerGuiCSS = "/Resources/css/primer-light.css";
/**
* Relative location of the CSS style sheet to be used for the Pamguard standard dialogs
*/
//private String dialogCSS = "/Resources/css/pamSettingsCSS.css";
//private String dialogCSS = new PrimerDark().getUserAgentStylesheet();
protected String primerDialogCSS = "/Resources/css/primer-dark.css";
/**
* Relative location of the CSS style sheet to be used for the Pamguard sliding dialogs
*/
//private String slidingDialogCSS = "/Resources/css/pamCSS.css";
//private String slidingDialogCSS = new PrimerDark().getUserAgentStylesheet();
protected String primerSlidingDialogCSS = "/Resources/css/primer-pamguard.css";
public PamAtlantaStyle() {
super.guiCSS = primerGuiCSS;
super.dialogCSS = primerDialogCSS;
super.slidingDialogCSS = primerSlidingDialogCSS;
}
}

View File

@ -42,35 +42,35 @@ public class PamDefaultStyle {
/**
* Relative location of the CSS style sheet to be used for the Pamguard GUI (but not dialogs)
*/
private String guiCSS = "/Resources/css/pamCSS.css";
protected String guiCSS = "/Resources/css/pamCSS.css";
/**
* Relative location of the CSS style sheet to be used for the Pamguard GUI when in night mode. If there
* is not a style sheet specific to night mode, set it to null or point back to the guiCSS field.
*/
private String guiCSSNightMode = guiCSS;
protected String guiCSSNightMode = guiCSS;
/**
* Relative location of the CSS style sheet to be used for the Pamguard standard dialogs
*/
private String dialogCSS = "/Resources/css/pamDefaultDialogCSS.css";
protected String dialogCSS = "/Resources/css/pamDefaultDialogCSS.css";
/**
* Relative location of the CSS style sheet to be used for the Pamguard std dialogs when in night mode. If there
* is not a style sheet specific to night mode, set it to null or point back to the dialogCSS field.
*/
private String dialogCSSNightMode = dialogCSS;
protected String dialogCSSNightMode = dialogCSS;
/**
* Relative location of the CSS style sheet to be used for the Pamguard sliding dialogs
*/
private String slidingDialogCSS = "/Resources/css/pamSettingsCSS.css";
protected String slidingDialogCSS = "/Resources/css/pamSettingsCSS.css";
/**
* Relative location of the CSS style sheet to be used for the Pamguard sliding dialogs when in night mode. If there
* is not a style sheet specific to night mode, set it to null or point back to the slidingDialogCSS field.
*/
private String slidingDialogCSSNightMode = slidingDialogCSS;
protected String slidingDialogCSSNightMode = slidingDialogCSS;
/**
* <p>Return the CSS Style sheet to be used for the Pamguard GUI (displays and such) but not the dialogs.</p>

View File

@ -50,7 +50,7 @@ import warnings.PamWarning;
public class RawDLSettingsPane extends SettingsPane<RawDLParams>{
public static double MAX_WIDTH = 250;
public static double MAX_WIDTH = 270;
/**
* The source for the FFT data source.
@ -181,7 +181,6 @@ public class RawDLSettingsPane extends SettingsPane<RawDLParams>{
vBox.getChildren().add(label);
windowLength = new PamSpinner<Integer>(0, Integer.MAX_VALUE, 10, 10000);
windowLength.setPrefWidth(100);
windowLength.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
windowLength.setEditable(true);
windowLength.valueProperty().addListener((obsVal, oldVal, newVal)->{
@ -189,7 +188,6 @@ public class RawDLSettingsPane extends SettingsPane<RawDLParams>{
});
hopLength = new PamSpinner<Integer>(0, Integer.MAX_VALUE, 10, 10000);
hopLength.setPrefWidth(100);
hopLength.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
hopLength.setEditable(true);
hopLength.valueProperty().addListener((obsVal, oldVal, newVal)->{
@ -197,7 +195,6 @@ public class RawDLSettingsPane extends SettingsPane<RawDLParams>{
});
reMergeSeg = new PamSpinner<Integer>(0, Integer.MAX_VALUE, 1, 1);
reMergeSeg.setPrefWidth(100);
reMergeSeg.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
reMergeSeg.setEditable(true);

View File

@ -1,6 +1,12 @@
package rawDeepLearningClassifier.layoutFX.exampleSounds;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import simulatedAcquisition.sounds.SimSignal;
/**
* The example sound factory
@ -9,6 +15,8 @@ import java.net.URL;
*/
public class ExampleSoundFactory {
/**
* An example sound type.
* @author Jamie macaulay
@ -16,21 +24,32 @@ public class ExampleSoundFactory {
*/
public enum ExampleSoundType {
BAT_CALL("Bat Call (Myotis daubentonii)"),
PORPOISE_CLICK("Harbour Porpoise (Phocoena phocoena)", ExampleSoundCategory.ODONTOCETES_CLICKS),
SPERM_WHALE("Sperm Whale (Physeter macrocephalus)", ExampleSoundCategory.ODONTOCETES_CLICKS),
DOLPHIN("Dolphin (Delphinid)", ExampleSoundCategory.ODONTOCETES_CLICKS),
BEAKED_WHALE("Beaked Whale (Ziphiidae)", ExampleSoundCategory.ODONTOCETES_CLICKS),
RIGHT_WHALE("Southern Right Whale (Eubalaena australis)"),
BAT_CALL("Bat Call (Myotis daubentonii)", ExampleSoundCategory.BAT),
MINKE_WHALE("Minke Whale (Balaenoptera spp.)"),
RIGHT_WHALE("Southern Right Whale (Eubalaena australis)", ExampleSoundCategory.MYSTICETES),
MINKE_WHALE("Minke Whale (Balaenoptera spp.)", ExampleSoundCategory.MYSTICETES),
HUMPBACK_WHALE("Humpback whale (Megaptera novaeangliae) ");
HUMPBACK_WHALE("Humpback whale (Megaptera novaeangliae) ", ExampleSoundCategory.MYSTICETES);
private final String text;
private final ExampleSoundCategory soundCategory;
/**
* @param text
*/
ExampleSoundType(final String text) {
ExampleSoundType(final String text, final ExampleSoundCategory soundCategory) {
this.text = text;
this.soundCategory = soundCategory;
}
/* (non-Javadoc)
@ -40,8 +59,173 @@ public class ExampleSoundFactory {
public String toString() {
return text;
}
/**
* Get category of the example sound.
* @return the example sound category.
*/
public ExampleSoundCategory getCategory() {
return soundCategory;
}
}
public enum ExampleSoundCategory {MYSTICETES, ODONTOCETES_CLICKS, OCONTOCETES_TONAL, BAT}
/**
* Get all the example sounds for a particular category.
* @param - the category of sund to extract.
* @return the example sounds for a category.
*/
private List<ExampleSoundType> getAnExampleSoundTypes(ExampleSoundCategory category) {
List<ExampleSoundType> exampleSounds = Arrays.asList(ExampleSoundType.values());
List<ExampleSoundType> resultSet =
exampleSounds.stream()
.filter(c -> c.getCategory().equals(category))
.collect(Collectors.toList());
return resultSet;
}
/**
* Get all the example sounds for a set of categories.
* @param - the categories to use.
* @return the example sounds for a category.
*/
public ArrayList<ExampleSoundType> getExampleSoundTypes(ExampleSoundCategory... cateogry) {
ArrayList<ExampleSoundType> resultSet = new ArrayList<ExampleSoundType>();
for (int i=0; i<cateogry.length; i++) {
resultSet.addAll(getAnExampleSoundTypes(cateogry[i]));
}
return resultSet;
}
/**
*Beaked whale click template, sR is 192000;
*/
public static final double[] beakedWhale1 = {2.47E-04,4.17E-04,-2.08E-04,-4.96E-04,2.10E-04,1.77E-04,-1.94E-04,4.12E-04,
-3.52E-04,-4.06E-04,5.34E-04,1.78E-04,-1.57E-04,-3.78E-04,6.04E-04,2.92E-04,-1.11E-03,-9.88E-05,4.69E-04,4.78E-04,-2.56E-04,
-6.52E-04,9.52E-04,7.76E-04,-1.24E-03,-2.34E-03,-7.72E-04,5.15E-03,9.90E-03,-7.51E-03,-2.34E-02,1.01E-02,2.53E-02,-1.19E-02,-1.14E-02,
8.45E-03,4.52E-04,-7.41E-03,-3.62E-03,1.55E-02,7.40E-03,-1.44E-02,-2.38E-04,7.15E-04,-1.20E-02,3.95E-04,1.57E-02,4.98E-03,1.92E-03,
1.54E-02,-2.55E-02,-5.13E-02,2.06E-02,4.93E-02,4.04E-03,1.07E-02,-4.28E-03,-6.29E-02,-2.66E-02,3.46E-02,3.53E-02,3.77E-02,2.10E-02,
-5.72E-02,-8.11E-02,-2.50E-03,4.14E-02,7.01E-02,7.57E-02,-4.29E-02,-1.31E-01,-7.97E-02,4.48E-02,1.41E-01,1.17E-01,-3.82E-02,-1.92E-01,
-1.16E-01,6.49E-02,1.70E-01,1.65E-01,-1.03E-01,-2.66E-01,-4.51E-02,1.66E-01,2.08E-01,9.35E-03,-2.98E-01,-1.26E-01,2.83E-01,1.67E-01,
-1.97E-01,-2.05E-01,9.55E-02,2.64E-01,-3.56E-02,-2.88E-01,2.30E-02,2.49E-01,-2.65E-02,-1.77E-01,1.71E-02,1.22E-01,6.03E-03,-1.18E-01,
1.24E-02,1.12E-01,-6.87E-02,-3.49E-02,6.68E-02,-3.83E-02,-1.76E-02,4.04E-02,4.81E-03,-4.35E-02,3.24E-03,5.49E-02,-3.68E-02,-1.93E-02,
3.83E-02,-2.45E-02,-6.69E-03,3.95E-02,-1.97E-02,-3.61E-02,4.18E-02,3.72E-03,-3.75E-02,3.54E-02,-4.81E-03,-3.30E-02,3.52E-02,2.50E-03,
-3.08E-02,1.80E-02,1.40E-02,-2.37E-02,4.51E-03,1.71E-02,-1.81E-02,-6.25E-04,1.83E-02,-1.33E-02,-9.61E-03,1.96E-02,-2.14E-03,
-1.97E-02,1.43E-02,9.88E-03,-1.85E-02,5.62E-03,1.13E-02,-1.41E-02,-6.57E-04,1.33E-02,-6.73E-03,-7.21E-03,1.07E-02,-2.59E-03,
-1.03E-02,1.08E-02,5.15E-03,-1.25E-02,7.48E-04,9.56E-03,-5.28E-03,-5.46E-03,7.89E-03,1.54E-04,-8.15E-03,5.09E-03,6.07E-03,-7.92E-03,
-7.59E-04,8.78E-03,-5.57E-03,-5.39E-03,8.47E-03,-1.48E-03,-7.02E-03,5.20E-03,3.33E-03,-6.12E-03,8.16E-04,6.54E-03,-4.25E-03,-3.56E-03,
4.57E-03,-6.18E-04,-1.87E-03,1.52E-03,3.46E-04};
/**
* Dolphin click template. sR is 500000;
*/
public static final double[] porp1 = {-3.05E-05,-0.002563477,-0.004974365,0.011444092,-0.009521484,-0.025115967,0.043365479,0.006896973,-0.090332031,0.045959473,
0.112335205,-0.129669189,-0.099395752,0.208465576,0.036865234,-0.25994873,0.040771484,0.273834229,-0.121124268,-0.264709473,0.18447876,0.235626221,-0.241851807,
-0.194458008,0.281036377,0.129699707,-0.306427002,-0.048278809,0.293182373,-0.043273926,-0.243774414,0.110229492,0.162536621,-0.144958496,-0.078491211,0.136444092,
0.004547119,-0.105926514,0.037628174,0.058898926,-0.05682373,-0.018371582,0.047973633,-0.018737793,-0.024383545,0.03302002,-0.014404297,-0.030517578,0.045227051,
0.002532959,-0.063751221,0.027191162,0.057067871,-0.054901123,-0.042449951,0.065246582,0.016448975,-0.06741333,0.002319336,0.055664063,-0.023345947,-0.040496826,
0.030548096,0.015625,-0.033569336,0.002441406,0.022857666,-0.019042969,-0.013702393,0.020965576,0.001831055,-0.023101807,0.001068115,0.01739502,-0.005401611,
-0.017944336,0.004394531,0.013427734,-0.008880615,-0.013122559,0.007781982,0.006561279,-0.010650635,-0.004150391,0.005310059};
/**
* Dolphin click template. sR is 192000;
*/
public static final double[] dolphin1 = {3.56E-05,1.13E-03,-1.28E-03,4.39E-05,1.17E-04,4.11E-04,-3.05E-04,1.57E-04,-3.45E-04,5.21E-04,-5.18E-04,
1.93E-03,-8.44E-04,-1.62E-04,-8.80E-04,2.74E-04,-4.06E-04,1.32E-03,-7.23E-04,5.70E-04,-6.91E-04,6.78E-04,-7.04E-04,-1.36E-03,-4.10E-04,
1.41E-03,-1.11E-03,1.36E-03,-9.02E-04,-2.69E-04,-1.49E-04,2.05E-04,-1.53E-04,6.97E-05,-7.78E-04,9.78E-04,-1.04E-03,-9.00E-05,-8.66E-04,
6.78E-05,-1.06E-03,1.39E-03,-6.03E-04,3.49E-04,2.80E-04,9.42E-04,-3.65E-04,-5.98E-04,-1.91E-04,4.00E-04,-1.22E-03,4.52E-04,-1.35E-03,8.43E-04,
-1.20E-03,5.83E-04,-3.36E-04,1.26E-03,-2.39E-04,1.63E-04,-1.31E-03,1.15E-03,9.60E-04,1.58E-03,-5.09E-04,1.16E-03,-1.15E-03,-2.38E-04,-3.77E-04,
1.37E-04,-1.57E-03,1.30E-03,-9.01E-04,1.00E-03,-9.13E-06,8.95E-04,-9.26E-04,3.68E-04,-6.05E-05,5.16E-04,-2.56E-04,2.45E-03,-1.46E-03,1.80E-03,
-5.76E-04,4.27E-03,4.60E-03,1.62E-02,2.77E-02,4.65E-02,-2.96E-02,-1.70E-01,-3.27E-01,1.98E-01,7.30E-01,-1.69E-01,-4.94E-01,3.59E-02,1.08E-01,
2.70E-02,-9.51E-03,-2.52E-02,-1.19E-02,5.12E-03,3.54E-03,9.35E-03,6.57E-03,5.81E-03,-1.82E-03,-3.81E-03,-1.73E-02,-3.26E-03,1.66E-02,1.47E-02,
-1.78E-04,-1.35E-02,-5.18E-03,5.96E-03,1.20E-03,-2.03E-03,8.27E-04,3.08E-03,7.34E-03,2.49E-03,-8.53E-03,-3.58E-03,-4.46E-03,2.39E-03,6.70E-03,
2.08E-03,-1.54E-03,3.96E-05,-3.75E-04,4.47E-05,9.08E-04,1.13E-03,-4.51E-04,-1.16E-03,-2.38E-03,1.33E-03,4.09E-03,-4.09E-05,-2.57E-03,-7.47E-05,
-4.94E-04,-1.12E-04,-2.10E-04,3.48E-04,-1.33E-04,-8.04E-04,-1.28E-04,2.31E-04,1.63E-03,4.06E-03,-1.90E-03,-4.81E-03,-3.43E-03,2.05E-03,2.64E-03,
1.05E-03,-1.25E-03,-1.52E-03,-2.15E-04,5.58E-04,1.09E-03,-2.92E-04,-7.16E-05,-1.62E-04,-7.08E-04,1.37E-03,-3.63E-04,-1.01E-04,-9.10E-04,4.76E-04,
-4.89E-04,6.00E-04,-1.97E-03,-3.72E-04,-1.23E-03,-2.13E-03,1.80E-03,1.72E-03,-4.45E-04,8.07E-04,2.73E-03,1.87E-03,-3.51E-04,-1.79E-03,
-4.25E-05,-3.60E-04,-6.36E-03,-3.80E-03};
/**
* Sperm whale click that contains P0 , P1 and P2 pulses. sR is 192000/4
*/
public static final double[] sperm1 = {6.25E-05,-2.17E-05,4.27E-05,-0.00020994,-0.000214738,4.15E-05,-4.20E-06,-1.19E-05,1.43E-05,-6.63E-06,-0.000131916,7.46E-05,7.74E-05,
-3.48E-05,0.000112665,7.23E-05,0.000124127,-0.000327633,-0.000504408,-0.0001821,-9.08E-06,-0.000303635,-0.00091038,-0.000737628,-0.002809006,-0.002485561,0.002436103,
0.001387111,-0.000240529,0.008338125,0.01556416,0.003837149,-0.012601288,-0.010037818,0.001317383,0.006350685,0.003097904,-0.003146625,-0.005176637,-0.005103367,
-0.003033016,0.000264741,0.000979974,0.001417843,0.001295476,0.000270959,-0.000941692,-0.002497482,-0.001093983,0.001588331,0.001606697,0.000428882,0.000342588,
0.000576856,0.000175455,0.000351797,0.000535963,6.16E-05,-2.81E-05,3.01E-05,-4.62E-05,6.29E-05,-0.00032481,-0.000627716,0.000541881,0.000930361,6.94E-05,-8.11E-05,
-0.001084492,-0.001999887,-0.000853651,-0.000455461,-0.0009841,-0.000148444,0.000505996,0.000659125,0.002106154,0.00305439,0.002859567,0.002226094,-0.001580242,
-0.005047821,-0.003593811,-0.002505516,-0.00239728,0.000993556,0.004712824,0.005116607,0.002759289,-0.000433693,-0.00259594,-0.002059373,6.38E-05,0.00080239,0.001226022,
0.000524362,-5.97E-05,0.000218345,0.002725451,0.013643442,0.007104888,-0.013153579,-0.000327077,0.008434641,-0.034580464,-0.058165279,0.001699742,0.050940528,0.016095566,
-0.019505718,-0.014421101,0.00069818,0.012322224,0.015961877,0.019905987,0.012646343,-0.003135543,-0.003774804,-0.002494694,-0.004462543,-2.78E-05,0.006201286,0.007524738,
-0.000122701,-0.00686273,-0.003151422,0.000472041,-0.004336464,-0.006828523,-0.0036367,-0.004451807,-0.00476565,-0.00059454,0.001060291,0.000210872,0.000292835,0.001312147,
0.00354525,0.003836739,-0.001563894,-0.003728106,0.000589295,0.002063008,0.005110769,0.008073922,0.002351888,0.000991397,0.004482293,0.001852083,-0.001210519,-0.003916204,
-0.009643673,-0.011895388,-0.011094342,-0.009496773,0.007035453,0.021768597,0.012407682,0.007770304,0.009816115,-0.004929878,-0.02191959,-0.021845953,-0.009616377,0.003728446,
0.011398892,0.007160923,-0.001221613,-0.003364027,-0.001979512,-0.00161046,-0.000138627,0.00464312,0.004116845,0.001597662,0.003842689,0.002166315,-0.001378553,-0.005946158,
-0.011386535,-0.004845226,0.002418087,-0.003915996,-0.001246813,0.028316573,0.039767874,-0.002601435,-0.030996041,-0.012193441,0.000524819,-0.003479641,-0.001961131,0.005014191,
0.000109726,-0.008264739,-0.003328171,-0.003266307,-0.005688887,0.002147438,0.005314515,0.003113408,0.000906803,-0.00362076,-0.004367909,0.001707293,0.004516978,0.002670098,
0.005179915,0.005209394,0.000157009,-0.001113109,0.000351461,-0.00070744,-0.002641287,-0.000378381,0.000650114,-0.000699954,0.001493645,0.002380219,0.001847398,0.000957028,
-0.00020906,-0.001138818,-0.005258351,-0.004390589,-0.000750034,0.001350919,0.005041997,0.004159317,0.00380484,0.006116095,0.004054061,-0.007240427,-0.015931238,-0.008497872,
-0.004869947,-0.005248341,0.005820257,0.017324379,0.015179912,0.001501706,-0.004758621,-0.004807403,-0.004766533,0.000532342,0.001876597,0.002421249,0.002974527,-0.003363805,
-0.006394844,-0.004090489,-0.000551194,0.000815621,0.002722833,0.006326427,0.002422239,1.71E-05,0.001718135,0.000155882,-9.98E-06,0.000374249,0.000685689,-0.00060601,
-0.002945803,-0.001182812,0.000705219,0.000131511,-0.001627181,-0.004276435,-0.004121385,-0.001013222,-0.000580473,-0.001749975,-0.000810329,0.001049795,0.002380673,
0.00092144,-0.001721435,-0.001959407,0.001039882,0.003527076,0.001077526,0.001321712,0.003990982,0.00159095,-6.99E-05,0.000197319,0.000611932,0.000414778,-0.000977586,
0.000546997,-0.00015996,-0.003209788,-0.002958488,-0.001050216,0.000691699,-0.002462978,-0.00411392,-0.001070453,-0.002638013};
// /**
// * Generate a click waveform with some added noise.
// * @param type - the type of click e.g. ClickTriggerGraph.PORPOISE_CLICK.
// * @param noise. 0 to 1. 1 means max noise amplitude will be same as maximum click amplitude.
// * @return click and noise waveform.
// */
// private double[] generateClickWaveform(ExampleSoundType type, double noise){
// SimSignal clickSound;
// int sR;
// double length;
// double freq;
// switch (type){
// //TODO - add more types of clicks.
// case PORPOISE_CLICK:
// clickSound=new ClickSound("Porpoise", freq=140000, freq2=140000, length=0.00015, WINDOWTYPE.HANN);
// sR=500000;
// break;
// case SPERM_WHALE:
// clickSound=(new ClickSound("Beaked Whale", 30000, 60000, length = 0.3e-3, WINDOWTYPE.HANN));
// sR=192000;
// break;
// default:
// clickSound=new ClickSound("Porpoise", freq=140000, freq2=140000, length=0.00015, WINDOWTYPE.HANN);
// sR=500000;
// break;
// }
//
// //now need to work out how many noise samples to add. Use the length of the click
// int nNoiseSamples=(int) (2*length*sR);
// double[] waveform=new double[3*nNoiseSamples];
// int n=0;
// for (int i=0; i<3*nNoiseSamples; i++){
// double noiseSample=noise*(Math.random()-0.5);
// double[] signal=clickSound.getSignal(0,sR,0);
// if (i>nNoiseSamples && n <signal.length){
// waveform[i]=signal[n]+noiseSample;
// n=n+1;
// }
// else waveform[i]=noiseSample;
// }
//
// return waveform;
// }
/**
* Get the example sound type.
* @param exampleSoundType
@ -54,7 +238,7 @@ public class ExampleSoundFactory {
switch (exampleSoundType) {
case BAT_CALL:
path = getClass().getResource("/Resources/exampleSounds/DUB_20200623_000152_885.wav");
exampleSound = new SimpleExampleSound(path);
exampleSound = new SimpleExampleSound(path, 2500, 5000);
break;
case RIGHT_WHALE:
//file = new File("src/rawDeepLearningClassifier/layoutFX/exampleSounds/southern_right_whale_clip2.wav");
@ -71,11 +255,44 @@ public class ExampleSoundFactory {
path = getClass().getResource("/Resources/exampleSounds/Humpback_whale.wav");
exampleSound = new SimpleExampleSound(path);
break;
case PORPOISE_CLICK:
exampleSound = new SimpleExampleSound(porp1, 500000);
break;
case SPERM_WHALE:
exampleSound = new SimpleExampleSound(sperm1, 48000);
break;
case BEAKED_WHALE:
exampleSound = new SimpleExampleSound(beakedWhale1, 192000);
break;
case DOLPHIN:
exampleSound = new SimpleExampleSound(dolphin1, 192000);
break;
default:
break;
}
return exampleSound;
}
/**
* Get all the example sounds for a particular category.
* @param - the category of sund to extract.
* @return the example sounds for a category.
*/
public ExampleSoundType[] getExampleSoundTypes(ExampleSoundCategory category) {
List<ExampleSoundType> exampleSounds = Arrays.asList(ExampleSoundType.values());
List<ExampleSoundType> resultSet =
exampleSounds.stream()
.filter(c -> c.getCategory().equals(category))
.collect(Collectors.toList());
return (ExampleSoundType[]) resultSet.toArray();
}
}

View File

@ -39,6 +39,21 @@ public class SimpleExampleSound implements ExampleSound{
e.printStackTrace();
}
}
public SimpleExampleSound(URL path, int start, int end) {
try {
data = DLUtils.loadWavFile(path);
} catch (IOException | UnsupportedAudioFileException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
data = data.trim(start, end);
}
public SimpleExampleSound(double[] wave, float sampleRate) {
this.data = new AudioData(wave, sampleRate);
}
@Override
public double[] getWave() {
@ -50,4 +65,5 @@ public class SimpleExampleSound implements ExampleSound{
return data.getSampleRate();
}
}

Some files were not shown because too many files have changed in this diff Show More