Merge branch 'main' of https://github.com/macster110/PAMGuard
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_DISABLED_BUILDER" value="net.sourceforge.metrics.builder"/>
|
||||
<mapAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||
</launchConfiguration>
|
1
.gitignore
vendored
@ -111,3 +111,4 @@ settings.xml
|
||||
.classpath
|
||||
.classpath
|
||||
.settings/org.eclipse.jdt.core.prefs
|
||||
.classpath
|
||||
|
7
.project
@ -11,8 +11,13 @@
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>net.sourceforge.metrics.builder</name>
|
||||
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>LaunchConfigHandle</key>
|
||||
<value><project>/.externalToolBuilders/net.sourceforge.metrics.builder.launch</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
|
176
README.html
@ -388,7 +388,7 @@ PamguardBeta_ViewerMode.exe):</p>
|
||||
<h1><a name="_LATEST_VERSION_2.02.03"></a><a name="_VERSION_2.02.07_January"></a><a
|
||||
name="_Latest_Version_2.02.10"></a><em><span style='font-size:12.0pt;
|
||||
font-family:"Cambria",serif;font-style:normal'><a href="#_Version_2.02.11_April">Latest
|
||||
Version 2.02.11 April 2024</a></span></em></h1>
|
||||
Version 2.02.12 June 2024</a></span></em></h1>
|
||||
|
||||
<h1><em><span style='font-size:12.0pt;font-family:"Cambria",serif;font-style:
|
||||
normal'><a href="#_Version_2.02.10_January">Version 2.02.10 January 2024</a></span></em></h1>
|
||||
@ -465,22 +465,36 @@ Version 2.00.10 June 2017</a></span></h1>
|
||||
name="_Latest_Version_2.02.06"></a><a name="_Latest_Version_2.02.07"></a><a
|
||||
name="_Latest_Version_2.02.08"></a><a name="_Version_2.02.09_June"></a><a
|
||||
name="_Version_2.02.10_January"></a><a name="_Version_2.02.11_April"></a>Version
|
||||
2.02.11 April 2024</h1>
|
||||
2.02.12 June 2024</h1>
|
||||
|
||||
<p class=MsoNormal> </p>
|
||||
|
||||
<h2>New Features</h2>
|
||||
|
||||
<p class=MsoNormal>Deep Learning Classifier. Major upgrade to support for Deep
|
||||
Learning models in PAMGuard. See online help for details.</p>
|
||||
|
||||
<p class=MsoNormal>Click detector: Remembers locations of displays and doesn’t
|
||||
continually reset them. </p>
|
||||
|
||||
<p class=MsoNormal>Help for Matched Click Classifier</p>
|
||||
<p class=MsoNormal>Help for Matched Click Classifier.</p>
|
||||
|
||||
<p class=MsoNormal>Project information dialog. This allows capture of essential
|
||||
project information to store with your data. See menu item Settings/Project
|
||||
information.</p>
|
||||
|
||||
<h2>Tethys Database</h2>
|
||||
|
||||
<p class=MsoNormal>Many users will be aware that we’re integrating an interface
|
||||
to the <a href="https://tethys.sdsu.edu/">Tethys Database</a> into PAMGuard.
|
||||
Some basic features are available for testing. If interested, please contact
|
||||
the PAMGuard support team. </p>
|
||||
|
||||
<h2>Bug Fixes</h2>
|
||||
|
||||
<p class=MsoNormal>Linking clicks to offline clicks table. We had a database
|
||||
that had become corrupted so added code to relink offline clicks to their corresponding
|
||||
clicks from binary data. </p>
|
||||
that had become corrupted so added code to relink offline clicks to their
|
||||
corresponding clicks from binary data. </p>
|
||||
|
||||
<p class=MsoNormal>Drawing non-acoustic data: Data that were not associated
|
||||
with any hydrophones, e.g. visual sightings in Logger forms were not drawing on
|
||||
@ -497,14 +511,35 @@ as PAMGuard stops / restarts. </p>
|
||||
function fixed and now inserts correct times of start and ends of events into
|
||||
database. </p>
|
||||
|
||||
<p class=MsoNormal>Clip generator. Changes to ensure PAMGuard keeps audio data
|
||||
long enough to make clips. In some circumstances data were being discarded too
|
||||
early so clips could not be created. </p>
|
||||
|
||||
<p class=MsoNormal>Acquisition “Skip initial seconds” feature, designed to
|
||||
remove high sample levels e.g. from calibration tones at start of a soundtrap
|
||||
recording was not working with the click detector. This is fixed but replacing
|
||||
all data with 0’s and still sending data. Note that this may lead to
|
||||
artificially low noise measures at the start of a file. </p>
|
||||
|
||||
<p class=MsoNormal>Data reprocessing options. Updated to ensure that the option
|
||||
"Start normally. Note risk of overwriting!" is always available. Also
|
||||
improved code naming binary files to attempt to push them to exact times,
|
||||
rather than a couple of seconds after the hour. </p>
|
||||
|
||||
<p class=MsoNormal>improved code naming binary files to attempt to push them to
|
||||
exact times, rather than a couple of seconds after the hour. </p>
|
||||
|
||||
<p class=MsoNormal>Updated icons to improve display on high definition screens.
|
||||
</p>
|
||||
|
||||
<h1>Version 2.02.10 January 2024</h1>
|
||||
|
||||
<h2><span lang=EN-US>New Features</span></h2>
|
||||
|
||||
<p class=MsoNormal><b><span lang=EN-US>Importing modules</span></b><span
|
||||
lang=EN-US> from other configurations: New options from file menu allowing import
|
||||
of specific modules, or module settings from other configurations. E.g. if you
|
||||
had three similar configurations and had set one of them up with a new
|
||||
lang=EN-US> from other configurations: New options from file menu allowing
|
||||
import of specific modules, or module settings from other configurations. E.g.
|
||||
if you had three similar configurations and had set one of them up with a new
|
||||
detector, or got the click classifier settings set up just right in one of
|
||||
those configurations, you can import the additional modules or the click
|
||||
detector settings easily into the other configurations. </span></p>
|
||||
@ -532,9 +567,9 @@ correctly saving updated bearings to the database. Now fixed. </span></p>
|
||||
|
||||
<p class=MsoNormal><b><span lang=EN-US>ROCCA Classifier fixes</span></b></p>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US>Allow Rocca to run without classifiers: Fixed
|
||||
bug that threw an error if no classifier files were specified in Rocca
|
||||
Params dialog</span></p>
|
||||
<p class=MsoNormal><span lang=EN-US>Allow Rocca to run without classifiers:
|
||||
Fixed bug that threw an error if no classifier files were specified in
|
||||
Rocca Params dialog</span></p>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US>Fix memory issue with
|
||||
RoccaContourDataBlocks not being released for garbage collection</span></p>
|
||||
@ -1128,8 +1163,8 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> &nb
|
||||
|
||||
<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'> </span>Bug
|
||||
456. Under certain conditions, the Ishmael detection plugin that is
|
||||
shown at the bottom of the spectrogram can disappear about 500 msec behind the
|
||||
456. Under certain conditions, the Ishmael detection plugin that is shown
|
||||
at the bottom of the spectrogram can disappear about 500 msec behind the
|
||||
current time. </p>
|
||||
|
||||
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>5. </span><span
|
||||
@ -1218,10 +1253,10 @@ lang=EN-US> </span>Add functionality for bluetooth headsets. </p>
|
||||
|
||||
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>2. </span><span
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> </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>
|
||||
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'> </span><span
|
||||
@ -1232,8 +1267,8 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> &nb
|
||||
Add 15 minute data load option to viewer mode. </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'> </span>
|
||||
Add 3D map for target motion module. </p>
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> </span><span
|
||||
lang=EN-US> </span>Add 3D map for target motion module. </p>
|
||||
|
||||
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>6. </span><span
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> </span><span
|
||||
@ -1259,12 +1294,12 @@ lang=EN-US> </span>Added channel display to noise one band measurement display.
|
||||
</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'> </span>
|
||||
Added Azigram module, to work in conjunction with Difar. </p>
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> </span><span
|
||||
lang=EN-US> </span>Added Azigram module, to work in conjunction with Difar. </p>
|
||||
|
||||
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>12. </span><span
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> </span>
|
||||
Added beaked whale to sim sounds </p>
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> </span><span
|
||||
lang=EN-US> </span>Added beaked whale to sim sounds </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'> </span><span
|
||||
@ -1301,8 +1336,9 @@ PSFX files when PAMGuard exits.</p>
|
||||
<p class=MsoNormal><b><span lang=EN-US>Bug Fixes</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'> </span>
|
||||
Bug 433. Custom storage options were being lost when Pamguard restarted.</p>
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> </span><span
|
||||
lang=EN-US> </span>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'> </span><span
|
||||
@ -1310,8 +1346,8 @@ 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'> </span>
|
||||
Bug 435. Logger forms subtabs not working.</p>
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> </span><span
|
||||
lang=EN-US> </span>Bug 435. Logger forms subtabs not working.</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'> </span><span
|
||||
@ -1392,8 +1428,8 @@ classify clicks. </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'> </span><span
|
||||
lang=EN-US> </span>Added option in Sound Acquisition settings dialog to
|
||||
override filename time stamp and use PC local time instead. </p>
|
||||
lang=EN-US> </span>Added option in Sound Acquisition settings dialog to override
|
||||
filename time stamp and use PC local time instead. </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'> </span><span
|
||||
@ -1415,9 +1451,9 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> &nb
|
||||
Implemented a simple UDP output for PAMGuard alarms. </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'> </span>
|
||||
Changes to Spectrogram Mark Observers, to allow individual channels to be
|
||||
selected instead of the spectrogram panel as a whole. </p>
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> </span><span
|
||||
lang=EN-US> </span>Changes to Spectrogram Mark Observers, to allow individual
|
||||
channels to be selected instead of the spectrogram panel as a whole. </p>
|
||||
|
||||
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>8. </span><span
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> </span><span
|
||||
@ -1452,9 +1488,9 @@ 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'> </span>
|
||||
Java 12 is better at handling Windows scaling issues on high-DPI displays. Beyond
|
||||
that, users should not notice much of a difference between this version and
|
||||
previous beta releases.</p>
|
||||
Java 12 is better at handling Windows scaling issues on high-DPI displays.
|
||||
Beyond that, users should not notice much of a difference between this version
|
||||
and previous beta releases.</p>
|
||||
|
||||
<!-- ************************************************************************************************************************** --><!-- ************************************************************************************************************************** -->
|
||||
|
||||
@ -1688,8 +1724,8 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> &nb
|
||||
<p class=MsoNormal><b><span lang=EN-US>Upgrades</span></b></p>
|
||||
|
||||
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>1. </span><span
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> </span>
|
||||
Improvement to Range Rings in Map display.</p>
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> </span><span
|
||||
lang=EN-US> </span>Improvement to Range Rings in Map display.</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'> </span>
|
||||
@ -2158,7 +2194,7 @@ showing. </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'>
|
||||
</span><span lang=EN-US>Bug 323. Difar module.</span> Fixed a couple of small
|
||||
</span><span lang=EN-US>Bug 323. Difar module. </span>Fixed a couple of small
|
||||
bugs in the DIFAR system which caused it to not work if old configuratins were
|
||||
used. </p>
|
||||
|
||||
@ -2304,8 +2340,8 @@ the new version. However please note the following:</span></p>
|
||||
|
||||
<p class=MsoListParagraph style='margin-left:54.0pt;text-indent:-36.0pt'><span
|
||||
lang=EN-US>1.</span><span lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>
|
||||
</span><span lang=EN-US>New classes will be added to the configuration files,
|
||||
so they will no longer work with older PAMGuard versions.</span></p>
|
||||
</span><span lang=EN-US>New classes will be added to the configuration files, so
|
||||
they will no longer work with older PAMGuard versions.</span></p>
|
||||
|
||||
<p class=MsoListParagraph style='margin-left:54.0pt;text-indent:-36.0pt'><span
|
||||
lang=EN-US>2.</span><span lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>
|
||||
@ -2428,8 +2464,8 @@ milliseconds. However, getDuration actually returns the number of samples.
|
||||
|
||||
<p class=MsoNormal><b><span lang=EN-US>Plug-Ins</span></b></p>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US>A major change in this version of PAMGuard
|
||||
is how plug-ins are managed. PAMGuard now has the ability to dynamically load
|
||||
<p class=MsoNormal><span lang=EN-US>A major change in this version of PAMGuard is
|
||||
how plug-ins are managed. PAMGuard now has the ability to dynamically load
|
||||
plug-in modules (saved as jar files) at runtime. This will greatly simplify the
|
||||
process of testing and distributing newly developed modules, since only a small
|
||||
jar file will be required rather than a new bespoke PAMGuard installation.</span></p>
|
||||
@ -2438,9 +2474,9 @@ jar file will be required rather than a new bespoke PAMGuard installation.</span
|
||||
unchanged, in most cases simply requiring the addition of an interface class.
|
||||
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>. Plug-in modules can be downloaded from the
|
||||
PAMGuard website here, but developers are encouraged to host and maintain their
|
||||
own modules.</span></p>
|
||||
target="_blank">here</a>. Plug-in modules can be downloaded from the PAMGuard
|
||||
website here, but developers are encouraged to host and maintain their 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,
|
||||
@ -2615,9 +2651,9 @@ main click detector display. </span></p>
|
||||
|
||||
<p class=MsoNormal><b><span lang=EN-US>Target Motion Analysis</span></b></p>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US>A major piece of work has been undertaken to
|
||||
improve the Target Motion tracking with PAMGuard. Details are available in the
|
||||
online help. Users of the Click Detector will notice the following changes:</span></p>
|
||||
<p class=MsoNormal><span lang=EN-US>A major piece of work has been undertaken
|
||||
to improve the Target Motion tracking with PAMGuard. Details are available in
|
||||
the online help. Users of the Click Detector will notice the following changes:</span></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'>
|
||||
@ -3055,8 +3091,8 @@ allocation to allow more memory for the database interface. Hopefully Fixed. </p
|
||||
|
||||
<p class=MsoListParagraph style='margin-left:38.25pt;text-indent:-20.25pt'><span
|
||||
lang=EN-AU>9.</span><span lang=EN-AU style='font-size:7.0pt;font-family:"Times New Roman",serif'>
|
||||
</span>Bug 239. <span lang=EN-AU>Fixed bug in the DIFAR module that was incorrectly
|
||||
preventing cross-fixes for some calls.</span></p>
|
||||
</span>Bug 239. <span lang=EN-AU>Fixed bug in the DIFAR module that was
|
||||
incorrectly preventing cross-fixes for some calls.</span></p>
|
||||
|
||||
<p class=MsoNormal>Details of these bugs can be found at <a
|
||||
href="https://sourceforge.net/p/pamguard/bugs">https://sourceforge.net/p/pamguard/bugs</a></p>
|
||||
@ -3515,9 +3551,9 @@ to these menus to provide additional information to users. </p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:36.0pt'><i>Radar Display</i></p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:36.0pt'>Functionality has been added to the
|
||||
radar display so that bearings can be shown relative to either the vessel or to
|
||||
true North. </p>
|
||||
<p class=MsoNormal style='margin-left:36.0pt'>Functionality has been added to
|
||||
the radar display so that bearings can be shown relative to either the vessel
|
||||
or to true North. </p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:36.0pt'>Better control of data in viewer
|
||||
mode, making is easy to scroll through and view data for short time periods. </p>
|
||||
@ -3872,11 +3908,11 @@ Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif
|
||||
|
||||
<p class=MsoNormal>2. Improved offline viewer functionality. </p>
|
||||
|
||||
<p class=MsoNormal>The offline viewer is much improved with better data
|
||||
scrolling and the ability to view data either stored in the database or the
|
||||
binary storage system. Work has stated on functions which read and use data
|
||||
stored in audio files. This is currently limited to re-calculating and
|
||||
displaying displaying spectrogram data during viewer mode operation. </p>
|
||||
<p class=MsoNormal>The offline viewer is much improved with better data scrolling
|
||||
and the ability to view data either stored in the database or the binary
|
||||
storage system. Work has stated on functions which read and use data stored in
|
||||
audio files. This is currently limited to re-calculating and displaying
|
||||
displaying spectrogram data during viewer mode operation. </p>
|
||||
|
||||
<p class=MsoNormal>3. Heading sensor readout</p>
|
||||
|
||||
@ -3977,8 +4013,8 @@ channels 0 and 1. Similarly if you switched sound cards, you may have to
|
||||
reconfigure every detector and several of the displays to handle the changes in
|
||||
channel numbering. </p>
|
||||
|
||||
<p class=MsoNormal>I have spent a considerable amount of time trying to work
|
||||
out a better system for handling channel numbering in PAMGUARD and have decided
|
||||
<p class=MsoNormal>I have spent a considerable amount of time trying to work out
|
||||
a better system for handling channel numbering in PAMGUARD and have decided
|
||||
that the only practical thing to do is to force all software channel numbering
|
||||
back to a zero indexed system. i.e. even if you read out hardware channels
|
||||
3,4,5 and 6, within PAMGUARD, everywhere apart from the Sound acquisition
|
||||
@ -4302,11 +4338,11 @@ Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif
|
||||
|
||||
<p class=MsoListParagraph style='text-indent:-18.0pt'><span style='font-family:
|
||||
Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>
|
||||
</span>New menu functionality by right clicking on any of the tabs of the main tab
|
||||
control will allow the user to copy the tab contents to the system clipboard
|
||||
from where it can be copied into other programs (e.g. Word, Powerpoint,
|
||||
etc.).Some modules, such as the map, have this implemented in other menus
|
||||
(right click) and also allow printing. </p>
|
||||
</span>New menu functionality by right clicking on any of the tabs of the main
|
||||
tab control will allow the user to copy the tab contents to the system
|
||||
clipboard from where it can be copied into other programs (e.g. Word,
|
||||
Powerpoint, etc.).Some modules, such as the map, have this implemented in other
|
||||
menus (right click) and also allow printing. </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'>
|
||||
@ -4374,8 +4410,8 @@ online help. </p>
|
||||
|
||||
<p class=MsoNormal><b>PAMGUARD Mixed Mode operation</b></p>
|
||||
|
||||
<p class=MsoNormal>Analyses data from wav or AIF file and synchronises it with GPS
|
||||
data reloaded from a database so that detected sounds may be correctly
|
||||
<p class=MsoNormal>Analyses data from wav or AIF file and synchronises it with
|
||||
GPS data reloaded from a database so that detected sounds may be correctly
|
||||
localised. Multiple display frames - enables PAMGUARD GUI to be split into
|
||||
multiple display windows, displayed on multiple monitors if desired. Enables
|
||||
the operator to simultaneously view the map and the click detector for example,
|
||||
@ -4566,9 +4602,9 @@ a serial port </p>
|
||||
|
||||
<p class=MsoNormal>New Likelihood detector. </p>
|
||||
|
||||
<p class=MsoNormal>The likelihood detector module is an implementation of a
|
||||
likelihood ratio test with flexible algorithms and configuration to estimate
|
||||
likelihood. It is </p>
|
||||
<p class=MsoNormal>The likelihood detector module is an implementation of a likelihood
|
||||
ratio test with flexible algorithms and configuration to estimate likelihood.
|
||||
It is </p>
|
||||
|
||||
<p class=MsoNormal>suitable for detecting both short duration Odontocete clicks
|
||||
(Sperm, Beaked, etc.) as well as moderate duration Mysticete calls (Humpback,
|
||||
|
@ -4,7 +4,7 @@
|
||||
<groupId>org.pamguard</groupId>
|
||||
<artifactId>Pamguard</artifactId>
|
||||
<name>Pamguard</name>
|
||||
<version>2.02.11d</version>
|
||||
<version>2.02.12</version>
|
||||
<description>Pamguard using Maven to control dependencies</description>
|
||||
<url>www.pamguard.org</url>
|
||||
<organization>
|
||||
|
26
readme.md
@ -6,19 +6,21 @@ PAMGuard is a bioacoustics analysis program designed for use in real time resear
|
||||
## Why do we need PAMGuard?
|
||||
PAMGuard fufills two main requirements within marine bioacoustics
|
||||
|
||||
1) **Real time operation**: Almost all PAMGuard features and modules work in real time - this allows scientists and industry to detect, classify and loclaise animals in real time on a standard consumer laptop, enabling mitigations and research survey without expensive bespoke software solutions and the transparncy of open source software.
|
||||
1) **Real time operation**: Almost all PAMGuard features and modules work in real time - this allows scientists and industry to detect, classify and localise the position of animals in real time on a standard consumer laptop, enabling mitigation and research surveys without expensive bespoke software solutions and the transparncy of open source software.
|
||||
|
||||
2) **Processing and visuslisation of large datasets**: Off-the-shelf autonomous PAM devices, large scale surveys involving drifters, towed arrays and bottom mounted devices and real time continuous monitoring system all generate huge volumes of data whcih requires automated analysis approaches. PAMGuard allows the processing of very large passive acoustic datasets using automated algorothms and provides visualisation tools for a manual analyst to check the results.
|
||||
2) **Processing and visuslisation of large datasets**: Off-the-shelf autonomous PAM devices, large scale surveys involving drifters, towed arrays, glidders, bottom mounted devices and real time continuous monitoring system all generate huge volumes of data whcih requires automated analysis approaches. PAMGuard allows the processing of very large passive acoustic datasets using automated algorothms and crucially provides comprehensive visualisation tools for a manual analyst to check the results.
|
||||
|
||||
## Installation
|
||||
PAMGuard is available on Windows and can be downloaded from the [PAMGuard website](www.pamguard.org). Note that we are considering MacOS installers but they are not available at this time.
|
||||
PAMGuard is available on Windows and can be downloaded from the [PAMGuard website](www.pamguard.org). Note that we are considering MacOS and Linux installers but they are not available at this time.
|
||||
|
||||
## Tutorial
|
||||
## Quick start tutorial
|
||||
PAMGuard is a modular program with two modes; real-time and viewer. Typically a user will start with real-time model, either in the field collecting data or post processing sound files from a recorder. Once data are processed, users move on to viewer mode where data can be explored and further processed.
|
||||
|
||||
Upon opening PAMGuard for the first time you are greeted with a blank screen. You must add a series of modules to create the desired acosutic workflow. For example if processing sound files then first add the Sound Acquisition module **_File->Add Modules->Sound Processing->Sound Acquisition_**. Then add the desired detection algorothms e.g. **_File->Add Modules->Detector->Click Detectors_**. Some modules (such as the click detector) have their own displays, others are added to more generalised displays. For example, the whislte and moan detector module shows detections on a spectrgram display. First add a new tab using **_File->Add Modules->Displays->User Display**. Click on the user display tab and then from the top menu select **_User display-> New Spectrgram_**. Right click on the added spectrgram and select whistle and moan contours to show whistle detections overlaid on the raw spectrgram.
|
||||
Upon opening PAMGuard for the first time you are greeted with a blank screen. You must add a series of modules to create the desired acosutic workflow - this is referred to as PAMGuard *data model*. For example if processing sound files then first add the Sound Acquisition module **_File->Add Modules->Sound Processing->Sound Acquisition_**. Then add the desired detection algorothms e.g. **_File->Add Modules->Detector->Click Detectors_**. Some modules (such as the click detector) have their own bespoke displays, others are added to more generalised displays. For example, the whistle and moan detector module shows detections on a spectrgram display, time base display, map etc.. First add a new tab using **_File->Add Modules->Displays->User Display**. Click on the user display tab and then from the top menu select **_User display-> New Spectrogram_**. Right click on the added spectrgram and select whistle and moan contours to show whistle detections overlaid on the raw spectrgram.
|
||||
|
||||
Make sure to add the database and binary file storage modules **_File->Add Modules->Utilities->..._**) to save data then press the run button (red button) and data will process. PAMGuard can handle huge datasets so runing might take hours or even days. Progress is shown on the bottom of the screen.
|
||||
Make sure to add the database and binary file storage modules **_File->Add Modules->Utilities->..._**) to save data then press the run button (red button) and data will process. PAMGuard can handle huge datasets so running might take hours or even days. Progress is shown on the bottom of the screen.
|
||||
|
||||
Once the data has run, open PAMGuard viewer mode. Select the database you used to process the data along and thebianry file storage path and PAMGuard will open, showing an overview of the dataset in a new _Data map_ tab. Right click anywhere on the data map and select "Center data here" - PAMGuard will load the data for the selected period which can be explored using whichever displays have been added to the data model.
|
||||
|
||||
## Features
|
||||
### Hardware integration
|
||||
@ -49,20 +51,22 @@ Almsot all detection data can be visualised on a map. PAMGaurd also supports plo
|
||||
An important aspect of PAMGuard is the ability for users to explore porcessed data. PAMGuard allows users to visualise data at multiple different times scales, from inspecting individual waveforms microseconds long to datagrams showing detector output or soundscape metrics over days, weeks or even years.
|
||||
|
||||
### Advanced manual annotation
|
||||
The displays within PAMGuard support a variety of manual annottion tools.
|
||||
The displays within PAMGuard support a variety of manual annotation tools. Users can add data to annotations in multiple ways, from simple text annotations to complex forms created by users.
|
||||
|
||||
### Deep learning integration
|
||||
PAMGuard allows users to run their own deep learning models using the deep learning module. AI can therfore be integrated into PAMGuard workflows, allowing for much more efficient analysis of data.
|
||||
PAMGuard allows users to run their own deep learning models using the deep learning module. AI can therfore be integrated into PAMGuard workflows, allowing for more efficient analysis of data.
|
||||
|
||||
### Metadata standard and Tethys compatibility
|
||||
PAMGuard Integrates with Tethys
|
||||
PAMGuard Integrates with Tethys database. Users can export processed PAMGuard data to a Tethys database seamlessly; this ifeature is great for large scale projects or organisatiosn with long term datasets.
|
||||
|
||||
## Feature roadmap
|
||||
There's lots of features we would like to add to PAMGuard. If you want to add a feature you can either code it up yourself in Java and submit a pull request or get in touch with us to discuss how to it might be integrated. Some smaller features might be in our roadmap anyway but larger features usually require funding. Some features we are thinking about (but do not necassarily have time for yet) are;
|
||||
|
||||
* Support for decidecade noise bands (base 10 filter bank) in noise band monitor to meet Euopean standards
|
||||
* Capabaility to export data directly from PAMGaurd e.g. as MAT files.
|
||||
* Automated test suite to make releases more stable. Note that unit and integration tests are also being slowly incorporated.
|
||||
* Capabaility to export data directly from PAMGaurd e.g. as MAT files (in progress).
|
||||
* Automated test suite to make releases more stable. Note that unit and integration tests are also being slowly incorporated.
|
||||
* Support for ARM based computers (in progress).
|
||||
* A graphical user interface and Python library for training PAMGuard compatible deep learning models.
|
||||
|
||||
## Development
|
||||
This is the main code repository for the PAMGuard software and was created on 7 January 2022 from a [sourceforge SVN repository](https://sourceforge.net/p/pamguard/svn/HEAD/tree/) revision r6278.
|
||||
|
@ -15,6 +15,7 @@ import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
@ -594,7 +595,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
|
||||
System.out.println("The current file was null");
|
||||
return false;
|
||||
}
|
||||
// System.out.printf("*********************************** Opening file %s\n", currentFile.getName());
|
||||
System.out.printf("*********************************** Opening file %s\n", currentFile.getName());
|
||||
|
||||
try {
|
||||
|
||||
@ -602,7 +603,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
|
||||
audioStream.close();
|
||||
}
|
||||
|
||||
System.out.println("FileInputSystem - prepareInputFile");
|
||||
// System.out.println("FileInputSystem - prepareInputFile");
|
||||
|
||||
audioStream = PamAudioFileManager.getInstance().getAudioInputStream(currentFile);
|
||||
|
||||
@ -638,6 +639,9 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
|
||||
fileInputParameters.bitDepth = audioFormat.getSampleSizeInBits();
|
||||
|
||||
loadByteConverter(audioFormat);
|
||||
|
||||
// System.out.println("FileInputSystem - prepareInputFile done");
|
||||
|
||||
|
||||
} catch (UnsupportedAudioFileException ex) {
|
||||
ex.printStackTrace();
|
||||
@ -1017,9 +1021,11 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
|
||||
newDataUnit = new RawDataUnit(ms, 1 << ichan, totalSamples, newSamples);
|
||||
newDataUnit.setRawData(doubleData[ichan]);
|
||||
|
||||
if (1000*(readFileSamples/sampleRate)>=fileInputParameters.skipStartFileTime) {
|
||||
newDataUnits.addNewData(newDataUnit);
|
||||
if (1000*(readFileSamples/sampleRate)<fileInputParameters.skipStartFileTime) {
|
||||
// zero the data. Skipping it causes all the timing to screw up
|
||||
Arrays.fill(doubleData[ichan], 0.);
|
||||
}
|
||||
newDataUnits.addNewData(newDataUnit);
|
||||
|
||||
// GetOutputDataBlock().addPamData(pamDataUnit);
|
||||
}
|
||||
|
@ -933,6 +933,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
||||
|
||||
@Override
|
||||
public InputStoreInfo getStoreInfo(boolean detail) {
|
||||
System.out.println("FolderInputSystem: Get store info start:");
|
||||
if (allFiles == null || allFiles.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
@ -962,6 +963,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
||||
storeInfo.setLastFileEnd(lastFileEnd); // just incase changed
|
||||
storeInfo.setFileStartTimes(allFileStarts);
|
||||
}
|
||||
System.out.println("FolderInputSystem: Get store info complete:");
|
||||
return storeInfo;
|
||||
}
|
||||
|
||||
|
@ -31,12 +31,12 @@ public class PamguardVersionInfo {
|
||||
* Version number, major version.minorversion.sub-release.
|
||||
* Note: can't go higher than sub-release 'f'
|
||||
*/
|
||||
static public final String version = "2.02.11d";
|
||||
static public final String version = "2.02.12";
|
||||
|
||||
/**
|
||||
* Release date
|
||||
*/
|
||||
static public final String date = "30 May 2024";
|
||||
static public final String date = "24 June 2024";
|
||||
|
||||
// /**
|
||||
// * Release type - Beta or Core
|
||||
|
@ -4,6 +4,8 @@ import java.awt.BorderLayout;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.ButtonGroup;
|
||||
@ -64,15 +66,28 @@ public class ReprocessChoiceDialog extends PamDialog {
|
||||
List<ReprocessStoreChoice> userChoices = choiceSummary.getChoices();
|
||||
choiceButtons = new JRadioButton[userChoices.size()];
|
||||
ButtonGroup bg = new ButtonGroup();
|
||||
SelAction selAction = new SelAction();
|
||||
for (int i = 0; i < userChoices.size(); i++) {
|
||||
ReprocessStoreChoice aChoice = userChoices.get(i);
|
||||
choiceButtons[i] = new JRadioButton(aChoice.toString());
|
||||
choiceButtons[i].setToolTipText(aChoice.getToolTip());
|
||||
bg.add(choiceButtons[i]);
|
||||
choiceButtons[i].addActionListener(selAction);
|
||||
choicePanel.add(choiceButtons[i], c);
|
||||
c.gridy++;
|
||||
}
|
||||
setDialogComponent(mainPanel);
|
||||
getCancelButton().setVisible(false);
|
||||
getOkButton().setEnabled(false);
|
||||
}
|
||||
|
||||
private class SelAction implements ActionListener {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
getOkButton().setEnabled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static ReprocessStoreChoice showDialog(Window parentFrame, StoreChoiceSummary choices) {
|
||||
|
@ -62,7 +62,7 @@ public class ReprocessManager {
|
||||
*/
|
||||
boolean setupOK = setupInputStream(choiceSummary, choice);
|
||||
|
||||
if (choice == ReprocessStoreChoice.DONTSSTART) {
|
||||
if (choice == null || choice == ReprocessStoreChoice.DONTSSTART) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -172,6 +172,8 @@ public class ReprocessManager {
|
||||
choiceSummary.addChoice(ReprocessStoreChoice.STARTNORMAL);
|
||||
return choiceSummary;
|
||||
}
|
||||
|
||||
choiceSummary.addChoice(ReprocessStoreChoice.STARTNORMAL);
|
||||
|
||||
ArrayList<PamControlledUnit> outputStores = PamController.getInstance().findControlledUnits(DataOutputStore.class, true);
|
||||
boolean partStores = false;
|
||||
|
@ -65,6 +65,9 @@ public class StoreChoiceSummary {
|
||||
* @param choice
|
||||
*/
|
||||
public void addChoice(ReprocessStoreChoice choice) {
|
||||
if (choices.contains(choice)) {
|
||||
return;
|
||||
}
|
||||
choices.add(choice);
|
||||
}
|
||||
|
||||
|
@ -472,7 +472,7 @@ final public class PamModel implements PamSettings {
|
||||
mi.setModulesMenuGroup(utilitiesGroup);
|
||||
mi.setMaxNumber(1);
|
||||
//mi.addGUICompatabilityFlag(PamGUIManager.FX); //has FX enabled GUI.
|
||||
// mi.setHidden(SMRUEnable.isEnable() == false);
|
||||
mi.setHidden(SMRUEnable.isEnable() == false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -25,6 +25,7 @@ import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
@ -32,6 +33,7 @@ import java.util.TimeZone;
|
||||
|
||||
import PamController.PamController;
|
||||
import PamUtils.time.CalendarControl;
|
||||
import binaryFileStorage.BinaryStore;
|
||||
|
||||
|
||||
/**
|
||||
@ -85,7 +87,7 @@ public class PamCalendar {
|
||||
* viewPositions which is the number of milliseconds from the sessionsStartTime.
|
||||
*/
|
||||
private static long viewPosition;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If files are being analysed, return the time based on the file
|
||||
@ -880,14 +882,18 @@ public class PamCalendar {
|
||||
*/
|
||||
public static void setSessionStartTime(long sessionStartTime) {
|
||||
PamCalendar.sessionStartTime = sessionStartTime;
|
||||
PamController.getInstance().updateMasterClock(getTimeInMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param soundFileTimeMillis The start time of a sound file
|
||||
* Relative time within a sound file. This is always just added to sessionStartTime
|
||||
* to give an absolute time.
|
||||
* @param soundFileTimeMillis The relative time of a sound file.
|
||||
*/
|
||||
public static void setSoundFileTimeInMillis(long soundFileTimeMillis) {
|
||||
PamCalendar.soundFileTimeInMillis = soundFileTimeMillis;
|
||||
PamController.getInstance().updateMasterClock(getTimeInMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,6 +10,8 @@ import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import PamController.PamController;
|
||||
|
||||
public class GenericSwingDialog extends PamDialog {
|
||||
|
||||
private boolean allOk;
|
||||
@ -45,6 +47,9 @@ public class GenericSwingDialog extends PamDialog {
|
||||
* @return
|
||||
*/
|
||||
public static boolean showDialog(Window parentFrame, String title, Point screenPoint, PamDialogPanel ...dialogPanels) {
|
||||
if (parentFrame == null) {
|
||||
parentFrame = PamController.getMainFrame();
|
||||
}
|
||||
GenericSwingDialog swingDialog = new GenericSwingDialog(parentFrame, title, dialogPanels);
|
||||
swingDialog.setParams();
|
||||
swingDialog.pack();
|
||||
|
@ -5,6 +5,7 @@ import javax.swing.JComponent;
|
||||
/**
|
||||
* General class for dialog panels which will be incorporated into one or
|
||||
* more actual dialogs.
|
||||
* Can be quickly opened with GenericSwingDialog
|
||||
* @author Doug Gillespie
|
||||
*
|
||||
*/
|
||||
|
@ -150,7 +150,8 @@ abstract public class SymbolModifier {
|
||||
if (dialogPanel == null) {
|
||||
return null;
|
||||
}
|
||||
JMenuItem menuItem = new JMenuItem("Options ...");
|
||||
JMenuItem menuItem = new JMenuItem("More options ...");
|
||||
menuItem.setToolTipText("More symbol options");
|
||||
menuItem.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
|
@ -8,12 +8,13 @@ import java.util.Enumeration;
|
||||
import javax.swing.tree.TreeNode;
|
||||
|
||||
import PamUtils.PamUtils;
|
||||
import PamView.dialog.PamDialogPanel;
|
||||
import PamView.symbol.modifier.SymbolModifier;
|
||||
|
||||
public class ModifierTreeNode implements TreeNode {
|
||||
private SymbolModifier modifier;
|
||||
private SymbolTreeRoot rootNode;
|
||||
private ArrayList<ChoiceTreeNode> choiceNodes;
|
||||
private ArrayList<TreeNode> choiceNodes;
|
||||
|
||||
public ModifierTreeNode(SymbolTreeRoot rootNode, SymbolModifier modifier) {
|
||||
super();
|
||||
@ -22,17 +23,25 @@ public class ModifierTreeNode implements TreeNode {
|
||||
int modBits = modifier.getModifyableBits();
|
||||
int nMod = Integer.bitCount(modBits);
|
||||
choiceNodes = new ArrayList<>();
|
||||
|
||||
int leafIndex = 0;
|
||||
|
||||
for (int i = 0; i < nMod; i++) {
|
||||
choiceNodes.add(new ChoiceTreeNode(this, 1<<PamUtils.getNthChannel(i, modBits), i));
|
||||
choiceNodes.add(new ChoiceTreeNode(this, 1<<PamUtils.getNthChannel(i, modBits), leafIndex++));
|
||||
}
|
||||
|
||||
|
||||
|
||||
PamDialogPanel optionsPanel = modifier.getDialogPanel();
|
||||
if (optionsPanel != null) {
|
||||
choiceNodes.add(new OptionsTreeNode(this, modifier, optionsPanel, leafIndex++));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeNode getChildAt(int childIndex) {
|
||||
return choiceNodes.get(childIndex);
|
||||
// return
|
||||
// return
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -73,16 +82,22 @@ public class ModifierTreeNode implements TreeNode {
|
||||
}
|
||||
|
||||
public void setModBitmap(int modBitMap) {
|
||||
for (ChoiceTreeNode cN : choiceNodes) {
|
||||
cN.checkBox.setSelected((cN.selectionBit & modBitMap) != 0);
|
||||
for (TreeNode tN : choiceNodes) {
|
||||
if (tN instanceof ChoiceTreeNode) {
|
||||
ChoiceTreeNode cN = (ChoiceTreeNode) tN;
|
||||
cN.checkBox.setSelected((cN.selectionBit & modBitMap) != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getModBitmap() {
|
||||
int mp = 0;
|
||||
for (ChoiceTreeNode cN : choiceNodes) {
|
||||
if (cN.checkBox.isSelected()) {
|
||||
mp |= cN.selectionBit;
|
||||
for (TreeNode tN : choiceNodes) {
|
||||
if (tN instanceof ChoiceTreeNode) {
|
||||
ChoiceTreeNode cN = (ChoiceTreeNode) tN;
|
||||
if (cN.checkBox.isSelected()) {
|
||||
mp |= cN.selectionBit;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mp;
|
||||
|
81
src/PamView/symbol/modifier/swing/OptionsTreeNode.java
Normal file
@ -0,0 +1,81 @@
|
||||
package PamView.symbol.modifier.swing;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.tree.TreeNode;
|
||||
|
||||
import PamView.dialog.GenericSwingDialog;
|
||||
import PamView.dialog.PamDialogPanel;
|
||||
import PamView.symbol.modifier.SymbolModifier;
|
||||
|
||||
public class OptionsTreeNode implements TreeNode {
|
||||
|
||||
private ModifierTreeNode parent;
|
||||
private SymbolModifier modifier;
|
||||
private PamDialogPanel optionsPanel;
|
||||
protected JButton optionsButton;
|
||||
private int leafIndex;
|
||||
|
||||
public OptionsTreeNode(ModifierTreeNode parent, SymbolModifier modifier, PamDialogPanel optionsPanel, int leafIndex) {
|
||||
this.parent = parent;
|
||||
this.modifier = modifier;
|
||||
this.optionsPanel = optionsPanel;
|
||||
this.leafIndex = leafIndex;
|
||||
optionsButton = new JButton("more ...");
|
||||
optionsButton.setToolTipText("More symbol options");
|
||||
optionsButton.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showOptions();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showOptions() {
|
||||
optionsPanel.setParams();
|
||||
boolean ok = GenericSwingDialog.showDialog(null, "Options", optionsPanel);
|
||||
if (ok) {
|
||||
optionsPanel.getParams();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeNode getChildAt(int childIndex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChildCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeNode getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex(TreeNode node) {
|
||||
return leafIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllowsChildren() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeaf() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<? extends TreeNode> children() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -18,12 +18,10 @@ import javax.swing.tree.TreePath;
|
||||
|
||||
import PamView.dialog.DialogScrollPane;
|
||||
import PamView.dialog.PamDialogPanel;
|
||||
import PamView.symbol.PamSymbolChooser;
|
||||
import PamView.symbol.StandardSymbolChooser;
|
||||
import PamView.symbol.StandardSymbolOptions;
|
||||
import PamView.symbol.modifier.SymbolModifier;
|
||||
import PamView.symbol.modifier.SymbolModifierParams;
|
||||
import PamguardMVC.debug.Debug;
|
||||
|
||||
/**
|
||||
* Panel to include in a dialog with options to select and activate a variety of symbol modifiers.
|
||||
@ -137,6 +135,7 @@ public class SymbolModifierPanel implements PamDialogPanel {
|
||||
JMenuItem optsItem = modifier.getModifierOptionsMenu();
|
||||
if (optsItem != null) {
|
||||
popMenu.add(optsItem);
|
||||
popMenu.addSeparator();
|
||||
}
|
||||
}
|
||||
if (nodeInd > 0) {
|
||||
|
@ -43,6 +43,10 @@ public class SymbolTreeRenderer extends DefaultTreeCellRenderer {
|
||||
if (value instanceof ChoiceTreeNode) {
|
||||
return checkboxChoice(tree, (ChoiceTreeNode) value, sel, expanded, leaf, row, hasFocus);
|
||||
}
|
||||
|
||||
if (value instanceof OptionsTreeNode) {
|
||||
return ((OptionsTreeNode) value).optionsButton;
|
||||
}
|
||||
|
||||
Component component = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
|
||||
if (value instanceof ModifierTreeNode) {
|
||||
|
@ -257,12 +257,13 @@ public class PamRawDataBlock extends AcousticDataBlock<RawDataUnit> {
|
||||
synchronized public RawDataUnit[] getAvailableSamples(long startMillis, long durationMillis, int channelMap) throws RawDataUnavailableException {
|
||||
RawDataUnit firstUnit = getFirstUnit();
|
||||
if (firstUnit == null) {
|
||||
throw new RawDataUnavailableException(this, RawDataUnavailableException.DATA_NOT_ARRIVED, startMillis, (int) durationMillis);
|
||||
throw new RawDataUnavailableException(this, RawDataUnavailableException.DATA_NOT_ARRIVED, 0,0, startMillis, (int) durationMillis);
|
||||
}
|
||||
long firstMillis = firstUnit.getTimeMilliseconds();
|
||||
long firstSamples = firstUnit.getStartSample();
|
||||
RawDataUnit lastUnit = getLastUnit();
|
||||
long lastMillis = lastUnit.getEndTimeInMilliseconds();
|
||||
long lastSample = lastUnit.getStartSample()+lastUnit.getSampleDuration();
|
||||
|
||||
|
||||
long firstAvailableMillis = Math.max(firstMillis, startMillis);
|
||||
@ -272,7 +273,8 @@ public class PamRawDataBlock extends AcousticDataBlock<RawDataUnit> {
|
||||
double[][] data = getSamplesForMillis(firstAvailableMillis, lastAvailableMillis-firstAvailableMillis, channelMap);
|
||||
if (data == null) {
|
||||
// this shouldn't happen. If an exception wasn't thrown from getSamples... then data should no tb enull
|
||||
throw new RawDataUnavailableException(this, RawDataUnavailableException.DATA_NOT_ARRIVED, startMillis, (int) durationMillis);
|
||||
throw new RawDataUnavailableException(this, RawDataUnavailableException.DATA_NOT_ARRIVED,
|
||||
firstSamples, lastSample, startMillis, (int) durationMillis);
|
||||
}
|
||||
RawDataUnit[] dataUnits = new RawDataUnit[data.length];
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
@ -298,7 +300,7 @@ public class PamRawDataBlock extends AcousticDataBlock<RawDataUnit> {
|
||||
synchronized public double[][] getSamplesForMillis(long startMillis, long durationMillis, int channelMap) throws RawDataUnavailableException {
|
||||
RawDataUnit firstUnit = getFirstUnit();
|
||||
if (firstUnit == null) {
|
||||
throw new RawDataUnavailableException(this, RawDataUnavailableException.DATA_NOT_ARRIVED, startMillis, (int) durationMillis);
|
||||
throw new RawDataUnavailableException(this, RawDataUnavailableException.DATA_NOT_ARRIVED, 0, 0, startMillis, (int) durationMillis);
|
||||
}
|
||||
long firstMillis = firstUnit.getTimeMilliseconds();
|
||||
long firstSamples = firstUnit.getStartSample();
|
||||
@ -317,23 +319,28 @@ public class PamRawDataBlock extends AcousticDataBlock<RawDataUnit> {
|
||||
// run a few tests ...
|
||||
int chanOverlap = channelMap & getChannelMap();
|
||||
if (chanOverlap != channelMap) {
|
||||
throw new RawDataUnavailableException(this, RawDataUnavailableException.INVALID_CHANNEL_LIST, startSample, duration);
|
||||
throw new RawDataUnavailableException(this, RawDataUnavailableException.INVALID_CHANNEL_LIST, 0,0,startSample, duration);
|
||||
}
|
||||
if (duration < 0) {
|
||||
throw new RawDataUnavailableException(this, RawDataUnavailableException.NEGATIVE_DURATION, startSample, duration);
|
||||
throw new RawDataUnavailableException(this, RawDataUnavailableException.NEGATIVE_DURATION,0,0, startSample, duration);
|
||||
}
|
||||
|
||||
RawDataUnit dataUnit = getFirstUnit();
|
||||
if (dataUnit == null) {
|
||||
return null;
|
||||
}
|
||||
if (dataUnit.getStartSample() > startSample) {
|
||||
RawDataUnit lastUnit = getLastUnit();
|
||||
long firstSample = dataUnit.getStartSample();
|
||||
long lastSample = lastUnit.getStartSample()+lastUnit.getSampleDuration();
|
||||
if (firstSample > startSample) {
|
||||
// System.out.println("Earliest start sample : " + dataUnit.getStartSample());
|
||||
throw new RawDataUnavailableException(this, RawDataUnavailableException.DATA_ALREADY_DISCARDED, startSample, duration);
|
||||
throw new RawDataUnavailableException(this, RawDataUnavailableException.DATA_ALREADY_DISCARDED,
|
||||
firstSample, lastSample, startSample, duration);
|
||||
}
|
||||
dataUnit = getLastUnit();
|
||||
if (hasLastSample(dataUnit, startSample+duration, channelMap) == false) {
|
||||
throw new RawDataUnavailableException(this, RawDataUnavailableException.DATA_NOT_ARRIVED, startSample, duration);
|
||||
throw new RawDataUnavailableException(this, RawDataUnavailableException.DATA_NOT_ARRIVED,
|
||||
firstSample, lastSample, startSample, duration);
|
||||
}
|
||||
|
||||
int nChan = PamUtils.getNumChannels(channelMap);
|
||||
|
@ -21,6 +21,10 @@ public class RawDataUnavailableException extends Exception {
|
||||
private long startSample;
|
||||
|
||||
private int duration;
|
||||
|
||||
private long availableStart;
|
||||
|
||||
private long availableEnd;
|
||||
/**
|
||||
* @return the dataCause
|
||||
*/
|
||||
@ -34,10 +38,12 @@ public class RawDataUnavailableException extends Exception {
|
||||
* @param startSample
|
||||
* @param cause
|
||||
*/
|
||||
public RawDataUnavailableException(PamRawDataBlock rawDataBlock, int dataCause, long startSample, int duration) {
|
||||
public RawDataUnavailableException(PamRawDataBlock rawDataBlock, int dataCause, long availStart, long availEnd, long startSample, int duration) {
|
||||
super();
|
||||
this.rawDataBlock = rawDataBlock;
|
||||
this.dataCause = dataCause;
|
||||
this.availableStart = availStart;
|
||||
this.availableEnd = availEnd;
|
||||
this.startSample = startSample;
|
||||
this.duration = duration;
|
||||
}
|
||||
@ -55,8 +61,8 @@ public class RawDataUnavailableException extends Exception {
|
||||
public String getMessage() {
|
||||
switch (dataCause) {
|
||||
case DATA_ALREADY_DISCARDED:
|
||||
return String.format("Samples %d length %d requested from %s have already been discarded", startSample, duration,
|
||||
rawDataBlock.getDataName());
|
||||
return String.format("Samples %d length %d requested from %s have already been discarded. %d to %d available", startSample, duration,
|
||||
rawDataBlock.getDataName(), availableStart, availableEnd);
|
||||
case DATA_NOT_ARRIVED:
|
||||
return String.format("Samples %d length %d requested from %s have not yet arrived",
|
||||
startSample, duration, rawDataBlock.getDataName());
|
||||
@ -70,6 +76,20 @@ public class RawDataUnavailableException extends Exception {
|
||||
}
|
||||
return super.getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the availableStart
|
||||
*/
|
||||
public long getAvailableStart() {
|
||||
return availableStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the availableEnd
|
||||
*/
|
||||
public long getAvailableEnd() {
|
||||
return availableEnd;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import Acquisition.AcquisitionControl;
|
||||
import Acquisition.AcquisitionProcess;
|
||||
import Acquisition.DaqSystem;
|
||||
import PamController.PamController;
|
||||
import PamModel.PamModel;
|
||||
import PamUtils.PamCalendar;
|
||||
import PamguardMVC.debug.Debug;
|
||||
|
||||
@ -130,6 +131,7 @@ public class ThreadedObserver implements PamObserver {
|
||||
}
|
||||
}
|
||||
}
|
||||
h += PamModel.getPamModel().getPamModelSettings().getThreadingJitterMillis()*2;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
@ -108,4 +108,25 @@ public class CompoundDataSelector extends DataSelector {
|
||||
return selectorList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSelector findDataSelector(Class selectorClass) {
|
||||
/**
|
||||
* Check this, then all in the selector list. Should iterate happily back to
|
||||
* a basic data selector as required even if there are multiple Compound ones.
|
||||
*/
|
||||
if (this.getClass() == selectorClass) {
|
||||
return this;
|
||||
}
|
||||
if (selectorList == null) {
|
||||
return null;
|
||||
}
|
||||
for (DataSelector aSelector : selectorList) {
|
||||
DataSelector subSel = aSelector.findDataSelector(selectorClass);
|
||||
if (subSel != null) {
|
||||
return subSel;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -76,6 +76,22 @@ public class DataSelectDialog extends PamDialog {
|
||||
// }
|
||||
}
|
||||
|
||||
public boolean setTab(int tabIndex) {
|
||||
if (tabPane == null) {
|
||||
return false;
|
||||
}
|
||||
if (tabIndex < 0 || tabIndex >= tabPane.getTabCount()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
tabPane.setSelectedIndex(tabIndex);
|
||||
}
|
||||
catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean showDialog() {
|
||||
if (dataPanel != null) {
|
||||
dataPanel.setParams();
|
||||
|
@ -97,6 +97,23 @@ public abstract class DataSelector {
|
||||
*/
|
||||
abstract public DynamicSettingsPane<Boolean> getDialogPaneFX();
|
||||
|
||||
/**
|
||||
* Find a data selector within a data selector. This is primarily for use with
|
||||
* ComoundDataSelector objects which may encapsulate multiple other selectors,
|
||||
* particularly when annotations are in use. but it's needed here so that it
|
||||
* can be called on any DataSelector object.
|
||||
* @param selectorClass class to data selector to find.
|
||||
* @return DataSelector or null if that class of data selector doesn't exist.
|
||||
*/
|
||||
public DataSelector findDataSelector(Class selectorClass) {
|
||||
if (this.getClass() == selectorClass) {
|
||||
return this;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a menu item for the data selector that can be easily added
|
||||
* to any other menu.
|
||||
|
@ -228,6 +228,7 @@ PamSettingsSource, DataOutputStore {
|
||||
super.pamToStart();
|
||||
prepareStores();
|
||||
openStores();
|
||||
binaryStoreProcess.checkFileTimer();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -245,9 +246,9 @@ PamSettingsSource, DataOutputStore {
|
||||
* Called from the process to close and reopen each datastream in
|
||||
* a new file. Probably gets called about once an hour on the hour.
|
||||
*/
|
||||
protected void reOpenStores(int endReason) {
|
||||
protected synchronized void reOpenStores(int endReason, long newFileTime) {
|
||||
|
||||
long dataTime = PamCalendar.getTimeInMillis();
|
||||
long dataTime = newFileTime;//PamCalendar.getTimeInMillis();
|
||||
long analTime = System.currentTimeMillis();
|
||||
BinaryOutputStream dataStream;
|
||||
for (int i = 0; i < storageStreams.size(); i++) {
|
||||
@ -536,7 +537,7 @@ PamSettingsSource, DataOutputStore {
|
||||
*/
|
||||
if (immediateChanges) {
|
||||
if (storesOpen) {
|
||||
reOpenStores(BinaryFooter.END_UNKNOWN);
|
||||
reOpenStores(BinaryFooter.END_UNKNOWN, PamCalendar.getTimeInMillis());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2601,5 +2602,11 @@ PamSettingsSource, DataOutputStore {
|
||||
public DataIntegrityChecker getInegrityChecker() {
|
||||
return new BinaryIntegrityChecker(this);
|
||||
}
|
||||
/**
|
||||
* @return the binaryStoreProcess
|
||||
*/
|
||||
public BinaryStoreProcess getBinaryStoreProcess() {
|
||||
return binaryStoreProcess;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,37 +7,43 @@ import PamUtils.PamCalendar;
|
||||
import PamguardMVC.PamProcess;
|
||||
|
||||
public class BinaryStoreProcess extends PamProcess {
|
||||
|
||||
|
||||
private BinaryStore binaryStore;
|
||||
|
||||
|
||||
private long startTime;
|
||||
|
||||
|
||||
private long nextFileTime;
|
||||
|
||||
|
||||
private Timer timer;
|
||||
|
||||
private Object timerSynch = new Object();
|
||||
|
||||
public BinaryStoreProcess(BinaryStore binaryStore) {
|
||||
super(binaryStore, null);
|
||||
this.binaryStore = binaryStore;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getProcessName() {
|
||||
return "Binary store file control";
|
||||
}
|
||||
|
||||
public synchronized void checkFileTime() {
|
||||
|
||||
public synchronized void checkFileTime(long masterClockTime) {
|
||||
// if (binaryStore.binaryStoreSettings.autoNewFiles &&
|
||||
// PamCalendar.getTimeInMillis() >= nextFileTime) {
|
||||
// startNewFiles();
|
||||
// }
|
||||
if (binaryStore.binaryStoreSettings.autoNewFiles &&
|
||||
PamCalendar.getTimeInMillis() >= nextFileTime) {
|
||||
startNewFiles();
|
||||
masterClockTime >= nextFileTime) {
|
||||
startNewFiles(masterClockTime);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private synchronized void startNewFiles() {
|
||||
private synchronized void startNewFiles(long masterClockTime) {
|
||||
nextFileTime += binaryStore.binaryStoreSettings.fileSeconds * 1000;
|
||||
binaryStore.reOpenStores(BinaryFooter.END_FILETOOLONG);
|
||||
binaryStore.reOpenStores(BinaryFooter.END_FILETOOLONG, masterClockTime);
|
||||
}
|
||||
|
||||
|
||||
@ -46,24 +52,55 @@ public class BinaryStoreProcess extends PamProcess {
|
||||
startTime = PamCalendar.getTimeInMillis();
|
||||
long round = binaryStore.binaryStoreSettings.fileSeconds * 1000;
|
||||
nextFileTime = (startTime/round) * round + round;
|
||||
// System.out.println("Next file start at " + PamCalendar.formatDateTime(nextFileTime));
|
||||
timer = new Timer();
|
||||
timer.schedule(new FileTimerTask(), 1000, 1000);
|
||||
|
||||
// System.out.println("Next file start at " + PamCalendar.formatDateTime(nextFileTime));
|
||||
}
|
||||
|
||||
public void checkFileTimer() {
|
||||
boolean needTimer = PamCalendar.isSoundFile() == false;
|
||||
if (needTimer) {
|
||||
startTimer();
|
||||
}
|
||||
else {
|
||||
stopTimer();
|
||||
}
|
||||
}
|
||||
|
||||
private void startTimer() {
|
||||
synchronized (timerSynch) {
|
||||
if (timer == null) {
|
||||
timer = new Timer();
|
||||
timer.schedule(new FileTimerTask(), 1000, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void stopTimer() {
|
||||
synchronized (timerSynch) {
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// @Override
|
||||
// public void masterClockUpdate(long timeMilliseconds, long sampleNumber) {
|
||||
// super.masterClockUpdate(timeMilliseconds, sampleNumber);
|
||||
// checkFileTime(timeMilliseconds);
|
||||
// }
|
||||
|
||||
class FileTimerTask extends TimerTask {
|
||||
@Override
|
||||
public void run() {
|
||||
checkFileTime();
|
||||
checkFileTime(PamCalendar.getTimeInMillis());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pamStop() {
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
}
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import PamView.PamSymbolType;
|
||||
import PamView.dialog.PamDialog;
|
||||
import PamView.dialog.PamDialogPanel;
|
||||
import PamView.dialog.PamGridBagContraints;
|
||||
import clickDetector.dataSelector.ClickDataSelector;
|
||||
import pamMaths.HistogramDisplay;
|
||||
import pamMaths.HistogramGraphicsLayer;
|
||||
import pamMaths.PamHistogram;
|
||||
@ -59,6 +60,7 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
||||
private JCheckBox amplitudeSelect;
|
||||
private JTextField minAmplitude;
|
||||
private JFrame ownerFrame;
|
||||
private ClickDataSelector dataSelector;
|
||||
/**
|
||||
* @param btDisplay
|
||||
*/
|
||||
@ -66,6 +68,7 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
||||
super();
|
||||
this.clickControl = clickControl;
|
||||
this.btDisplay = btDisplay;
|
||||
dataSelector = btDisplay.getClickDataSelector();
|
||||
clickDataBlock = clickControl.getClickDataBlock();
|
||||
histoPlot = new HistogramDisplay();
|
||||
histoPlot.setGraphicsOverLayer(histoOverLayer = new HistoOverLayer());
|
||||
@ -125,7 +128,8 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
||||
axMin = allHistogram.getScaleMinVal();
|
||||
axMax = allHistogram.getScaleMaxVal();
|
||||
plotRectangle = g.getClipBounds();
|
||||
double dx = (btDisplayParameters.minAmplitude - axMin) / (axMax-axMin) * plotRectangle.width;
|
||||
// double dx = (btDisplayParameters.minAmplitude - axMin) / (axMax-axMin) * plotRectangle.width;
|
||||
double dx = (dataSelector.getParams().minimumAmplitude - axMin) / (axMax-axMin) * plotRectangle.width;
|
||||
int x = (int) Math.round(dx);
|
||||
g.setColor(Color.RED);
|
||||
g.drawLine(x, 0, x, plotRectangle.height);
|
||||
@ -151,7 +155,7 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
||||
double newAmp = (double) mouseEvent.getX() / histoOverLayer.plotRectangle.width *
|
||||
(histoOverLayer.axMax-histoOverLayer.axMin) + histoOverLayer.axMin;
|
||||
BTDisplayParameters btDisplayParameters = btDisplay.getBtDisplayParameters();
|
||||
btDisplayParameters.minAmplitude = newAmp;
|
||||
dataSelector.getParams().minimumAmplitude = newAmp;
|
||||
ampCtrlPanel.setParams(btDisplayParameters);
|
||||
redrawHisto();
|
||||
//
|
||||
@ -173,7 +177,7 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
||||
if (btDisplayParameters.amplitudeSelect == false) {
|
||||
return false;
|
||||
}
|
||||
double dx = (btDisplayParameters.minAmplitude - histoOverLayer.axMin) /
|
||||
double dx = (dataSelector.getParams().minimumAmplitude - histoOverLayer.axMin) /
|
||||
(histoOverLayer.axMax-histoOverLayer.axMin) * histoOverLayer.plotRectangle.width;
|
||||
int x = (int) Math.round(dx);
|
||||
if (Math.abs(e.getX()-x) > 10) {
|
||||
@ -213,14 +217,14 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
||||
}
|
||||
private void setParams(BTDisplayParameters btParams) {
|
||||
amplitudeSelect.setSelected(btParams.amplitudeSelect);
|
||||
minAmplitude.setText(String.format("%3.1f", btParams.minAmplitude));
|
||||
minAmplitude.setText(String.format("%3.1f", dataSelector.getParams().minimumAmplitude));
|
||||
|
||||
enableControls();
|
||||
}
|
||||
private boolean getParams(BTDisplayParameters btParams) {
|
||||
btParams.amplitudeSelect = amplitudeSelect.isSelected();
|
||||
try {
|
||||
btParams.minAmplitude = Double.valueOf(minAmplitude.getText());
|
||||
dataSelector.getParams().minimumAmplitude = Double.valueOf(minAmplitude.getText());
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return false;
|
||||
|
@ -44,17 +44,17 @@ public class BTDisplayParameters implements Serializable, Cloneable, ManagedPara
|
||||
public int nBearingGridLines = 1;
|
||||
public int nAmplitudeGridLines = 0;
|
||||
public int nICIGridLines = 0;
|
||||
public boolean showEchoes = true;
|
||||
// public boolean showEchoes = true;
|
||||
public int minClickLength = 2, maxClickLength = 12;
|
||||
public int minClickHeight = 2, maxClickHeight = 12;
|
||||
private double timeRange = 10;
|
||||
public int displayChannels = 0;
|
||||
public boolean view360;
|
||||
public boolean amplitudeSelect = false;
|
||||
public double minAmplitude = 0;
|
||||
// public double minAmplitude = 0;
|
||||
public boolean showUnassignedICI = false;
|
||||
public boolean showEventsOnly = false;
|
||||
public boolean showANDEvents = true;
|
||||
// public boolean showEventsOnly = false;
|
||||
// public boolean showANDEvents = true;
|
||||
public boolean logICIScale;
|
||||
public int angleRotation = ROTATE_TOARRAY;
|
||||
|
||||
@ -65,7 +65,7 @@ public class BTDisplayParameters implements Serializable, Cloneable, ManagedPara
|
||||
/*
|
||||
* Show identified species
|
||||
*/
|
||||
private boolean[] showSpeciesList;
|
||||
// private boolean[] showSpeciesList;
|
||||
|
||||
public int colourScheme = COLOUR_BY_TRAIN;
|
||||
|
||||
@ -83,7 +83,7 @@ public class BTDisplayParameters implements Serializable, Cloneable, ManagedPara
|
||||
} catch (CloneNotSupportedException Ex) {
|
||||
Ex.printStackTrace();
|
||||
}
|
||||
showSpeciesList = null;
|
||||
// showSpeciesList = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -107,49 +107,49 @@ public class BTDisplayParameters implements Serializable, Cloneable, ManagedPara
|
||||
/**
|
||||
* @return the showSpeciesList
|
||||
*/
|
||||
public boolean getShowSpecies(int speciesIndex) {
|
||||
if (showSpeciesList != null && showSpeciesList.length > speciesIndex) {
|
||||
return showSpeciesList[speciesIndex];
|
||||
}
|
||||
makeShowSpeciesList(speciesIndex);
|
||||
return true;
|
||||
}
|
||||
private void makeShowSpeciesList(int maxIndex) {
|
||||
if (showSpeciesList == null) {
|
||||
showSpeciesList = new boolean[0];
|
||||
}
|
||||
else if (showSpeciesList.length > maxIndex) {
|
||||
return;
|
||||
}
|
||||
int oldLength = showSpeciesList.length;
|
||||
showSpeciesList = Arrays.copyOf(showSpeciesList, maxIndex + 1);
|
||||
for (int i = oldLength; i <= maxIndex; i++) {
|
||||
showSpeciesList[i] = true;
|
||||
}
|
||||
}
|
||||
// public boolean getShowSpecies(int speciesIndex) {
|
||||
// if (showSpeciesList != null && showSpeciesList.length > speciesIndex) {
|
||||
// return showSpeciesList[speciesIndex];
|
||||
// }
|
||||
// makeShowSpeciesList(speciesIndex);
|
||||
// return true;
|
||||
// }
|
||||
// private void makeShowSpeciesList(int maxIndex) {
|
||||
// if (showSpeciesList == null) {
|
||||
// showSpeciesList = new boolean[0];
|
||||
// }
|
||||
// else if (showSpeciesList.length > maxIndex) {
|
||||
// return;
|
||||
// }
|
||||
// int oldLength = showSpeciesList.length;
|
||||
// showSpeciesList = Arrays.copyOf(showSpeciesList, maxIndex + 1);
|
||||
// for (int i = oldLength; i <= maxIndex; i++) {
|
||||
// showSpeciesList[i] = true;
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param showSpeciesList the showSpeciesList to set
|
||||
*/
|
||||
public void setShowSpecies(int speciesIndex, boolean showSpecies) {
|
||||
makeShowSpeciesList(speciesIndex);
|
||||
showSpeciesList[speciesIndex] = showSpecies;
|
||||
}
|
||||
// public void setShowSpecies(int speciesIndex, boolean showSpecies) {
|
||||
// makeShowSpeciesList(speciesIndex);
|
||||
// showSpeciesList[speciesIndex] = showSpecies;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public PamParameterSet getParameterSet() {
|
||||
PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
|
||||
try {
|
||||
Field field = this.getClass().getDeclaredField("showSpeciesList");
|
||||
ps.put(new PrivatePamParameterData(this, field) {
|
||||
@Override
|
||||
public Object getData() throws IllegalArgumentException, IllegalAccessException {
|
||||
return showSpeciesList;
|
||||
}
|
||||
});
|
||||
} catch (NoSuchFieldException | SecurityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// try {
|
||||
// Field field = this.getClass().getDeclaredField("showSpeciesList");
|
||||
// ps.put(new PrivatePamParameterData(this, field) {
|
||||
// @Override
|
||||
// public Object getData() throws IllegalArgumentException, IllegalAccessException {
|
||||
// return showSpeciesList;
|
||||
// }
|
||||
// });
|
||||
// } catch (NoSuchFieldException | SecurityException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
return ps;
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ import java.awt.Insets;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.AdjustmentEvent;
|
||||
@ -115,9 +116,13 @@ import PamguardMVC.PamDataBlock;
|
||||
import PamguardMVC.PamDataUnit;
|
||||
import PamguardMVC.PamObservable;
|
||||
import PamguardMVC.PamObserver;
|
||||
import PamguardMVC.dataSelector.DataSelectDialog;
|
||||
import PamguardMVC.dataSelector.DataSelector;
|
||||
import PamguardMVC.superdet.SuperDetection;
|
||||
import clickDetector.ClickClassifiers.ClickIdInformation;
|
||||
import clickDetector.ClickClassifiers.ClickIdentifier;
|
||||
import clickDetector.alarm.ClickAlarmParameters;
|
||||
import clickDetector.dataSelector.ClickDataSelector;
|
||||
import clickDetector.dialogs.ClickDisplayDialog;
|
||||
import clickDetector.offlineFuncs.OfflineEventDataBlock;
|
||||
import clickDetector.offlineFuncs.OfflineEventDataUnit;
|
||||
@ -2240,11 +2245,15 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
if (btDisplayParameters.amplitudeSelect == false) {
|
||||
return;
|
||||
}
|
||||
ClickDataSelector clickDataSelector = getClickDataSelector();
|
||||
if (clickDataSelector == null) {
|
||||
return;
|
||||
}
|
||||
int n = countAmplitudeDeselected();
|
||||
PamDataBlock<ClickDetection> clickData = clickControl.getClickDataBlock();
|
||||
int nAll = clickData.getUnitsCount();
|
||||
String txt = String.format("%d of %d loaded clicks will not be displayed because their amplitude is < %3.1fdB",
|
||||
n, nAll, btDisplayParameters.minAmplitude);
|
||||
n, nAll, clickDataSelector.getParams().minimumAmplitude);
|
||||
Insets insets = getInsets();
|
||||
int x = insets.left;
|
||||
int y = getHeight()-5;
|
||||
@ -2383,19 +2392,33 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
}
|
||||
|
||||
menuItem = new JMenuItem("Settings ...");
|
||||
menuItem.setToolTipText("Display options");
|
||||
menuItem.addActionListener(new SettingsMenuAction());
|
||||
menu.add(menuItem);
|
||||
menuItem = new JMenuItem("Click data selector ...");
|
||||
menuItem.setToolTipText("Detailed data selection options");
|
||||
menuItem.addActionListener(new DataSelectorAction());
|
||||
menu.add(menuItem);
|
||||
menuItem = new JMenuItem("Show amplitude selector ...");
|
||||
menuItem.setToolTipText("Graphical amplitude selector display");
|
||||
menuItem.addActionListener(new AmplitudeSelector());
|
||||
menu.add(menuItem);
|
||||
menu.addSeparator();
|
||||
ArrayList<JMenuItem> colOptList = getSymbolChooser().getQuickMenuItems(clickControl.getGuiFrame(), this, "Colour by ", SymbolModType.EVERYTHING, true);
|
||||
ArrayList<JMenuItem> colOptList = getSymbolChooser().getQuickMenuItems(clickControl.getGuiFrame(), this, "Colour by ", SymbolModType.EVERYTHING, false);
|
||||
if (colOptList != null) {
|
||||
for (JMenuItem menuIt : colOptList) {
|
||||
menu.add(menuIt);
|
||||
}
|
||||
menu.addSeparator();
|
||||
}
|
||||
menuItem = new JMenuItem("More symbol options ...");
|
||||
menuItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showDataSymbolOptions(1);
|
||||
}
|
||||
});
|
||||
menu.add(menuItem);
|
||||
menu.addSeparator();
|
||||
|
||||
// menuItem = new JCheckBoxMenuItem("Colour by species id",
|
||||
// btDisplayParameters.colourScheme == BTDisplayParameters.COLOUR_BY_SPECIES);
|
||||
@ -2470,7 +2493,7 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Looks through the current modules and finds if there is a target motion or static localiser
|
||||
*/
|
||||
@ -2771,7 +2794,7 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
|
||||
BTDisplayParameters newParameters =
|
||||
ClickDisplayDialog.showDialog(clickControl,
|
||||
clickControl.getGuiFrame(), btDisplayParameters);
|
||||
clickControl.getGuiFrame(), btDisplayParameters, getClickDataSelector().getClickAlarmParameters());
|
||||
if (newParameters != null){
|
||||
btDisplayParameters = newParameters.clone();
|
||||
if (getVScaleManager() != null) {
|
||||
@ -2788,6 +2811,30 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a data selector specific to this display.
|
||||
* @return click data selector specific to this display.
|
||||
*/
|
||||
public DataSelector getDataSelector() {
|
||||
return clickControl.getClickDataBlock().getDataSelector(getUnitName(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the click specific data selector which may now be burried in a
|
||||
* CompoundDataSelector if annotations have been used.
|
||||
* @return ClickDataSelector.
|
||||
*/
|
||||
public ClickDataSelector getClickDataSelector() {
|
||||
DataSelector baseSel = getDataSelector();
|
||||
if (baseSel == null) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return (ClickDataSelector) baseSel.findDataSelector(ClickDataSelector.class);
|
||||
}
|
||||
}
|
||||
|
||||
class AmplitudeSelector implements ActionListener {
|
||||
@Override
|
||||
@ -2795,6 +2842,13 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
showAmplitudeSelector();
|
||||
}
|
||||
}
|
||||
|
||||
class DataSelectorAction implements ActionListener {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showDataSelector();
|
||||
}
|
||||
}
|
||||
|
||||
private void showAmplitudeSelector() {
|
||||
|
||||
@ -2814,6 +2868,38 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a dialog with both data and symbol options, but go to the correct tab.
|
||||
* @param selectedTab
|
||||
* @return
|
||||
*/
|
||||
private boolean showDataSymbolOptions(int selectedTab) {
|
||||
Window javaFrame = clickControl.getGuiFrame();
|
||||
DataSelectDialog dataSelectDialog = new DataSelectDialog(javaFrame, clickControl.getClickDataBlock(), getDataSelector(), symbolChooser);
|
||||
if (javaFrame == null) {
|
||||
dataSelectDialog.moveToMouseLocation();
|
||||
}
|
||||
dataSelectDialog.setTab(selectedTab);
|
||||
boolean ok = dataSelectDialog.showDialog();
|
||||
if (ok) {
|
||||
repaintBoth();
|
||||
if (clickControl.getOfflineToolbar() != null) {
|
||||
clickControl.getOfflineToolbar().displayActivated(clickBTDisplay);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
public void showDataSelector() {
|
||||
// if (getDataSelector().showSelectDialog(clickControl.getGuiFrame())) {
|
||||
// repaintBoth();
|
||||
// if (clickControl.getOfflineToolbar() != null) {
|
||||
// clickControl.getOfflineToolbar().displayActivated(clickBTDisplay);
|
||||
// }
|
||||
// };
|
||||
showDataSymbolOptions(0);
|
||||
}
|
||||
|
||||
private void checkBTAmplitudeSelectHisto() {
|
||||
if (btAmplitudeSelector == null) {
|
||||
return;
|
||||
@ -3036,15 +3122,15 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
zoomer.paintShape(g, this, true);
|
||||
}
|
||||
|
||||
// long t1 = System.nanoTime();
|
||||
synchronized (clickData.getSynchLock()) {
|
||||
// long t2 = System.nanoTime();
|
||||
// double ms = ((double) (t2-t1)) / 1000000.;
|
||||
// if (btDisplayParameters.VScale == BTDisplayParameters.DISPLAY_ICI) {
|
||||
// sortTempICIs();
|
||||
// }
|
||||
ArrayList<ClickDetection> clickCopy = clickData.getDataCopy(displayStartMillis, displayStartMillis+displayLengthMillis, true, getDataSelector());
|
||||
if (clickCopy.size() == 0) {
|
||||
return;
|
||||
}
|
||||
ListIterator<ClickDetection> clickIterator = clickCopy.listIterator(clickCopy.size()-1);
|
||||
|
||||
ListIterator<ClickDetection> clickIterator = clickData.getListIterator(PamDataBlock.ITERATOR_END);
|
||||
// synchronized (clickData.getSynchLock()) {
|
||||
//
|
||||
// ListIterator<ClickDetection> clickIterator = clickData.getListIterator(PamDataBlock.ITERATOR_END);
|
||||
while (clickIterator.hasPrevious()) {
|
||||
click = clickIterator.previous();
|
||||
if (shouldPlot(prevPlottedClick)){
|
||||
@ -3060,11 +3146,6 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
if (shouldPlot(prevPlottedClick)){ // and draw the last one !
|
||||
drawClick(g, prevPlottedClick, clipRectangle);
|
||||
}
|
||||
// g.drawString(String.format("Wait synch %3.3fms", ms), 0, 20);
|
||||
}
|
||||
// long t3 = System.nanoTime();
|
||||
// g.drawString(String.format("Last draw %3.3fms", lastPaintTime), 0, 20);
|
||||
// lastPaintTime = ((double) (t3-t0)) / 1000000.;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -3342,7 +3423,9 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
else if (btDisplayParameters.colourScheme == BTDisplayParameters.COLOUR_BY_HYDROPHONE) {
|
||||
keyPanel.add(new TextKeyItem("Colour by hydrophone"));
|
||||
}
|
||||
if (btDisplayParameters.getShowSpecies(0)) {
|
||||
ClickAlarmParameters selectParams = getClickDataSelector().getParams();
|
||||
// if (btDisplayParameters.getShowSpecies(0)) {
|
||||
if (selectParams.onlineAutoEvents | selectParams.onlineManualEvents) {
|
||||
keyPanel.add(symbolChooser.getDefaultSymbol(true).makeKeyItem("Unidentified species"));
|
||||
}
|
||||
|
||||
@ -3354,7 +3437,8 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
PamSymbol[] symbols = clickControl.getClickIdentifier().getSymbols();
|
||||
if (speciesList != null) {
|
||||
for (int i = 0; i < speciesList.length; i++) {
|
||||
if (btDisplayParameters.getShowSpecies(i+1)) {
|
||||
if (selectParams.getUseSpecies(i+1)) {
|
||||
// if (btDisplayParameters.getShowSpecies(i+1)) {
|
||||
if (btDisplayParameters.colourScheme != BTDisplayParameters.COLOUR_BY_TRAIN) {
|
||||
keyPanel.add(symbols[i].makeKeyItem(speciesList[i]));
|
||||
}
|
||||
@ -3423,11 +3507,12 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
PamDataBlock<ClickDetection> clickData = clickControl.getClickDataBlock();
|
||||
ClickDetection click;
|
||||
int n = 0;
|
||||
double minAmpli = getClickDataSelector().getParams().minimumAmplitude;
|
||||
synchronized (clickData.getSynchLock()) {
|
||||
ListIterator<ClickDetection> clickIterator = clickData.getListIterator(0);
|
||||
while (clickIterator.hasNext()) {
|
||||
click = clickIterator.next();
|
||||
if (click.getAmplitudeDB() < btDisplayParameters.minAmplitude) {
|
||||
if (click.getAmplitudeDB() < minAmpli) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
@ -3448,29 +3533,30 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
*/
|
||||
synchronized boolean shouldPlot(ClickDetection click) {
|
||||
if (click == null) return false;
|
||||
if (!clickInTimeWindow(click)) return false;
|
||||
if (btDisplayParameters.showEchoes == false && click.isEcho()) {
|
||||
return false;
|
||||
}
|
||||
// if (!clickInTimeWindow(click)) return false;
|
||||
// if (btDisplayParameters.showEchoes == false && click.isEcho()) {
|
||||
// return false;
|
||||
// }
|
||||
if (btDisplayParameters.VScale == BTDisplayParameters.DISPLAY_ICI) {
|
||||
// if (btDisplayParameters.showUnassignedICI == false && click.getICI() < 0) return false;
|
||||
if (btDisplayParameters.showUnassignedICI == false && click.getSuperDetectionsCount() <= 0) return false;
|
||||
// otherwise may be ok, since will estimate all ici's on teh fly.
|
||||
}
|
||||
if (btDisplayParameters.amplitudeSelect && click.getAmplitudeDB() < btDisplayParameters.minAmplitude) {
|
||||
return false;
|
||||
}
|
||||
// if (btDisplayParameters.amplitudeSelect && click.getAmplitudeDB() < btDisplayParameters.minAmplitude) {
|
||||
// return false;
|
||||
// }
|
||||
if (btDisplayParameters.displayChannels > 0 && (btDisplayParameters.displayChannels & click.getChannelBitmap()) == 0) return false;
|
||||
|
||||
int speciesIndex = clickControl.getClickIdentifier().codeToListIndex(click.getClickType());
|
||||
boolean showSpecies = btDisplayParameters.getShowSpecies(speciesIndex+1);
|
||||
boolean showEvents = (btDisplayParameters.showEventsOnly == false || click.getSuperDetectionsCount() > 0);
|
||||
if (btDisplayParameters.showANDEvents) {
|
||||
return showSpecies & showEvents;
|
||||
}
|
||||
else {
|
||||
return showSpecies | showEvents;
|
||||
}
|
||||
// int speciesIndex = clickControl.getClickIdentifier().codeToListIndex(click.getClickType());
|
||||
// boolean showSpecies = btDisplayParameters.getShowSpecies(speciesIndex+1);
|
||||
// boolean showEvents = (btDisplayParameters.showEventsOnly == false || click.getSuperDetectionsCount() > 0);
|
||||
// if (btDisplayParameters.showANDEvents) {
|
||||
// return showSpecies & showEvents;
|
||||
// }
|
||||
// else {
|
||||
// return showSpecies | showEvents;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4085,7 +4171,7 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
amplitudeSelectorLabel.setText("");
|
||||
}
|
||||
else {
|
||||
String txt = String.format(" Amplitude Selector showing clicks > %3.1fdB", btDisplayParameters.minAmplitude);
|
||||
String txt = String.format(" Amplitude Selector showing clicks > %3.1fdB", getClickDataSelector().getParams().minimumAmplitude);
|
||||
amplitudeSelectorLabel.setText(txt);
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ public class ClickDetector extends PamProcess {
|
||||
offlineEventLogging.setSubLogging(getClickDataBlock().getOfflineClickLogging());
|
||||
|
||||
triggerBackgroundHandler = new TriggerBackgroundHandler(this);
|
||||
|
||||
|
||||
clickBackgroundManager = new ClickBackgroundManager(this);
|
||||
|
||||
setProcessCheck(new BaseProcessCheck(this, RawDataUnit.class, 1, 0.0000001));
|
||||
@ -1378,7 +1378,7 @@ public class ClickDetector extends PamProcess {
|
||||
private boolean initialiseFilters;
|
||||
|
||||
private long clickStartSample, clickEndSample;
|
||||
|
||||
|
||||
private double maxSignalExcess;
|
||||
|
||||
private int clickTriggers;
|
||||
|
@ -17,10 +17,12 @@ public class ClickAlarmParameters extends DataSelectParams implements Cloneable,
|
||||
public static final long serialVersionUID = 1L;
|
||||
private boolean[] useSpeciesList;
|
||||
private double[] speciesWeightings;
|
||||
public boolean useEchoes;
|
||||
public boolean scoreByAmplitude;
|
||||
public boolean onlineAutoEvents, onlineManualEvents;
|
||||
public boolean useEchoes = true;
|
||||
public boolean scoreByAmplitude; // alarm options, probably not used any more.
|
||||
public double minimumAmplitude;
|
||||
public boolean onlineAutoEvents = true, onlineManualEvents = true;
|
||||
public int minICIMillis;
|
||||
private boolean clicksOREvents = false;
|
||||
/*
|
||||
* Which events to use ...
|
||||
*/
|
||||
@ -165,5 +167,30 @@ public class ClickAlarmParameters extends DataSelectParams implements Cloneable,
|
||||
return ps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the clicksOREvents
|
||||
*/
|
||||
public boolean isClicksOREvents() {
|
||||
return clicksOREvents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clicksOREvents the clicksOREvents to set
|
||||
*/
|
||||
public void setClicksOREvents(boolean clicksOREvents) {
|
||||
this.clicksOREvents = clicksOREvents;
|
||||
}
|
||||
/**
|
||||
* @return the clicksANDEvents
|
||||
*/
|
||||
public boolean isClicksANDEvents() {
|
||||
return !clicksOREvents;
|
||||
}
|
||||
|
||||
|
||||
public void setClicksANDEvents(boolean clicksANDEvents) {
|
||||
this.clicksOREvents = !clicksANDEvents;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -38,9 +38,9 @@ public class ClickDataSelector extends DataSelector {
|
||||
|
||||
@Override
|
||||
public PamDialogPanel getDialogPanel() {
|
||||
if (clickSelectPanel == null) {
|
||||
// if (clickSelectPanel == null) {
|
||||
clickSelectPanel = new ClickSelectPanel(this, allowScores, useEventTypes);
|
||||
}
|
||||
// }
|
||||
return clickSelectPanel;
|
||||
}
|
||||
@Override
|
||||
@ -60,19 +60,25 @@ public class ClickDataSelector extends DataSelector {
|
||||
if (clickAlarmParameters.useEchoes == false && click.isEcho()) {
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* First score based on whether the event panel is in use and
|
||||
* criteria satisfied.
|
||||
*/
|
||||
|
||||
double score = scoreClick(click);
|
||||
if (useEventTypes) {
|
||||
if (wantEventType(click) == false) {
|
||||
return 0;
|
||||
double eventScore = scoreEventType(click);
|
||||
if (clickAlarmParameters.isClicksANDEvents()) {
|
||||
score = Math.min(score, eventScore);
|
||||
}
|
||||
else {
|
||||
score = Math.max(score, eventScore);
|
||||
}
|
||||
}
|
||||
return score;
|
||||
|
||||
/*
|
||||
* Now score based on whether or not it's individual click type is wanted.
|
||||
*/
|
||||
}
|
||||
|
||||
private double scoreClick(ClickDetection click) {
|
||||
if (click.getAmplitudeDB() < clickAlarmParameters.minimumAmplitude) {
|
||||
return 0;
|
||||
}
|
||||
ClickIdentifier clickIdentifier = clickControl.getClickIdentifier();
|
||||
int code = click.getClickType();
|
||||
if (code > 0 && clickIdentifier != null) {
|
||||
@ -81,13 +87,13 @@ public class ClickDataSelector extends DataSelector {
|
||||
boolean enabled = clickAlarmParameters.getUseSpecies(code);
|
||||
if (enabled == false) {
|
||||
return 0;
|
||||
}
|
||||
if (isAllowScores()) {
|
||||
}if (isAllowScores()) {
|
||||
return clickAlarmParameters.getSpeciesWeight(code);
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -95,7 +101,7 @@ public class ClickDataSelector extends DataSelector {
|
||||
* @param click
|
||||
* @return
|
||||
*/
|
||||
private boolean wantEventType(ClickDetection click) {
|
||||
private double scoreEventType(ClickDetection click) {
|
||||
OfflineEventDataUnit oev = null;
|
||||
|
||||
try {
|
||||
@ -107,7 +113,7 @@ public class ClickDataSelector extends DataSelector {
|
||||
|
||||
int eventId = click.getOfflineEventID();
|
||||
if (oev == null) {
|
||||
return clickAlarmParameters.unassignedEvents;
|
||||
return clickAlarmParameters.unassignedEvents ? 1 : 0;
|
||||
}
|
||||
|
||||
// see if there is a super detection and see if it's got a comment.
|
||||
@ -118,10 +124,10 @@ public class ClickDataSelector extends DataSelector {
|
||||
isAutomatic = comment.startsWith("Automatic");
|
||||
}
|
||||
if (isAutomatic && clickAlarmParameters.onlineAutoEvents) {
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
else if (clickAlarmParameters.onlineManualEvents) {
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
// if (clickAlarmParameters.onlineAutoEvents && comment.startsWith("Automatic")) {
|
||||
// return true;
|
||||
@ -134,7 +140,7 @@ public class ClickDataSelector extends DataSelector {
|
||||
* list of event types and see if it's wanted.
|
||||
*/
|
||||
String evType = oev.getEventType();
|
||||
return clickAlarmParameters.isUseEventType(evType);
|
||||
return clickAlarmParameters.isUseEventType(evType) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
@ -188,7 +194,7 @@ public class ClickDataSelector extends DataSelector {
|
||||
* @see PamguardMVC.dataSelector.DataSelector#getParams()
|
||||
*/
|
||||
@Override
|
||||
public DataSelectParams getParams() {
|
||||
public ClickAlarmParameters getParams() {
|
||||
return clickAlarmParameters;
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import generalDatabase.lookupTables.LookUpTables;
|
||||
import generalDatabase.lookupTables.LookupList;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
@ -13,11 +14,13 @@ import java.awt.event.ActionListener;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
import PamController.PamController;
|
||||
@ -42,6 +45,7 @@ public class ClickSelectPanel implements PamDialogPanel {
|
||||
private ClickDataSelector clickDataSelector;
|
||||
private JPanel mainPanel;
|
||||
private boolean isViewer;
|
||||
private JComboBox<String> andOrBox;
|
||||
|
||||
public static final String mainTip = "You should select options in both the Click Type and the Event Type panels";
|
||||
|
||||
@ -70,10 +74,12 @@ public class ClickSelectPanel implements PamDialogPanel {
|
||||
public void setParams() {
|
||||
eventTypePanel.setParams();
|
||||
speciesPanel.setParams();
|
||||
andOrBox.setSelectedIndex(clickDataSelector.getParams().isClicksANDEvents() ? 0 : 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getParams() {
|
||||
clickDataSelector.getParams().setClicksANDEvents(andOrBox.getSelectedIndex() == 0);
|
||||
return (speciesPanel.getParams() & eventTypePanel.getParams());
|
||||
}
|
||||
|
||||
@ -163,17 +169,26 @@ public class ClickSelectPanel implements PamDialogPanel {
|
||||
// JRadioButton andEvents, orEvents;
|
||||
// JRadioButton anyEvents, onlyEvents;
|
||||
private JCheckBox useEchoes;
|
||||
private JTextField minAmplitude;
|
||||
private JCheckBox scoreByAmplitude;
|
||||
private JTextField minICI;
|
||||
|
||||
SpeciesPanel () {
|
||||
super();
|
||||
setLayout(new BorderLayout());
|
||||
// setLayout(new BorderLayout());
|
||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||
northPanel = new JPanel();
|
||||
northPanel.setLayout(new GridBagLayout());
|
||||
GridBagConstraints c = new PamGridBagContraints();
|
||||
c.gridwidth = 3;
|
||||
c.gridwidth = 1;
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
northPanel.add(new JLabel("Minimum amplitude ", JLabel.RIGHT), c);
|
||||
c.gridx++;
|
||||
northPanel.add(minAmplitude = new JTextField(4), c);
|
||||
c.gridx++;
|
||||
northPanel.add(new JLabel(" dB"));
|
||||
c.gridx = 0;
|
||||
c.gridy++;
|
||||
northPanel.add(new PamAlignmentPanel(useEchoes = new JCheckBox("Use Echoes"), BorderLayout.WEST), c);
|
||||
c.gridwidth = 1;
|
||||
c.gridy++;
|
||||
@ -185,35 +200,50 @@ public class ClickSelectPanel implements PamDialogPanel {
|
||||
// minICI.setToolTipText("Minimum ICI in milliseconds");
|
||||
// c.gridx++;
|
||||
// northPanel.add(new JLabel(" ms", JLabel.LEFT), c);
|
||||
c.gridwidth = 3;
|
||||
c.gridy++;
|
||||
c.gridx = 0;
|
||||
northPanel.add(scoreByAmplitude = new JCheckBox("Score by amplitude"), c);
|
||||
scoreByAmplitude.setVisible(allowScores);
|
||||
scoreByAmplitude.addActionListener(new AllSpeciesListener());
|
||||
scoreByAmplitude = new JCheckBox("Score by amplitude");
|
||||
if (allowScores) {
|
||||
c.gridwidth = 3;
|
||||
c.gridy++;
|
||||
c.gridx = 0;
|
||||
northPanel.add(scoreByAmplitude, c);
|
||||
scoreByAmplitude.setVisible(allowScores);
|
||||
scoreByAmplitude.addActionListener(new AllSpeciesListener());
|
||||
}
|
||||
WestAlignedPanel walpn;
|
||||
add(BorderLayout.NORTH, walpn = new WestAlignedPanel(northPanel));
|
||||
walpn.setBorder(new SeparatorBorder("Echoes"));
|
||||
this.add(walpn = new WestAlignedPanel(northPanel));
|
||||
walpn.setBorder(new SeparatorBorder("Click Selection"));
|
||||
|
||||
JPanel centralOuterPanel = new JPanel(new BorderLayout());
|
||||
centralPanel.setLayout(new GridBagLayout());
|
||||
centralOuterPanel.setBorder(new SeparatorBorder("Click Type Selection"));
|
||||
centralOuterPanel.setBorder(new SeparatorBorder("Click Types"));
|
||||
|
||||
add(BorderLayout.CENTER, centralOuterPanel);
|
||||
this.add(centralOuterPanel);
|
||||
JScrollPane scrollPane = new DialogScrollPane(new PamAlignmentPanel(centralPanel, BorderLayout.WEST), 10);
|
||||
centralOuterPanel.add(BorderLayout.CENTER, scrollPane);
|
||||
|
||||
centralEastPanel.setLayout(new GridBagLayout());
|
||||
c = new PamGridBagContraints();
|
||||
centralEastPanel.add(selectAll = new JButton("Select All"), c);
|
||||
c.gridx++;
|
||||
centralEastPanel.add(clearAll = new JButton("Clear All"), c);
|
||||
c.ipady = 0;
|
||||
c.insets.bottom = c.insets.top = c.insets.left = c.insets.right = 0;
|
||||
centralEastPanel.add(selectAll = new JButton("All"), c);
|
||||
c.gridy++;
|
||||
centralEastPanel.add(clearAll = new JButton("None"), c);
|
||||
selectAll.setBorder(new EmptyBorder(3,3,2,3));
|
||||
clearAll.setBorder(new EmptyBorder(3,3,2,3));
|
||||
selectAll.addActionListener(new AutoSelect(true));
|
||||
clearAll.addActionListener(new AutoSelect(false));
|
||||
centralOuterPanel.add(BorderLayout.SOUTH, new PamAlignmentPanel(centralEastPanel, BorderLayout.WEST));
|
||||
centralOuterPanel.add(BorderLayout.EAST, new PamAlignmentPanel(centralEastPanel, BorderLayout.NORTH));
|
||||
|
||||
centralOuterPanel.setToolTipText(mainTip);
|
||||
|
||||
this.add(andOrBox = new JComboBox<>());
|
||||
andOrBox.setToolTipText("Select how to logically combine the click and event selections");
|
||||
andOrBox.addItem("AND");
|
||||
andOrBox.addItem("OR");
|
||||
JPanel emptyPanel = new JPanel();
|
||||
emptyPanel.setPreferredSize(new Dimension(10, 5));
|
||||
this.add(emptyPanel);
|
||||
|
||||
setToolTipText(mainTip);
|
||||
}
|
||||
|
||||
@ -254,6 +284,7 @@ public class ClickSelectPanel implements PamDialogPanel {
|
||||
}
|
||||
}
|
||||
useEchoes.setSelected(clickAlarmParameters.useEchoes);
|
||||
minAmplitude.setText(String.format("%3.1f", clickAlarmParameters.minimumAmplitude));
|
||||
minICI.setText(String.format("%d", clickAlarmParameters.minICIMillis));
|
||||
scoreByAmplitude.setSelected(clickAlarmParameters.scoreByAmplitude);
|
||||
allWeight.setText(String.format("%3.1f", clickAlarmParameters.getSpeciesWeight(0)));
|
||||
@ -279,6 +310,12 @@ public class ClickSelectPanel implements PamDialogPanel {
|
||||
|
||||
ClickAlarmParameters clickAlarmParameters = clickDataSelector.getClickAlarmParameters().clone();
|
||||
clickAlarmParameters.useEchoes = useEchoes.isSelected();
|
||||
try {
|
||||
clickAlarmParameters.minimumAmplitude = Double.valueOf(minAmplitude.getText());
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return PamDialog.showWarning(null, "Minimum amplitude", "Invalid minimum amplitude value");
|
||||
}
|
||||
try {
|
||||
clickAlarmParameters.minICIMillis = Integer.valueOf(minICI.getText());
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import PamView.dialog.warn.WarnOnce;
|
||||
import clickDetector.BTDisplayParameters;
|
||||
import clickDetector.ClickControl;
|
||||
import clickDetector.ClickClassifiers.ClickIdentifier;
|
||||
import clickDetector.alarm.ClickAlarmParameters;
|
||||
|
||||
/**
|
||||
* Dialog for basic click display parameters
|
||||
@ -57,6 +58,8 @@ public class ClickDisplayDialog extends PamDialog implements ActionListener {
|
||||
private SizePanel sizePanel;
|
||||
private SpeciesPanel speciesPanel;
|
||||
private JComboBox<String> angleTypes;
|
||||
|
||||
private ClickAlarmParameters clickSelectParams;
|
||||
|
||||
private ClickDisplayDialog(Window owner) {
|
||||
|
||||
@ -86,12 +89,13 @@ public class ClickDisplayDialog extends PamDialog implements ActionListener {
|
||||
|
||||
}
|
||||
|
||||
public static BTDisplayParameters showDialog(ClickControl clickControl, Window parentFrame, BTDisplayParameters btDisplayParameters) {
|
||||
public static BTDisplayParameters showDialog(ClickControl clickControl, Window parentFrame, BTDisplayParameters btDisplayParameters, ClickAlarmParameters clickSelectParams) {
|
||||
if (singleInstance == null || singleInstance.getOwner() != parentFrame) {
|
||||
singleInstance = new ClickDisplayDialog(parentFrame);
|
||||
}
|
||||
singleInstance.clickControl = clickControl;
|
||||
singleInstance.btDisplayParameters = btDisplayParameters.clone();
|
||||
singleInstance.clickSelectParams = clickSelectParams;
|
||||
singleInstance.setParams(btDisplayParameters);
|
||||
singleInstance.setVisible(true);
|
||||
return singleInstance.btDisplayParameters;
|
||||
@ -514,14 +518,16 @@ public class ClickDisplayDialog extends PamDialog implements ActionListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
showEchoes.setSelected(btDisplayParameters.showEchoes);
|
||||
showEchoes.setSelected(clickSelectParams.useEchoes);
|
||||
if (species == null) {
|
||||
showAll.setSelected(true);
|
||||
}
|
||||
else {
|
||||
showAll.setSelected(btDisplayParameters.getShowSpecies(0));
|
||||
// showAll.setSelected(btDisplayParameters.getShowSpecies(0));
|
||||
showAll.setSelected(clickSelectParams.getUseSpecies(0));
|
||||
for (int i = 0; i < species.length; i++) {
|
||||
species[i].setSelected(btDisplayParameters.getShowSpecies(i+1));
|
||||
species[i].setSelected(clickSelectParams.getUseSpecies(i+1));
|
||||
// species[i].setSelected(btDisplayParameters.getShowSpecies(i+1));
|
||||
}
|
||||
// if (btDisplayParameters.showSpeciesList != null) {
|
||||
// for (int i = 0; i < Math.min(species.length, btDisplayParameters.showSpeciesList.length);i++) {
|
||||
@ -529,9 +535,10 @@ public class ClickDisplayDialog extends PamDialog implements ActionListener {
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
clicksInAnEvent.setSelected(btDisplayParameters.showEventsOnly);
|
||||
andOrSelection.setSelectedIndex(btDisplayParameters.showANDEvents ? 0: 1);
|
||||
clicksInAnEvent.setSelected(clickSelectParams.onlineAutoEvents | clickSelectParams.onlineAutoEvents);
|
||||
|
||||
// clicksInAnEvent.setSelected(btDisplayParameters.showEventsOnly);
|
||||
// andOrSelection.setSelectedIndex(btDisplayParameters.showANDEvents ? 0: 1);
|
||||
// orEvents.setSelected(!btDisplayParameters.showANDEvents);
|
||||
// andEvents.setSelected(btDisplayParameters.showANDEvents);
|
||||
// anyEvents.setSelected(!btDisplayParameters.showEventsOnly);
|
||||
@ -540,19 +547,17 @@ public class ClickDisplayDialog extends PamDialog implements ActionListener {
|
||||
enableButtons();
|
||||
}
|
||||
boolean getParams() {
|
||||
btDisplayParameters.showEchoes = showEchoes.isSelected();
|
||||
btDisplayParameters.setShowSpecies(0, showAll.isSelected());
|
||||
if (species != null) {
|
||||
for (int i = 0; i < species.length; i++) {
|
||||
btDisplayParameters.setShowSpecies(i+1, species[i].isSelected());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
btDisplayParameters.showEventsOnly = clicksInAnEvent.isSelected();
|
||||
btDisplayParameters.showANDEvents = (andOrSelection.getSelectedIndex() == 0);
|
||||
// btDisplayParameters.showANDEvents = andEvents.isSelected();
|
||||
// btDisplayParameters.showEventsOnly = onlyEvents.isSelected();
|
||||
// clickSelectParams.useEchoes = showEchoes.isSelected();
|
||||
// btDisplayParameters.setShowSpecies(0, showAll.isSelected());
|
||||
// if (species != null) {
|
||||
// for (int i = 0; i < species.length; i++) {
|
||||
// btDisplayParameters.setShowSpecies(i+1, species[i].isSelected());
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// btDisplayParameters.showEventsOnly = clicksInAnEvent.isSelected();
|
||||
// btDisplayParameters.showANDEvents = (andOrSelection.getSelectedIndex() == 0);
|
||||
return true;
|
||||
}
|
||||
class AllSpeciesListener implements ActionListener {
|
||||
|
@ -31,12 +31,15 @@ import clickDetector.ClickBTDisplay;
|
||||
import clickDetector.ClickControl;
|
||||
import clickDetector.ClickDisplay;
|
||||
import clickDetector.ClickClassifiers.ClickIdentifier;
|
||||
import clickDetector.alarm.ClickAlarmParameters;
|
||||
import clickDetector.dataSelector.ClickDataSelector;
|
||||
import PamView.PamToolBar;
|
||||
import PamView.component.PamSettingsIconButton;
|
||||
import PamView.dialog.PamCheckBox;
|
||||
import PamView.dialog.PamLabel;
|
||||
import PamView.dialog.PamRadioButton;
|
||||
import PamView.panel.PamPanel;
|
||||
import PamguardMVC.dataSelector.DataSelectParams;
|
||||
|
||||
public class OfflineToolbar {
|
||||
|
||||
@ -252,19 +255,29 @@ public class OfflineToolbar {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ClickDataSelector clickDataSelector = currentBTDisplay.getClickDataSelector();
|
||||
ClickAlarmParameters selectParams = clickDataSelector.getParams();
|
||||
BTDisplayParameters btDisplayParameters = currentBTDisplay.getBtDisplayParameters();
|
||||
btDisplayParameters.setShowSpecies(0, showNonSpecies.isSelected());
|
||||
btDisplayParameters.showEchoes = showEchoes.isSelected();
|
||||
|
||||
selectParams.setUseSpecies(0, showNonSpecies.isSelected());
|
||||
// btDisplayParameters.setShowSpecies(0, showNonSpecies.isSelected());
|
||||
// btDisplayParameters.showEchoes = showEchoes.isSelected();
|
||||
selectParams.useEchoes = showEchoes.isSelected();
|
||||
|
||||
if (clicksInAnEvent != null) {
|
||||
btDisplayParameters.showEventsOnly = clicksInAnEvent.isSelected();
|
||||
// btDisplayParameters.showEventsOnly = clicksInAnEvent.isSelected();
|
||||
// selectParams.onlineAutoEvents = selectParams.onlineManualEvents = true;
|
||||
selectParams.unassignedEvents =clicksInAnEvent.isSelected() == false;
|
||||
}
|
||||
if (andOrSelection != null) {
|
||||
btDisplayParameters.showANDEvents = (andOrSelection.getSelectedIndex() == 0);
|
||||
selectParams.setClicksANDEvents(andOrSelection.getSelectedIndex() == 0);
|
||||
// btDisplayParameters.showANDEvents = (andOrSelection.getSelectedIndex() == 0);
|
||||
}
|
||||
if (speciesButtons != null) {
|
||||
int n = speciesButtons.length;
|
||||
for (int i = 0; i < n; i++) {
|
||||
btDisplayParameters.setShowSpecies(i+1, speciesButtons[i].isSelected());
|
||||
selectParams.setUseSpecies(i+1, speciesButtons[i].isSelected());
|
||||
// btDisplayParameters.setShowSpecies(i+1, speciesButtons[i].isSelected());
|
||||
}
|
||||
}
|
||||
currentBTDisplay.repaintTotal();
|
||||
@ -275,23 +288,35 @@ public class OfflineToolbar {
|
||||
}
|
||||
|
||||
private void checkButtons(BTDisplayParameters btDisplayParameters) {
|
||||
showEchoes.setSelected(btDisplayParameters.showEchoes);
|
||||
showNonSpecies.setSelected(btDisplayParameters.getShowSpecies(0));
|
||||
ClickDataSelector clickDataSelector = currentBTDisplay.getClickDataSelector();
|
||||
ClickAlarmParameters selectParams = clickDataSelector.getParams();
|
||||
showEchoes.setSelected(selectParams.useEchoes);
|
||||
showNonSpecies.setSelected(selectParams.getUseSpecies(0));
|
||||
// showNonSpecies.setSelected(btDisplayParameters.getShowSpecies(0));
|
||||
boolean anySel = false;;
|
||||
if (clicksInAnEvent != null) {
|
||||
clicksInAnEvent.setSelected(btDisplayParameters.showEventsOnly);
|
||||
clicksInAnEvent.setSelected(selectParams.unassignedEvents == false);
|
||||
anySel |= clicksInAnEvent.isSelected();
|
||||
// clicksInAnEvent.setSelected(btDisplayParameters.showEventsOnly);
|
||||
}
|
||||
if (speciesButtons != null) {
|
||||
int n = speciesButtons.length;
|
||||
for (int i = 0; i < n; i++) {
|
||||
speciesButtons[i].setSelected(btDisplayParameters.getShowSpecies(i+1));
|
||||
speciesButtons[i].setSelected(selectParams.getUseSpecies(i+1));
|
||||
anySel |= speciesButtons[i].isSelected();
|
||||
// speciesButtons[i].setSelected(btDisplayParameters.getShowSpecies(i+1));
|
||||
}
|
||||
}
|
||||
// setting combo box fires actionlistener, so we have to make sure that all checkboxes have been properly set first
|
||||
// or else they will get cleared later
|
||||
if (andOrSelection != null) {
|
||||
andOrSelection.setSelectedIndex(btDisplayParameters.showANDEvents ? 0: 1);
|
||||
andOrSelection.setSelectedIndex(selectParams.isClicksANDEvents() ? 0 : 1);
|
||||
// andOrSelection.setSelectedIndex(btDisplayParameters.showANDEvents ? 0: 1);
|
||||
}
|
||||
firstSetup = true;
|
||||
if (anySel) {
|
||||
selectParams.setCombinationFlag(DataSelectParams.DATA_SELECT_AND);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,13 @@
|
||||
package clickDetector.tdPlots;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
import PamView.GeneralProjector;
|
||||
import PamView.PamSymbol;
|
||||
import PamView.dialog.PamDialogPanel;
|
||||
import PamView.symbol.PamSymbolChooser;
|
||||
import PamView.symbol.SymbolData;
|
||||
import PamView.symbol.modifier.SymbolModType;
|
||||
@ -32,4 +38,41 @@ public class ClickClassSymbolModifier extends SymbolModifier {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PamDialogPanel getDialogPanel() {
|
||||
// Just a play to check buttons and menus work. Not actually used at all so revert to super: returns null.
|
||||
return super.getDialogPanel();
|
||||
// return new DumyPanel();
|
||||
}
|
||||
|
||||
private class DumyPanel implements PamDialogPanel {
|
||||
|
||||
private JPanel mainPanel;
|
||||
public DumyPanel() {
|
||||
super();
|
||||
mainPanel = new JPanel();
|
||||
mainPanel.setBorder(new TitledBorder("More options"));
|
||||
mainPanel.add(new JCheckBox("Dummy option"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getDialogComponent() {
|
||||
// TODO Auto-generated method stub
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParams() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getParams() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,8 @@ import clickDetector.BTDisplayParameters;
|
||||
import clickDetector.ClickControl;
|
||||
import clickDetector.ClickDetection;
|
||||
import clickDetector.ClickDisplayManagerParameters;
|
||||
import clickDetector.alarm.ClickAlarmParameters;
|
||||
import clickDetector.dataSelector.ClickDataSelector;
|
||||
import clickDetector.dialogs.ClickDisplayDialog;
|
||||
import PamView.GeneralProjector.ParameterType;
|
||||
import PamView.GeneralProjector.ParameterUnits;
|
||||
@ -52,6 +54,10 @@ public class ClickPlotInfo extends TDDataInfo {
|
||||
allScaleInfo[3] = slantScaleInfo;
|
||||
clickHidingDialog = new ClickHidingDialog(this);
|
||||
}
|
||||
|
||||
ClickDataSelector getDataSelector() {
|
||||
return (ClickDataSelector) clickControl.getClickDataBlock().getDataSelector("ClickTDPlots", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getDataValue(PamDataUnit pamDataUnit) {
|
||||
@ -110,7 +116,8 @@ public class ClickPlotInfo extends TDDataInfo {
|
||||
private synchronized boolean shouldPlot(ClickDetection click) {
|
||||
|
||||
if (click == null) return false;
|
||||
if (btDisplayParams.showEchoes == false && click.isEcho()) {
|
||||
boolean showEchoes = getDataSelector().getClickAlarmParameters().useEchoes;
|
||||
if (showEchoes == false && click.isEcho()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -170,7 +177,7 @@ public class ClickPlotInfo extends TDDataInfo {
|
||||
*/
|
||||
@Override
|
||||
public boolean editOptions(Window frame) {
|
||||
BTDisplayParameters newParams = ClickDisplayDialog.showDialog(clickControl, frame, btDisplayParams);
|
||||
BTDisplayParameters newParams = ClickDisplayDialog.showDialog(clickControl, frame, btDisplayParams, getDataSelector().getClickAlarmParameters());
|
||||
if (newParams != null) {
|
||||
btDisplayParams = newParams.clone();
|
||||
updateSettings();
|
||||
|
@ -140,10 +140,13 @@ public class ClipProcess extends SpectrogramMarkProcess {
|
||||
clipErr = clipRequest.clipBlockProcess.processClipRequest(clipRequest);
|
||||
switch (clipErr) {
|
||||
case 0: // no error - clip should have been created.
|
||||
li.remove();
|
||||
break;
|
||||
case RawDataUnavailableException.DATA_ALREADY_DISCARDED:
|
||||
case RawDataUnavailableException.INVALID_CHANNEL_LIST:
|
||||
// System.out.println("Clip error : " + clipErr);
|
||||
// System.out.println("Clip error : " + clipErr);
|
||||
li.remove();
|
||||
break;
|
||||
case RawDataUnavailableException.DATA_NOT_ARRIVED:
|
||||
continue; // hopefully, will get this next time !
|
||||
}
|
||||
@ -230,6 +233,17 @@ public class ClipProcess extends SpectrogramMarkProcess {
|
||||
}
|
||||
minH = Math.max(minH, clipBlockProcesses[i].getRequiredDataHistory(o, arg));
|
||||
}
|
||||
|
||||
ClipRequest firstClip = null;
|
||||
synchronized(clipRequestSynch) {
|
||||
if (clipRequestQueue.size() > 0) {
|
||||
firstClip = clipRequestQueue.get(0);
|
||||
}
|
||||
}
|
||||
if (firstClip != null) {
|
||||
minH += firstClip.dataUnit.getDurationInMilliseconds();
|
||||
}
|
||||
|
||||
minH += Math.max(3000, 192000/(long)getSampleRate());
|
||||
if (specMouseDown) {
|
||||
minH = Math.max(minH, masterClockTime-specMouseDowntime);
|
||||
@ -453,8 +467,7 @@ public class ClipProcess extends SpectrogramMarkProcess {
|
||||
this.dataBlock = dataBlock;
|
||||
this.clipGenSetting = clipGenSetting;
|
||||
clipBudgetMaker = new StandardClipBudgetMaker(this);
|
||||
dataBlock.addObserver(this, true);
|
||||
|
||||
dataBlock.addObserver(this, false);
|
||||
|
||||
if (rawDataBlock != null) {
|
||||
int chanMap = decideChannelMap(rawDataBlock.getChannelMap());
|
||||
@ -499,6 +512,7 @@ public class ClipProcess extends SpectrogramMarkProcess {
|
||||
rawData = rawDataBlock.getSamples(rawStart, (int) (rawEnd-rawStart), channelMap);
|
||||
}
|
||||
catch (RawDataUnavailableException e) {
|
||||
System.out.println(e.getMessage());
|
||||
return e.getDataCause();
|
||||
}
|
||||
if (rawData==null) {
|
||||
@ -583,9 +597,15 @@ public class ClipProcess extends SpectrogramMarkProcess {
|
||||
public PamObserver getObserverObject() {
|
||||
return clipProcess.getObserverObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRequiredDataHistory(PamObservable o, Object arg) {
|
||||
return (long) ((clipGenSetting.preSeconds+clipGenSetting.postSeconds) * 1000.);
|
||||
long h = (long) ((clipGenSetting.preSeconds+clipGenSetting.postSeconds) * 1000.);
|
||||
// if (dataBlock != null) {
|
||||
// can't do this since dataBlock is observing this, so will wrap.
|
||||
// h += dataBlock.getRequiredHistory();
|
||||
// }
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
|
@ -269,7 +269,10 @@ public class DataStreamPaneFX extends PamBorderPane {
|
||||
});
|
||||
|
||||
canvasHolder.setOnScroll(e->{
|
||||
wheelMoved(e);
|
||||
//only change colours of the control key is down.
|
||||
if (e.isControlDown()) {
|
||||
wheelMoved(e);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import pamViewFX.fxNodes.PamColorsFX;
|
||||
import pamViewFX.fxNodes.PamScrollPane;
|
||||
import pamViewFX.fxNodes.PamVBox;
|
||||
import pamViewFX.fxNodes.pamAxis.PamDateAxis;
|
||||
import pamViewFX.fxNodes.pamScrollers.acousticScroller.ScrollBarPane;
|
||||
|
||||
public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
|
||||
@ -77,7 +78,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
/**
|
||||
* Scroll bar for time (horizontal)
|
||||
*/
|
||||
private ScrollBar timeScrollBar;
|
||||
private ScrollBarPane timeScrollBar;
|
||||
|
||||
/**
|
||||
* Settings strip at top of the display. Shows all sorts of detailed info such cursor position and start and end times.
|
||||
@ -145,7 +146,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
// //////////
|
||||
|
||||
holder.setCenter(mainScrollPane);
|
||||
holder.setBottom(createScrollBar());
|
||||
holder.setTop(createScrollBar());
|
||||
|
||||
// PamButton test = new PamButton("Test");
|
||||
// test.setOnAction((action)->{
|
||||
@ -208,13 +209,15 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
|
||||
|
||||
//create the scroll bar and listeners.
|
||||
timeScrollBar=new ScrollBar();
|
||||
timeScrollBar.valueProperty().addListener((obs_val, old_val, new_val)->{
|
||||
timeScrollBar=new ScrollBarPane();
|
||||
timeScrollBar.addValueListener((obs_val, old_val, new_val)->{
|
||||
calcStartEndMillis();
|
||||
updateScrollBarText();
|
||||
notifyScrollChange();
|
||||
});
|
||||
|
||||
|
||||
|
||||
timeScrollBar.setPrefHeight(20);
|
||||
|
||||
holder.setCenter(timeScrollBar);
|
||||
@ -228,7 +231,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
*/
|
||||
private void calcStartEndMillis(){
|
||||
screenStartMillis = (long) (dataMapControl.getFirstTime() +
|
||||
timeScrollBar.getValue() * 1000L);
|
||||
timeScrollBar.getCurrentValue() * 1000L);
|
||||
screenEndMillis = screenStartMillis + (long) (screenSeconds * 1000);
|
||||
}
|
||||
|
||||
@ -347,7 +350,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
* Do scrolling in seconds - will give up to 68 years with a
|
||||
* 32 bit integer control of scroll bar. milliseconds would give < 1 year !
|
||||
*/
|
||||
double currentPos = timeScrollBar.getValue();
|
||||
double currentPos = timeScrollBar.getCurrentValue();
|
||||
long dataStart = dataMapControl.getFirstTime();
|
||||
long dataEnd = dataMapControl.getLastTime();
|
||||
double dataSeconds = ((dataEnd-dataStart)/1000) + 1;
|
||||
@ -367,12 +370,12 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
else {
|
||||
//System.out.println("dataSeconds: "+dataSeconds+ " pixsPerHour: " +pixsPerHour+" screenWidth: "+screenWidth+" screenSeconds "+screenSeconds+" holder width: "+holder.getWidth());
|
||||
timeScrollBar.setVisible(true);
|
||||
timeScrollBar.setMax(0);
|
||||
timeScrollBar.setMax(Math.ceil(dataSeconds));
|
||||
timeScrollBar.setMinVal(0);
|
||||
timeScrollBar.setMaxVal(Math.ceil(dataSeconds));
|
||||
timeScrollBar.setBlockIncrement(Math.max(1, screenSeconds * 4/5));
|
||||
timeScrollBar.setUnitIncrement(Math.max(1, screenSeconds / 20));
|
||||
// timeScrollBar.setUnitIncrement(Math.max(1, screenSeconds / 20));
|
||||
timeScrollBar.setVisibleAmount(screenSeconds);
|
||||
timeScrollBar.setValue(currentPos);
|
||||
timeScrollBar.setCurrentValue(currentPos);
|
||||
}
|
||||
|
||||
}
|
||||
@ -394,7 +397,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
public void scrollToData(PamDataBlock dataBlock) {
|
||||
long startTime = dataBlock.getCurrentViewDataStart();
|
||||
int val = (int) ((startTime - getScreenStartMillis())/1000 - getScreenSeconds()/5) ;
|
||||
timeScrollBar.setValue(val);
|
||||
timeScrollBar.setCurrentValue(val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,6 +79,18 @@ public class TDGraphParametersFX implements Serializable, Cloneable, ManagedPara
|
||||
* Used only when saving as Color (javafx) is not serializable.
|
||||
*/
|
||||
public String plotFillS = "white";
|
||||
|
||||
/**
|
||||
* Show the hide panel on the left on start up. Note only used when first opening
|
||||
* saved settings or saving settings.
|
||||
*/
|
||||
public boolean showHidePaneLeft = true;
|
||||
|
||||
/**
|
||||
* Show the hide panel on the right on start up. Note only used when first opening
|
||||
* saved settings or saving settings.
|
||||
*/
|
||||
public boolean showHidePaneRight = false;
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -350,8 +350,8 @@ public class TDGraphFX extends PamBorderPane {
|
||||
setOverlayColour(LIGHT_TD_DISPLAY);
|
||||
|
||||
|
||||
//show the left hiding pane byu default.
|
||||
stackPane.getLeftHidingPane().showHidePane(true);
|
||||
// //show the left hiding pane byu default.
|
||||
// stackPane.getLeftHidingPane().showHidePane(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1699,8 +1699,7 @@ public class TDGraphFX extends PamBorderPane {
|
||||
|
||||
/**
|
||||
* A bit different to the standard getter in that this only gets called just
|
||||
* before the configuration is serialized into the .psf. It's time to pull any
|
||||
* configuration information out about every line drawn on this boomin' thing !
|
||||
* before the configuration is serialized into the .psfx.
|
||||
*
|
||||
* @return graph parameters ready to serialised.
|
||||
*/
|
||||
@ -1733,6 +1732,11 @@ public class TDGraphFX extends PamBorderPane {
|
||||
graphParameters.setScaleInfoData(scaleInfo.getDataTypeInfo(), scaleInfo.getScaleInfoData());
|
||||
}
|
||||
}
|
||||
|
||||
//Finally save whether the hiding panels are open or not.
|
||||
graphParameters.showHidePaneLeft = stackPane.getLeftHidingPane().isShowing();
|
||||
graphParameters.showHidePaneRight = stackPane.getRightHidingPane().isShowing();
|
||||
|
||||
}
|
||||
|
||||
return graphParameters;
|
||||
@ -1816,6 +1820,11 @@ public class TDGraphFX extends PamBorderPane {
|
||||
tdAxisSelPane.remakePane();
|
||||
tdAxisSelPane.selectAxisType();
|
||||
setAxisName(graphParameters.currentDataType);
|
||||
|
||||
//Open hide panes if needed.
|
||||
//Finally save whether the hiding panels are open or not.
|
||||
stackPane.getLeftHidingPane().showHidePane(graphParameters.showHidePaneLeft);
|
||||
stackPane.getRightHidingPane().showHidePane(graphParameters.showHidePaneRight);
|
||||
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package dataPlotsFX.rawClipDataPlot;
|
||||
|
||||
|
||||
import java.awt.geom.Path2D;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
@ -14,7 +15,7 @@ import PamguardMVC.PamDataUnit;
|
||||
import PamguardMVC.RawDataHolder;
|
||||
import clipgenerator.ClipSpectrogram;
|
||||
import dataPlotsFX.TDSymbolChooserFX;
|
||||
import dataPlotsFX.clickPlotFX.ClickSymbolChooserFX;
|
||||
import dataPlotsFX.clickPlotFX.ClickDisplayParams;
|
||||
import dataPlotsFX.data.TDDataProviderFX;
|
||||
import dataPlotsFX.data.TDScaleInfo;
|
||||
import dataPlotsFX.data.generic.GenericDataPlotInfo;
|
||||
@ -255,6 +256,36 @@ public class RawClipDataInfo extends GenericDataPlotInfo {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see dataPlots.data.TDDataInfo#getStoredSettings()
|
||||
*/
|
||||
@Override
|
||||
public Serializable getStoredSettings() {
|
||||
return rawClipParams;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see dataPlots.data.TDDataInfo#setStoredSettings(java.io.Serializable)
|
||||
*/
|
||||
@Override
|
||||
public boolean setStoredSettings(Serializable storedSettings) {
|
||||
if (RawClipParams.class.isAssignableFrom(storedSettings.getClass())) {
|
||||
rawClipParams = (RawClipParams) storedSettings;
|
||||
updateSettings();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever settings are updated.
|
||||
*/
|
||||
private void updateSettings() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -382,7 +382,7 @@ public class RawSoundPlotDataFX {
|
||||
|
||||
if (soundStore.currentRawDataMillis==0){
|
||||
if (++timeErrors < 10) {
|
||||
System.err.println("RawSoundPlotData: Raw sound data has no associated millisecond time: "+ soundStore.currentRawDataMillis);
|
||||
// System.err.println("RawSoundPlotData: Raw sound data has no associated millisecond time: "+ soundStore.currentRawDataMillis);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 522 KiB After Width: | Height: | Size: 164 KiB |
Before Width: | Height: | Size: 547 KiB After Width: | Height: | Size: 178 KiB |
Before Width: | Height: | Size: 396 KiB After Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 525 KiB After Width: | Height: | Size: 221 KiB |
After Width: | Height: | Size: 81 KiB |
@ -9,8 +9,14 @@
|
||||
<body>
|
||||
<h1 id="pamguard-s-deep-learning-module">PAMGuard's Deep
|
||||
Learning Module</h1>
|
||||
<h2 id="common-bugs-and-mistakes">Common Bugs and Mistakes</h2>
|
||||
<br>
|
||||
|
||||
<h2 id="common-bugs-and-mistakes">Common bugs and mistakes</h2>
|
||||
<p>The first time you use the module and/or load a different type
|
||||
of model e.g. a tensorflow or pytorch model, you must be connected to
|
||||
the internet.</p>
|
||||
<p>You must install the correct version of CUDA for hardware
|
||||
acceleration using an Nvidea GPU. See the currently supported CUDA
|
||||
versions on the Pytorch and Tensorflow websites.</p>
|
||||
<p>You should always have deep learning models in their own folder.
|
||||
Do not have any additional jar files or other programming related
|
||||
things (like .dll files) in the same or sub folders. This has been
|
||||
|
@ -7,20 +7,18 @@
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="pamguard-s-deep-learning-module">PAMGuard Deep
|
||||
Learning Module</h1>
|
||||
<h2 id="creation-and-config">Creation and Configuration</h2>
|
||||
<br>
|
||||
<h3 id="creating-an-instance-of-the-module">Creating an instance
|
||||
of the module</h3>
|
||||
<h1 id="pamguard-s-deep-learning-module">PAMGuard Deep Learning
|
||||
Module</h1>
|
||||
|
||||
<h2 id="creating-an-instance-of-the-module">Creating an instance
|
||||
of the module</h2>
|
||||
<p>
|
||||
The module can be added from the <em>File> Add modules >
|
||||
Classifier > Raw deep learning classifier</em> menu or by right
|
||||
clicking in the data model. More than one instance of the module can
|
||||
be added if multiple deep learning models are required.
|
||||
</p>
|
||||
<br>
|
||||
<h3 id="module-settings">Module settings</h3>
|
||||
<h2 id="module-settings">Module settings</h2>
|
||||
<p>
|
||||
The module settings are opened by selecting the <em>Settings >
|
||||
Raw deep learning classifier</em> menu. The main settings pane is shown
|
||||
@ -28,18 +26,18 @@
|
||||
and <em>Deep Learning Model</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<img width="700" height="630"
|
||||
src="images/deep_leanring_module_help.png">
|
||||
<img src="images/deep_leanring_module_help.png">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<em>The main settings pane for the deep learning module with
|
||||
descriptions</em>
|
||||
</p>
|
||||
<br>
|
||||
<h3 id="raw-sound-data">Raw Sound Data</h3>
|
||||
<p>The deep learning module accepts any raw data source i.e., any
|
||||
data source that contains raw waveform data.</p>
|
||||
data source that contains raw waveform data e.g. clicks, clips and
|
||||
Ishmael detections. Note that the module accepts whislte and moan
|
||||
detections but only if a delphinID classifier has been loaded.</p>
|
||||
<p>If the data is continuous, e.g. from the Sound Acquisition
|
||||
module then deep learning detections are saved to PAMGuard's data
|
||||
management system if they pass a user defined prediction threshold.
|
||||
@ -57,7 +55,6 @@
|
||||
processes. So, for example if channels 0 and 2 are in a group, then
|
||||
the raw waveform data from both channel 0 and 2 will be saved and can
|
||||
be used in downstream processes, e.g., for localisation.</p>
|
||||
<br>
|
||||
<h3 id="segmentation">Segmentation</h3>
|
||||
<p>
|
||||
The segmentation section defines how the raw data is segmented. Some
|
||||
@ -72,7 +69,6 @@
|
||||
re-merge</em> is the maximum number of segments that can form a single
|
||||
data unit before a new data unit is automatically created.
|
||||
</p>
|
||||
<br>
|
||||
<h3 id="deep-learning-model">Deep Learning Model</h3>
|
||||
<p>The deep learning model section is used to select the deep
|
||||
learning model. The drop down menu is used to select the framework the
|
||||
@ -92,14 +88,12 @@
|
||||
</p>
|
||||
<p>Once the model has loaded there some unique options depending on
|
||||
the currently selected framework.</p>
|
||||
<br>
|
||||
<h4 id="generic-model">Generic Model</h4>
|
||||
<p>
|
||||
A generic model must be set up via the <em>Advanced</em> menu button.
|
||||
</p>
|
||||
<p align="center">
|
||||
<img width="700" height="700"
|
||||
src="images/advanced_settings_generic_1.png">
|
||||
<img src="images/advanced_settings_generic_1.png">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -124,8 +118,7 @@
|
||||
including the shape of the input data e.g. a 100x50 image.
|
||||
</p>
|
||||
<p align="center">
|
||||
<img width="700" height="700"
|
||||
src="images/advanced_settings_generic_2.png">
|
||||
<img src="images/advanced_settings_generic_2.png">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -146,16 +139,15 @@
|
||||
transforms and input and output data whenever settings up a new
|
||||
PAMGuard data model and allow easier sharing of classifiers amongst
|
||||
researchers.</p>
|
||||
<br>
|
||||
<h4 id="animalspot-and-ketos-models">AnimalSpot and Ketos models</h4>
|
||||
<h4 id="koogu-ketos-animalspot-pamguard-zip-and-delphinid-models">Koogu,
|
||||
Ketos, AnimalSpot, PAMGuard zip and delphinID models</h4>
|
||||
<p>
|
||||
If using an AnimalSpot or Ketos model then all transforms are
|
||||
automatically set up. The transforms can be viewed and altered via the
|
||||
Advanced menu button but in the majority of cases these settings
|
||||
should not be used. It is advisable to select "Use default
|
||||
segment length" to change the <em>Window length</em> to the
|
||||
default for the selected model. Note that this is often necessary for
|
||||
Ketos models but usually not a requirement for AnimalSpot models.
|
||||
If using a deep learning model from a supported framework then all
|
||||
transforms are automatically set up. The transforms can be viewed and
|
||||
altered via the Advanced menu button but in the majority of cases
|
||||
these settings should not be used. For some models, it is advisable to
|
||||
select "Use default segment length" to change the <em>Window
|
||||
length</em> to the default for the selected model.
|
||||
</p>
|
||||
<p align="center">
|
||||
<img width="700" height="700"
|
||||
@ -163,18 +155,43 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<em>An AnimalSpot or Ketos model will automatically create a list
|
||||
of transforms with the appropriate settings. These is no need to use
|
||||
the advanced pane but it is there in case users wish to change
|
||||
transform settings for some reason</em>
|
||||
<em>An AnimalSpot, Ketos or other supported deep learning model
|
||||
will automatically create a list of transforms with the appropriate
|
||||
settings. These is no need to use the advanced pane but it is there
|
||||
in case users wish to change transform settings for some reason</em>
|
||||
</p>
|
||||
<h3 id="default-models">Default Models</h3>
|
||||
<p>Default models are selectable from the menu button in the Deep
|
||||
Learning Pane. Default models are deep learning classifiers which are
|
||||
open source, known to be effective and have have been published in
|
||||
open access academic litrature; they are downloaded directly from a
|
||||
GitHub repository and then all associated settings are automtically
|
||||
applied. The default model selection pane also contains hyperlinks to
|
||||
the papers descirbing each model which will take users directly to the
|
||||
relvent website.</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="images/default_settings_humpback_1.png">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<em>Default models can be downloaded. Default models are models
|
||||
which are published, open and have been known to work well amongst
|
||||
the bioacoustics community. More will be added to PAMGaurd over time.
|
||||
If you you would like your model to become a defualt model then drop
|
||||
PAMGuard support an email.</em>
|
||||
</p>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<p class="prevLink"><a href="rawDeepLearning_overview.html">Previous:
|
||||
Overview</a></p>
|
||||
<p class="nextLink"><a href="rawDeepLearning_Running.html">Next:
|
||||
Running the Deep Learning module</a></p>
|
||||
<p class="prevLink">
|
||||
<a href="rawDeepLearning_overview.html">Previous: Overview</a>
|
||||
</p>
|
||||
<p class="nextLink">
|
||||
<a href="rawDeepLearning_Running.html">Next: Running the Deep
|
||||
Learning module</a>
|
||||
</p>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
|
@ -9,12 +9,12 @@
|
||||
<body>
|
||||
<h1 id="pamguard-s-deep-learning-module">PAMGuard's Deep
|
||||
Learning Module</h1>
|
||||
|
||||
|
||||
<h2 id="viewing-and-exporting-results">Viewing and exporting
|
||||
results</h2>
|
||||
<br>
|
||||
<p>Output from the deep learning module can be viewed in PAMGuard
|
||||
viewer mode, or extracted from binary files using MATLAB or R.</p>
|
||||
<br>
|
||||
<h3 id="pamguard-viewer-mode">PAMGuard viewer mode</h3>
|
||||
<p>Detections form continuous raw data are shown in the datagram in
|
||||
the same way as all data streams in PAMGuard.</p>
|
||||
@ -32,7 +32,7 @@
|
||||
manual analyst can quickly navigate to detections with high prediction
|
||||
values for a certain class. Hovering over or right clicking on a data
|
||||
unit in the time display and selecting the information button, will
|
||||
show the data unit's metadata, including the prediction values for all
|
||||
show the data unit’s metadata, including the prediction values for all
|
||||
output classes from the deep learning model.</p>
|
||||
<p align="center">
|
||||
<img src="images/bat_time_base_display.png">
|
||||
@ -50,7 +50,6 @@
|
||||
deep learning prediction values. The spectrogram will also show deep
|
||||
learning detections as translucent blue boxes (these must be selected
|
||||
in the right click menu).</p>
|
||||
<br>
|
||||
<h3 id="matlab">MATLAB</h3>
|
||||
<p>The easiest way to export to MATLAB is to select the desired
|
||||
units in the time base display, right click and select the MATLAB
|
||||
@ -96,7 +95,7 @@ predicitons = dldetections(<span class="hljs-number">1</span>).annotations.dlcla
|
||||
waveform data in each structure;</p>
|
||||
<pre>
|
||||
<code class="lang-matlab">
|
||||
<span class="hljs-comment">% plot all the spectrograms.</span>
|
||||
<span class="hljs-comment">% plot all the spectrograms.</span>
|
||||
clf
|
||||
tiledlayout(<span class="hljs-number">5</span>,<span class="hljs-number">5</span>)
|
||||
<span class="hljs-keyword">for</span> <span class="hljs-built_in">i</span>=<span
|
||||
@ -155,7 +154,6 @@ tiledlayout(<span class="hljs-number">5</span>,<span class="hljs-number">5</span
|
||||
<em>Right whale detections from a deep learning model imported
|
||||
and then plotted in MATLAB</em>
|
||||
</p>
|
||||
<br>
|
||||
<h3 id="r">R</h3>
|
||||
<p>In the same way as MATLAB export, the PAMGuard time base display
|
||||
and export selected data units directly to an R struct which can be
|
||||
@ -165,13 +163,17 @@ tiledlayout(<span class="hljs-number">5</span>,<span class="hljs-number">5</span
|
||||
functions compared to the MATLAB library. The PAMBinaries R library
|
||||
can be found <a href="https://github.com/TaikiSan21/PamBinaries">here</a>.
|
||||
</p>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<p class="prevLink"><a href="rawDeepLearning_Running.html">Previous:
|
||||
Running the Deep Learning module</a></p>
|
||||
<p class="nextLink"><a href="rawDeepLearning_Bugs.html">Next:
|
||||
Common Bugs and Mistakes</a></p>
|
||||
<p class="prevLink">
|
||||
<a href="rawDeepLearning_Running.html">Previous: Running the Deep
|
||||
Learning module</a>
|
||||
</p>
|
||||
<p class="nextLink">
|
||||
<a href="rawDeepLearning_Bugs.html">Next: Common Bugs and Mistakes</a>
|
||||
</p>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
|
@ -10,12 +10,10 @@
|
||||
<h1 id="pamguard-s-deep-learning-module">PAMGuard's Deep
|
||||
Learning Module</h1>
|
||||
<h2 id="running">Running</h2>
|
||||
<br>
|
||||
<h3 id="real-time">Real time</h3>
|
||||
<p>In real time, the deep learning model runs automatically when
|
||||
processing starts. A warning will appear if there are issues with the
|
||||
model and/or it cannot cope with real time speeds.</p>
|
||||
<br>
|
||||
<h3 id="viewer-mode">Viewer Mode</h3>
|
||||
<p>
|
||||
The deep learning module can be re-run on <em>detector</em> data (e.g.
|
||||
@ -26,13 +24,18 @@
|
||||
Detections without a deep learning annotation will have one added and
|
||||
detections with an existing annotation will have it overwritten.
|
||||
</p>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<p class="prevLink"><a href="rawDeepLearning_CreateAndConfig.html">Previous:
|
||||
Creating and Configuring the Deep Learning module</a></p>
|
||||
<p class="nextLink"><a href="rawDeepLearning_Results.html">Next:
|
||||
Viewing and Exporting Results</a></p>
|
||||
<p class="prevLink">
|
||||
<a href="rawDeepLearning_CreateAndConfig.html">Previous: Creating
|
||||
and Configuring the Deep Learning module</a>
|
||||
</p>
|
||||
<p class="nextLink">
|
||||
<a href="rawDeepLearning_Results.html">Next: Viewing and Exporting
|
||||
Results</a>
|
||||
</p>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
|
@ -7,10 +7,11 @@
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="pamguard-s-deep-learning-module">PAMGuard Deep
|
||||
Learning Module</h1>
|
||||
<h1 id="pamguard-s-deep-learning-module">PAMGuard's deep
|
||||
learning module</h1>
|
||||
<p>Note: this module requires an internet connection upon first use
|
||||
to download correct libraries.</p>
|
||||
<h2 id="overview">Overview</h2>
|
||||
|
||||
<p>PAMGuard's deep learning module allows users to deploy a
|
||||
large variety of deep learning models natively in PAMGuard. It is core
|
||||
module, fully integrated into PAMGuard's display and data
|
||||
@ -19,9 +20,7 @@
|
||||
signal and can integrate into multiple types of acoustic analysis
|
||||
workflows, for example post analysis of recorder data or used as part
|
||||
of real time localisation workflow.</p>
|
||||
|
||||
<br>
|
||||
<h3 id="how-it-works">How it works</h3>
|
||||
<h2 id="how-it-works">How it works</h2>
|
||||
<p>The deep learning module accepts raw data from different types
|
||||
of data sources, e.g. from the Sound Acquisition module, clicks and
|
||||
clips. It segments data into equal sized chunks with a specified
|
||||
@ -32,8 +31,7 @@
|
||||
learning model, then can be automatically set up by PAMGuard.
|
||||
Currently there are three implemented frameworks</p>
|
||||
<p align="center">
|
||||
<img width="900" height="370"
|
||||
src="images/deep_learning_module_process.png">
|
||||
<img src="images/deep_learning_module_process.png">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -44,7 +42,6 @@
|
||||
the model are saved and can be viewed in real time (e.g. mitigation)
|
||||
or in post processing (e.g. data from SoundTraps).</em>
|
||||
</p>
|
||||
<br>
|
||||
<h3 id="generic-model">Generic Model</h3>
|
||||
<p>
|
||||
A generic model allows a user to load any model compatible with the <a
|
||||
@ -54,12 +51,11 @@
|
||||
existing framework instead of a generic model as these models will
|
||||
automatically generate the required transforms.
|
||||
</p>
|
||||
<br>
|
||||
<h3 id="animalspot">AnimalSpot</h3>
|
||||
<p>
|
||||
<a href="https://github.com/ChristianBergler/ANIMAL-SPOT">ANIMAL-SPOT</a>
|
||||
is a deep learning based framework which was initially designed for <a
|
||||
href="https://github.com/ChristianBergler/ORCA-SPOT">killer
|
||||
href="(https://github.com/ChristianBergler/ORCA-SPOT">killer
|
||||
whale sound detection</a>) in noise heavy underwater recordings (see <a
|
||||
href="https://www.nature.com/articles/s41598-019-47335-w">Bergler
|
||||
et al. (2019)</a>). It has now been expanded to a be species independent
|
||||
@ -68,21 +64,43 @@
|
||||
AnimalSpot models will automatically set up their own data transforms
|
||||
and output classes.
|
||||
</p>
|
||||
<br>
|
||||
<h3 id="ketos">Ketos</h3>
|
||||
<p>
|
||||
<a href="https://meridian.cs.dal.ca/2015/04/12/ketos/">Ketos</a> is an
|
||||
acoustic deep learning framework based on Tensorflow and developed by
|
||||
<a href="https://meridian.cs.dal.ca/">MERIDIAN</a>. It has excellent
|
||||
resources and tutorials and Python libraries can be installed easily
|
||||
via pip. Imported Ketos model will automatically set up their own data
|
||||
via pip. Imported Ketos (.ktpb) models will automatically set up their
|
||||
own data transforms and output classes.
|
||||
</p>
|
||||
<h3 id="koogu">Koogu</h3>
|
||||
<p>
|
||||
<a href="https://shyamblast.github.io/Koogu/en/stable/">Koogu </a> is
|
||||
a Python package which allows users to train a deep learning model.
|
||||
Koogu helps users by integrating with some frequency used annotation
|
||||
programs and provides tools to train and test classifiers. Imported
|
||||
Koogu models (.kgu) will automatically set up their own data
|
||||
transforms and output classes.
|
||||
</p>
|
||||
<h3 id="pamguardzip">PAMGuardZip</h3>
|
||||
<p>
|
||||
PAMGuard zip models consist of a deep learning model (either a
|
||||
Tensorflow saved_model.pb or PyTorch <em>*.py model) alongside a
|
||||
PAMGuard metdata file (</em>.pdtf*) within a zip archive. The metadata
|
||||
file contains all the information needed for PAMGaurd to set up the
|
||||
model. PAMGuard will import the zip file, decompress it and search for
|
||||
the relevent deep learning model and metadata file then set up all
|
||||
settings accordingly. This framework allows users to easily share
|
||||
pre-tested PAMGuard compatible models.
|
||||
</p>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<p class="nextLink"><a href="rawDeepLearning_CreateAndConfig.html">Next:
|
||||
Creating and Configuring the Deep Learning module</a></p>
|
||||
<p class="nextLink">
|
||||
<a href="rawDeepLearning_CreateAndConfig.html">Next: Creating and
|
||||
Configuring the Deep Learning module</a>
|
||||
</p>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
|
@ -19,6 +19,9 @@ public class SmruDaqJNI {
|
||||
static public final int SMRU_VAL_SLAVE_MASTERED = 3;
|
||||
|
||||
static public final int SMRU_RET_OK = 0;
|
||||
|
||||
static public final int GREEN_LED = 1;
|
||||
static public final int RED_LED = 0;
|
||||
|
||||
/**
|
||||
* Have rebuilt SAIL Daq interface in 2022, but in principle this was
|
||||
@ -29,11 +32,6 @@ public class SmruDaqJNI {
|
||||
private static final String SILIB = "SailDaqJNI";
|
||||
// private static final String SILIB = "SailDaqV7";
|
||||
|
||||
/**
|
||||
* this is the verbose level for the C code part.
|
||||
*/
|
||||
private static final int verboseLevel = 0;
|
||||
|
||||
private static final String DEVNAME = "/dev/cypress_smru0";
|
||||
|
||||
private static final int MINJNIVERSION = 5;
|
||||
@ -265,7 +263,7 @@ public class SmruDaqJNI {
|
||||
this.smruDaqSystem = smruDaqSystem;
|
||||
loadLibrary();
|
||||
if (haveLibrary()) {
|
||||
setVerbose(verboseLevel);
|
||||
setVerbose(SmruDaqSystem.VERBOSELEVEL);
|
||||
|
||||
/**
|
||||
* List the devices, but don't do any resetting and
|
||||
@ -492,7 +490,7 @@ public class SmruDaqJNI {
|
||||
public int toggleLED(int board, int led) {
|
||||
board = boardOrder[board];
|
||||
int state = getLED(board, led);
|
||||
System.out.println("state="+state);
|
||||
// System.out.println("LED state="+state);
|
||||
if (state == 0) {
|
||||
state = 1;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import java.util.List;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
@ -13,6 +14,7 @@ import soundPlayback.PlaybackControl;
|
||||
import soundPlayback.PlaybackSystem;
|
||||
import Acquisition.AcquisitionControl;
|
||||
import Acquisition.AcquisitionDialog;
|
||||
import Acquisition.AcquisitionProcess;
|
||||
import Acquisition.DaqSystem;
|
||||
import Acquisition.AudioDataQueue;
|
||||
import PamController.PamControlledUnitSettings;
|
||||
@ -49,7 +51,8 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
||||
|
||||
public static final String oldCardName = "SMRU Ltd DAQ Card";
|
||||
|
||||
private static final int VERBOSELEVEL = 0;
|
||||
public static final int VERBOSELEVEL = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @param daqControl
|
||||
@ -61,6 +64,11 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
||||
smruDaqJNI = new SmruDaqJNI(this);
|
||||
|
||||
nDaqCards = smruDaqJNI.getnDevices();
|
||||
for (int i = 0; i < nDaqCards; i++) {
|
||||
for (int l = 0; l < 2; l++) {
|
||||
smruDaqJNI.setLED(i, l, 0);
|
||||
}
|
||||
}
|
||||
|
||||
smruDaqDialogPanel = new SmruDaqDialogPanel(this);
|
||||
PamSettingManager.getInstance().registerSettings(this);
|
||||
@ -275,6 +283,8 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
||||
boolean prepareDaqCard(int iBoard, boolean fullReset) {
|
||||
// devices are left closed, so will need to reopen them.
|
||||
// of course, there is a vile lookup table, so...
|
||||
smruDaqJNI.setLED(iBoard, SmruDaqJNI.GREEN_LED, 0);
|
||||
smruDaqJNI.setLED(iBoard, SmruDaqJNI.RED_LED, 0);
|
||||
int hardId = smruDaqJNI.getBoardOrder(iBoard);
|
||||
int prepOk = smruDaqJNI.prepareDevice(hardId, fullReset);
|
||||
terminalPrint("Opened daq card returned " + prepOk, 1);
|
||||
@ -313,6 +323,7 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
||||
|
||||
if (ans) {
|
||||
Thread t = new Thread(new DaqThread());
|
||||
t.setPriority(Thread.MAX_PRIORITY);
|
||||
t.start();
|
||||
keepRunning = true;
|
||||
daqThreadRunning = true;
|
||||
@ -371,18 +382,43 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
||||
boolean first = true;
|
||||
boolean needRestart = false;
|
||||
int iChan;
|
||||
// some flags on checks of incoming data rate
|
||||
// long recentSamples = 0;
|
||||
// long recentCheckTime = System.currentTimeMillis();
|
||||
int loopCount = 0;
|
||||
for (int iBoard = 0; iBoard < nDaqCards; iBoard++) {
|
||||
smruDaqJNI.setLED(iBoard, SmruDaqJNI.GREEN_LED, 1);
|
||||
smruDaqJNI.setLED(iBoard, SmruDaqJNI.RED_LED, 0);
|
||||
}
|
||||
|
||||
while (keepRunning) {
|
||||
iChan = 0;
|
||||
dataMillis = daqControl.getAcquisitionProcess().absSamplesToMilliseconds(totalSamples);
|
||||
if (isStalled()) {
|
||||
needRestart = true;
|
||||
for (int iBoard = 0; iBoard < nDaqCards; iBoard++) {
|
||||
smruDaqJNI.setLED(iBoard, SmruDaqJNI.GREEN_LED, 0);
|
||||
smruDaqJNI.setLED(iBoard, SmruDaqJNI.RED_LED, 1);
|
||||
}
|
||||
// don't set this false or the shutdown doesn't work properly.
|
||||
// keepRunning = false;
|
||||
break;
|
||||
}
|
||||
loopCount++;
|
||||
for (int iBoard = 0; iBoard < nDaqCards && keepRunning; iBoard++) {
|
||||
if ((loopCount % 10000) == 0) {
|
||||
// toggleLED(iBoard, 0);
|
||||
smruDaqJNI.setLED(iBoard, SmruDaqJNI.GREEN_LED, 1);
|
||||
}
|
||||
for (int i = 0; i < boardChannels[iBoard] && keepRunning; i++) {
|
||||
newData = smruDaqJNI.readSamples(iBoard, i, wantedSamples);
|
||||
if (newData == null) {
|
||||
smruDaqJNI.setLED(iBoard, SmruDaqJNI.RED_LED, 1);
|
||||
System.out.println(String.format("Null data read from smruDaqJNI.readSamples board %d, chan %d, samples %d",
|
||||
iBoard, i, wantedSamples));
|
||||
// System.out.println("Issue restart ...");
|
||||
needRestart = true;
|
||||
keepRunning = false;
|
||||
// keepRunning = false;
|
||||
break;
|
||||
}
|
||||
readSamples = newData.length;
|
||||
@ -409,19 +445,47 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
||||
if (++dcOffsetCalls == 100) {
|
||||
dcOffsetScale = 100.; // after a bit, increase the time constant.
|
||||
}
|
||||
|
||||
|
||||
|
||||
totalSamples += readSamples;
|
||||
|
||||
}
|
||||
};
|
||||
daqThreadRunning = false;
|
||||
if (needRestart) {
|
||||
PamController pamController = PamController.getInstance();
|
||||
pamController.pamStop();
|
||||
PamDialog.showWarning(daqControl.getGuiFrame(), daqControl.getUnitName(), "Problem with one or more SAIL DAQ Cards.\n"
|
||||
+ "Restart PAMGuard, check connections and try again." );
|
||||
// pamController.startLater();
|
||||
|
||||
for (int iBoard = 0; iBoard < nDaqCards; iBoard++) {
|
||||
smruDaqJNI.setLED(iBoard, SmruDaqJNI.GREEN_LED, 0);
|
||||
}
|
||||
|
||||
if (needRestart) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
PamController pamController = PamController.getInstance();
|
||||
pamController.pamStop();
|
||||
System.out.println("Problem with one or more SAIL DAQ Cards. "
|
||||
+ "Restart PAMGuard, check connections and try again." );
|
||||
// PamDialog.showWarning(daqControl.getGuiFrame(), daqControl.getUnitName(), "Problem with one or more SAIL DAQ Cards.\n"
|
||||
// + "Restart PAMGuard, check connections and try again." );
|
||||
pamController.startLater();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// private long lastFakeStall = 0;
|
||||
private boolean isStalled() {
|
||||
// if (lastFakeStall == 0) {
|
||||
// lastFakeStall = System.currentTimeMillis();
|
||||
// }
|
||||
// long now = System.currentTimeMillis();
|
||||
// if (now-lastFakeStall > 10000) {
|
||||
// System.out.println("Random pretend stalled");
|
||||
// lastFakeStall = 0;
|
||||
// return true;
|
||||
// }
|
||||
return daqControl.getAcquisitionProcess().isStalled();
|
||||
}
|
||||
|
||||
public static short getSample(byte[] buffer, int position) {
|
||||
|
@ -21,6 +21,7 @@ public class CounterControl extends SimpleControl {
|
||||
|
||||
Character suffix;
|
||||
|
||||
public enum CounterSuffix {NOSUFFIX, CHARSUFFIX};
|
||||
|
||||
public CounterControl(ControlDescription controlDescription,
|
||||
LoggerForm loggerForm) {
|
||||
@ -36,25 +37,19 @@ public class CounterControl extends SimpleControl {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private String calculateCounter() {
|
||||
int num = FormCounterManagement.getInstance().getCounterNumber(this,controlDescription.getFormDescription().getDBTABLENAME());
|
||||
|
||||
String numSt = Integer.toString(num);
|
||||
int nZeros = 3-numSt.length();
|
||||
|
||||
String tSt = "";
|
||||
for (int i=0;i<nZeros;i++){
|
||||
tSt+="0";
|
||||
// System.out.println(tSt);
|
||||
}
|
||||
|
||||
numSt = tSt+numSt;
|
||||
String numSt = String.format("%03d", num);
|
||||
// int nZeros = 3-numSt.length();
|
||||
//
|
||||
// String tSt = "";
|
||||
// for (int i=0;i<nZeros;i++){
|
||||
// tSt+="0";
|
||||
//// System.out.println(tSt);
|
||||
// }
|
||||
//
|
||||
// numSt = tSt+numSt;
|
||||
// System.out.println(tSt);
|
||||
// System.out.println(numSt);
|
||||
|
||||
@ -109,31 +104,19 @@ public class CounterControl extends SimpleControl {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
AbstractFormatter getAbstractformatter() {
|
||||
|
||||
DefaultFormatter formatter = new DefaultFormatter();
|
||||
return formatter;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void updateCounter() {
|
||||
if (loggerForm.getNewOrEdit()==LoggerForm.EditDataForm) return;
|
||||
// System.out.println("updateCounter");
|
||||
setData(calculateCounter());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,9 @@ package loggerForms.formdesign.controlpropsets;
|
||||
|
||||
import loggerForms.FormDescription;
|
||||
import loggerForms.UDColName;
|
||||
import loggerForms.controlDescriptions.ControlTypes;
|
||||
import loggerForms.formdesign.ControlTitle;
|
||||
import loggerForms.formdesign.itempanels.BooleanCtrlColPanel;
|
||||
import loggerForms.formdesign.itempanels.CtrlColPanel;
|
||||
|
||||
public class CounterPropertySet extends BasePropertySet {
|
||||
@ -15,12 +17,17 @@ public class CounterPropertySet extends BasePropertySet {
|
||||
@Override
|
||||
public CtrlColPanel getItemPropertyPanel(ControlTitle selTitle,
|
||||
UDColName propertyName) {
|
||||
// if (selTitle.getType() == ControlTypes.COUNTER) {
|
||||
// System.out.println("counter");
|
||||
// }
|
||||
switch (propertyName) {
|
||||
case Plot:
|
||||
case Autoclear:
|
||||
case ReadOnly:
|
||||
case AutoUpdate:
|
||||
return null;
|
||||
// case Topic:
|
||||
// return new BooleanCtrlColPanel(selTitle, new );
|
||||
}
|
||||
return super.getItemPropertyPanel(selTitle, propertyName);
|
||||
}
|
||||
|
@ -236,9 +236,9 @@ public class NoiseBandControl extends PamControlledUnit implements PamSettings {
|
||||
@Override
|
||||
public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
|
||||
noiseBandSettings = ((NoiseBandSettings)pamControlledUnitSettings.getSettings()).clone();
|
||||
System.out.println("********************************************************");
|
||||
System.out.println("NOISE BAND SETTINGS: " + noiseBandSettings.rawDataSource);
|
||||
System.out.println("********************************************************");
|
||||
// System.out.println("********************************************************");
|
||||
// System.out.println("NOISE BAND SETTINGS: " + noiseBandSettings.rawDataSource);
|
||||
// System.out.println("********************************************************");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -905,7 +905,7 @@ public class PamVector implements Serializable, Cloneable, PamCoordinate, Manage
|
||||
}
|
||||
double[] angs = new double[3];
|
||||
angs[0] = vectors[0].getHeading();
|
||||
angs[1] = vectors[1].getPitch();
|
||||
angs[1] = vectors[0].getPitch();
|
||||
if (vectors.length >= 2) {
|
||||
angs[2] = vectors[1].getPitch();
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import dataModelFX.DataModelPaneFX;
|
||||
import org.controlsfx.control.ToggleSwitch;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A pane which holds a set of tabs.
|
||||
*
|
||||
@ -125,7 +126,7 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
|
||||
this.pamGuiManagerFX=pamGuiManagerFX;
|
||||
this.mainTabPane = mainTabPane;
|
||||
|
||||
Pane layout=createMainPane(mainTabPane, stage);
|
||||
Node layout=createMainPane(mainTabPane, stage);
|
||||
|
||||
//add main pane to PamGui
|
||||
this.getChildren().add(layout);
|
||||
@ -140,7 +141,7 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
|
||||
//create the main tab pane.
|
||||
this.mainTabPane = new PamTabPane();
|
||||
|
||||
Pane layout=createMainPane(mainTabPane, stage);
|
||||
Node layout=createMainPane(mainTabPane, stage);
|
||||
|
||||
//add main pane to PamGui
|
||||
this.getChildren().add(layout);
|
||||
@ -154,7 +155,7 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
|
||||
* @param stage - the stage holding this GUI.
|
||||
* @return a pane which sits in the stage.
|
||||
*/
|
||||
private Pane createMainPane(PamTabPane mainTabPane, Stage stage){
|
||||
private Node createMainPane(PamTabPane mainTabPane, Stage stage){
|
||||
|
||||
//create the pane which holds tab pane
|
||||
final PamBorderPane layout = new PamBorderPane();
|
||||
@ -261,7 +262,6 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
|
||||
|
||||
PamBorderPane layoutHolder=new PamBorderPane(layout);
|
||||
layoutHolder.setTop(hidingLoadPane);
|
||||
|
||||
|
||||
return layoutHolder;
|
||||
|
||||
|
@ -253,6 +253,10 @@ public class PamGuiTabFX extends PamTabFX {
|
||||
double r1 = 1 - r;
|
||||
|
||||
int smallWindows = 0;
|
||||
|
||||
|
||||
//the padding between windows
|
||||
double padding = 10;
|
||||
|
||||
ArrayList<PamGuiInternalPane> dw = internalPanes;
|
||||
|
||||
@ -268,7 +272,9 @@ public class PamGuiTabFX extends PamTabFX {
|
||||
|
||||
//now place windows in correct position
|
||||
//large windows
|
||||
double x, y, w, h = 0;
|
||||
double x, y, w, h = 0.;
|
||||
double pad =0.;
|
||||
|
||||
if (largeWindows > 0) {
|
||||
x = 0;
|
||||
y = 0;
|
||||
@ -284,7 +290,10 @@ public class PamGuiTabFX extends PamTabFX {
|
||||
if (dw.get(i).getUserDisplayNode().isMinorDisplay()== true) continue;
|
||||
|
||||
dw.get(i).setPaneLayout(x, y);
|
||||
dw.get(i).setPaneSize(w, h);
|
||||
|
||||
//set the padding if the pane is not the last pane.
|
||||
pad = (i== dw.size()-1) ? 0 : padding;
|
||||
dw.get(i).setPaneSize(w - (horz? pad:0), h - (horz? 0:pad));
|
||||
if (horz) x += w;
|
||||
else y += h;
|
||||
}
|
||||
@ -307,7 +316,10 @@ public class PamGuiTabFX extends PamTabFX {
|
||||
for (int i = 0; i < dw.size(); i++) {
|
||||
if (dw.get(i).getUserDisplayNode().isMinorDisplay() == false) continue;
|
||||
dw.get(i).setPaneLayout(x, y);
|
||||
dw.get(i).setPaneSize(w, h);
|
||||
|
||||
//set the padding if the pane is not the last pane.
|
||||
pad = (i== dw.size()-1) ? 0 : padding;
|
||||
dw.get(i).setPaneSize(w- (horz? pad:0), h - (horz? 0:pad));
|
||||
if (horz) x += w;
|
||||
else y +=h;
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ import javafx.beans.property.DoubleProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Insets;
|
||||
|
||||
/**
|
||||
* Hiding pane which can be added to any node.
|
||||
@ -156,7 +155,7 @@ public class HidingPane extends StackPane {
|
||||
//create a button which hides the side panel
|
||||
hideButton=createShowButton(false);
|
||||
styleHideButton(hideButton);
|
||||
hideButton.setOnAction(new HideButtonPressed());
|
||||
// hideButton.setOnAction(new HideButtonPressed());
|
||||
hideButton.setVisible(false);
|
||||
// hideButton.setStyle("close-button-right");
|
||||
|
||||
@ -333,8 +332,6 @@ public class HidingPane extends StackPane {
|
||||
double dragX=0;
|
||||
double dragY=0;
|
||||
double distance=0;
|
||||
|
||||
|
||||
private PamButton createShowButton(final boolean show){
|
||||
|
||||
final PamButton pamButton=new PamButton();
|
||||
@ -343,6 +340,7 @@ public class HidingPane extends StackPane {
|
||||
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
// record a delta distance for the drag and drop operation.
|
||||
// System.out.println("HidingPane.showButton - setOnMousePressed");
|
||||
dragX =mouseEvent.getSceneX();
|
||||
dragY =mouseEvent.getSceneY();
|
||||
}
|
||||
@ -350,10 +348,24 @@ public class HidingPane extends StackPane {
|
||||
|
||||
pamButton.setOnMouseReleased(new EventHandler<MouseEvent>() {
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
if (distance==0) return;
|
||||
// System.out.println("HidingPane.showButton - setOnMouseReleased");
|
||||
|
||||
//the mouse has been pressed
|
||||
if (distance==0) {
|
||||
if (isShowing()) {
|
||||
showHidePane(false);
|
||||
}
|
||||
else {
|
||||
showHidePane(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//the mouse has been dragged dragged
|
||||
distance=sideIndex*distance;
|
||||
// System.out.println("Mouse released: HidePanel distance: "+distance);
|
||||
if (!overlay) distance=Math.abs(distance);
|
||||
|
||||
//need to see where the drag has ended-if greater than 50% then open but if less then close.
|
||||
if (!isHorizontal()){
|
||||
if (distance<expandedSize/2) showHidePane(overlay? true : false);
|
||||
@ -363,6 +375,7 @@ public class HidingPane extends StackPane {
|
||||
if (distance<expandedSize/2) showHidePane(overlay? true : false);
|
||||
if (distance>=expandedSize/2) showHidePane(overlay? false : true);
|
||||
}
|
||||
|
||||
//reset the distance
|
||||
distance=0;
|
||||
}
|
||||
@ -370,12 +383,14 @@ public class HidingPane extends StackPane {
|
||||
|
||||
pamButton.setOnMouseDragged(new EventHandler<MouseEvent>() {
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
// System.out.println("HidingPane.showButton - setOnMouseDragged");
|
||||
if (visibleImmediatly) hidePane.setVisible(true);
|
||||
else hidePane.setVisible(false);
|
||||
// hideButton.setVisible(true);
|
||||
/**
|
||||
* Work out the distance the panel is to be dragged;
|
||||
*/
|
||||
double distance = 0;
|
||||
if (!isHorizontal()){
|
||||
if (!show) distance=(mouseEvent.getSceneX()-dragX);
|
||||
else distance=(mouseEvent.getSceneX()-dragX)+sideIndex*expandedSize;
|
||||
@ -387,26 +402,28 @@ public class HidingPane extends StackPane {
|
||||
if (!overlay) distance=expandedSize+sideIndex*distance;
|
||||
}
|
||||
// if (show && Math.abs(distance)>expandedSize) return;
|
||||
|
||||
|
||||
translatePanel(distance);
|
||||
|
||||
HidingPane.this.distance = distance ;
|
||||
}
|
||||
});
|
||||
|
||||
pamButton.setOnMouseEntered(new EventHandler<MouseEvent>() {
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
// System.out.println("HidingPane.showButton - mouse entered");
|
||||
pamButton.setOpacity(1.0);
|
||||
pamButton.setPadding(new Insets(2.,2.,2.,2.));
|
||||
}
|
||||
});
|
||||
|
||||
pamButton.setOnMouseExited(new EventHandler<MouseEvent>() {
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
// System.out.println("HidingPane.showButton - mouse exited");
|
||||
if (show) pamButton.setOpacity(showButtonOpacity);
|
||||
pamButton.setPadding(new Insets(0.,0.,0.,0.));
|
||||
}
|
||||
});
|
||||
// pamButton.setOnMouseEntered(new EventHandler<MouseEvent>() {
|
||||
// @Override public void handle(MouseEvent mouseEvent) {
|
||||
//// System.out.println("HidingPane.showButton - mouse entered");
|
||||
// pamButton.setOpacity(1.0);
|
||||
// pamButton.setPadding(new Insets(2.,2.,2.,2.));
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// pamButton.setOnMouseExited(new EventHandler<MouseEvent>() {
|
||||
// @Override public void handle(MouseEvent mouseEvent) {
|
||||
//// System.out.println("HidingPane.showButton - mouse exited");
|
||||
// if (show) pamButton.setOpacity(showButtonOpacity);
|
||||
// pamButton.setPadding(new Insets(0.,0.,0.,0.));
|
||||
// }
|
||||
// });
|
||||
|
||||
// pamButton.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
||||
// @Override public void handle(MouseEvent mouseEvent) {
|
||||
@ -415,15 +432,15 @@ public class HidingPane extends StackPane {
|
||||
// }
|
||||
// });
|
||||
|
||||
pamButton.addEventHandler(ActionEvent.ACTION,new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent e) {
|
||||
System.out.println("HidingPane.showButton - action event clicked");
|
||||
showHidePane(show);
|
||||
}
|
||||
});
|
||||
// pamButton.addEventHandler(ActionEvent.ACTION,new EventHandler<ActionEvent>() {
|
||||
// @Override
|
||||
// public void handle(ActionEvent e) {
|
||||
// System.out.println("HidingPane.showButton - action event clicked");
|
||||
// showHidePane(show);
|
||||
// }
|
||||
// });
|
||||
|
||||
if (show) pamButton.setOpacity(showButtonOpacity);
|
||||
// if (show) pamButton.setOpacity(showButtonOpacity);
|
||||
|
||||
return pamButton;
|
||||
}
|
||||
@ -601,7 +618,7 @@ public class HidingPane extends StackPane {
|
||||
showing.setValue(true);
|
||||
if (visibleImmediatly) hidePane.setVisible(true);
|
||||
//hideButton.setVisible(true);
|
||||
//System.out.println("HidingPane: Open Hide Pane");
|
||||
// System.out.println("HidingPane: Open Hide Pane");
|
||||
//open the panel
|
||||
if (timeLineShow.getStatus()==Status.RUNNING) {
|
||||
//stops the issue with the hiding pane freezing.
|
||||
@ -613,7 +630,7 @@ public class HidingPane extends StackPane {
|
||||
else{
|
||||
showing.setValue(false);
|
||||
if (!visibleImmediatly) hidePane.setVisible(false);
|
||||
//System.out.println("HidingPane: Close Hide Pane");
|
||||
// System.out.println("HidingPane: Close Hide Pane");
|
||||
//close the panel
|
||||
timeLineHide.play();
|
||||
}
|
||||
@ -638,17 +655,17 @@ public class HidingPane extends StackPane {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever the pin button is pressed.
|
||||
* @author Jamie Macaulay
|
||||
*/
|
||||
class HideButtonPressed implements EventHandler<ActionEvent>{
|
||||
|
||||
@Override
|
||||
public void handle(ActionEvent arg0) {
|
||||
showHidePane(false);
|
||||
}
|
||||
}
|
||||
// /**
|
||||
// * Called whenever the pin button is pressed.
|
||||
// * @author Jamie Macaulay
|
||||
// */
|
||||
// class HideButtonPressed implements EventHandler<ActionEvent>{
|
||||
//
|
||||
// @Override
|
||||
// public void handle(ActionEvent arg0) {
|
||||
// showHidePane(false);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Get the button which hides the pane.
|
||||
@ -732,6 +749,15 @@ public class HidingPane extends StackPane {
|
||||
return this.showing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the hiding pane is showing.
|
||||
* @return true if showing.
|
||||
*/
|
||||
public boolean isShowing(){
|
||||
return this.showing.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the opacity of the show button when the mouse is outside the button.
|
||||
* @return the opacity of the show button.
|
||||
|
@ -6,6 +6,8 @@ import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.DoubleProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleDoubleProperty;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.Node;
|
||||
@ -844,5 +846,18 @@ public class ScrollBarPane extends PamBorderPane {
|
||||
this.showMillis = showMillis;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience function which adds a change listener to the current value and visible amount prooperty.
|
||||
* @param val - the change listener to add.
|
||||
*/
|
||||
public void addValueListener(ChangeListener val) {
|
||||
//add listener to visible amount property.
|
||||
visibleAmountProperty.addListener(val);
|
||||
|
||||
//add listener to current value amount property.
|
||||
currentValueProperty.addListener(val);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
package pamViewFX.fxPlotPanes;
|
||||
|
||||
import Layout.PamAxis;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.SimpleDoubleProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.geometry.Side;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.canvas.Canvas;
|
||||
@ -256,13 +259,31 @@ public class PlotPane extends PamBorderPane {
|
||||
PamHBox horzHolder=new PamHBox();
|
||||
|
||||
Pane leftPane=new Pane();
|
||||
|
||||
//create an observable which is the size of the axis pane if the pane is visible and otherwise
|
||||
//is zero.
|
||||
ObservableValue<Number> valLeft = Bindings
|
||||
.when(yAxisLeftPane.visibleProperty())
|
||||
.then(yAxisLeftPane.widthProperty())
|
||||
.otherwise(
|
||||
new SimpleDoubleProperty(0.)
|
||||
);
|
||||
|
||||
//need both min and pref to make binding work properly;
|
||||
leftPane.prefWidthProperty().bind(yAxisLeftPane.widthProperty());
|
||||
leftPane.minWidthProperty().bind(yAxisLeftPane.widthProperty());
|
||||
leftPane.prefWidthProperty().bind(valLeft);
|
||||
leftPane.minWidthProperty().bind(valLeft);
|
||||
|
||||
Pane rightPane=new Pane();
|
||||
rightPane.prefWidthProperty().bind(yAxisRightPane.widthProperty());
|
||||
rightPane.minWidthProperty().bind(yAxisRightPane.widthProperty());
|
||||
|
||||
ObservableValue<Number> valRight = Bindings
|
||||
.when(yAxisRightPane.visibleProperty())
|
||||
.then(yAxisRightPane.widthProperty())
|
||||
.otherwise(
|
||||
new SimpleDoubleProperty(0.)
|
||||
);
|
||||
|
||||
rightPane.prefWidthProperty().bind(valRight);
|
||||
rightPane.minWidthProperty().bind(valRight);
|
||||
|
||||
horzHolder.getChildren().addAll(leftPane, axisPane, rightPane);
|
||||
//axisPane.toFront(); this changes the order of children in a PamHBox.
|
||||
@ -369,8 +390,8 @@ public class PlotPane extends PamBorderPane {
|
||||
|
||||
//holderPane.getChildren().clear();
|
||||
|
||||
//HACK- 05/08/2016 have to do this because there is a bug in switching children postions in a border pane.
|
||||
//casues a duplicate childrne error.
|
||||
//HACK- 05/08/2016 have to do this because there is a bug in switching children positions in a border pane.
|
||||
//causes duplicate children error
|
||||
holderPane.setRight(null);
|
||||
holderPane.setLeft(null);
|
||||
holderPane.setTop(null);
|
||||
@ -385,24 +406,30 @@ public class PlotPane extends PamBorderPane {
|
||||
else if (topBorder > 0) {
|
||||
// holderPane.setTopSpace(topBorder);
|
||||
}
|
||||
|
||||
if (bottom) {
|
||||
holderPane.setBottom(bottomHolder);
|
||||
}
|
||||
else if (bottomBorder > 0) {
|
||||
// holderPane.setBottomSpace(bottomBorder);
|
||||
}
|
||||
|
||||
if (right) {
|
||||
holderPane.setRight(yAxisRightPane) ;
|
||||
yAxisRightPane.setVisible(true);
|
||||
}
|
||||
else if (rightBorder > 0){
|
||||
// holderPane.setRightSpace(rightBorder);
|
||||
else {
|
||||
yAxisRightPane.setVisible(false);
|
||||
}
|
||||
|
||||
if (left) {
|
||||
holderPane.setLeft(yAxisLeftPane) ;
|
||||
yAxisLeftPane.setVisible(true);
|
||||
}
|
||||
else if (leftBorder > 0) {
|
||||
// holderPane.setLeftSpace(leftBorder);
|
||||
else {
|
||||
yAxisLeftPane.setVisible(false);
|
||||
}
|
||||
|
||||
holderPane.setCenter(canvasHolder);
|
||||
//bottomHolder.toBack();
|
||||
|
||||
|
@ -561,6 +561,7 @@ public class DLControl extends PamControlledUnit implements PamSettings {
|
||||
* @return the number of classes.
|
||||
*/
|
||||
public int getNumClasses() {
|
||||
if (getDLModel()==null) return 0;
|
||||
return getDLModel().getNumClasses();
|
||||
|
||||
}
|
||||
|
@ -37,6 +37,13 @@ public class RawDLParams implements Serializable, Cloneable {
|
||||
* Holds channel and grouping information
|
||||
*/
|
||||
public GroupedSourceParameters groupedSourceParams = new GroupedSourceParameters();
|
||||
|
||||
/**
|
||||
* True to enable segmentation. If segmentation is disabled then the raw waveform from
|
||||
* a data unit is passed directly to the model. Note that this is not an option for raw sound
|
||||
* data.
|
||||
*/
|
||||
public boolean enableSegmentation = true;
|
||||
|
||||
/**
|
||||
* The number of raw samples to send to the classifier.
|
||||
@ -85,7 +92,7 @@ public class RawDLParams implements Serializable, Cloneable {
|
||||
* different class names. If we change model then the class names may change.
|
||||
* Previously annotated data will then be messed up. But, in a giant dataset
|
||||
* that may be an issue. Perhaps users wish to run a new model on some chunk of
|
||||
* data without messing up all the other classified detectionS which have used
|
||||
* data without messing up all the other classified detections which have used
|
||||
* that module. So store the data in binary files? That is super inefficient as
|
||||
* the same string is stored many times. So instead store a short which
|
||||
* identifies the string that sits in this table. Everytime a new model is added
|
||||
|
@ -141,12 +141,12 @@ public class DLPredictonPane extends DynamicSettingsPane<DLPredictionFilterParam
|
||||
@Override
|
||||
public DLPredictionFilterParams getParams(DLPredictionFilterParams currParams) {
|
||||
|
||||
if (classPanes==null) return currParams;
|
||||
for (int i=0; i<classPanes.length ; i++) {
|
||||
currParams.classSelect[i] = classPanes[i].enable.isSelected();
|
||||
currParams.minClassPredicton[i] = classPanes[i].slider.getValue();
|
||||
}
|
||||
|
||||
|
||||
return currParams;
|
||||
}
|
||||
|
||||
|
@ -382,6 +382,7 @@ public class DelphinIDUtils {
|
||||
// String modelPath = "/Users/au671271/Library/CloudStorage/Dropbox/PAMGuard_dev/Deep_Learning/delphinID/testencounter415/whistle_model_2/whistle_4s_415.zip";
|
||||
String modelPath = "D:/Dropbox/PAMGuard_dev/Deep_Learning/delphinID/testencounter415/whistle_model_2/whistle_4s_415.zip";
|
||||
|
||||
//line widths in pixels
|
||||
double[] lineWidths = new double[] {6, 7, 10, 15, 20};
|
||||
|
||||
for (double lineWidth:lineWidths) {
|
||||
|
@ -117,7 +117,7 @@ public class GenericModelWorker extends DLModelWorker<StandardPrediction> {
|
||||
|
||||
((GenericModelParams) genericParams).defaultShape = longArr2Long(genericModel.getInputShape().getShape());
|
||||
((GenericModelParams) genericParams).defualtOuput = longArr2Long(genericModel.getOutShape().getShape());
|
||||
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
@ -486,9 +486,17 @@ public class SegmenterProcess extends PamProcess {
|
||||
|
||||
//pass the raw click data to the segmenter
|
||||
for (int i=0;i<chans.length; i++) {
|
||||
newRawData(pamDataUnit,
|
||||
rawDataChunk[i], chans[i], true);
|
||||
|
||||
if (dlControl.getDLParams().enableSegmentation) {
|
||||
//segment the data unit into different chunks.
|
||||
newRawData(pamDataUnit,
|
||||
rawDataChunk[i], chans[i], dlControl.getDLParams().rawSampleSize, dlControl.getDLParams().sampleHop, true);
|
||||
}
|
||||
else {
|
||||
//send the whole data chunk to the deep learning unit
|
||||
newRawData(pamDataUnit,
|
||||
rawDataChunk[i], chans[i], rawDataChunk[i].length, rawDataChunk[i].length, true);
|
||||
}
|
||||
//the way that the newRawdata works is it waits for the next chunk and copies all relevant bits
|
||||
//from previous chunks into segments. This is fine for continuous data but means that chunks of data
|
||||
//don't get their last hop...
|
||||
@ -512,7 +520,7 @@ public class SegmenterProcess extends PamProcess {
|
||||
* @param iChan - the channel that is being segmented
|
||||
*/
|
||||
public void newRawData(PamDataUnit unit, double[] rawDataChunk, int iChan) {
|
||||
newRawData(unit, rawDataChunk, iChan, false);
|
||||
newRawData(unit, rawDataChunk, iChan, dlControl.getDLParams().rawSampleSize ,dlControl.getDLParams().sampleHop , false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -523,15 +531,17 @@ public class SegmenterProcess extends PamProcess {
|
||||
*
|
||||
* @param unit - the data unit which contains relevant metadata on time
|
||||
* etc.
|
||||
* @param rawDataChunk - the sound chunk to segment extracted from the data
|
||||
* @param rawDataChunk - the sound chunk extracted from the data
|
||||
* unit.
|
||||
* @param iChan - the channel that is being segmented
|
||||
* @param rawSampleSize - the segment size in samples i.e. the size of the segmenting window.
|
||||
* @param rawSampleHop - the segment hop in samples i.e. how far the window jumps for each segment.
|
||||
* @param forceSave - make sure that all data is passed into the buffers and
|
||||
* do not wait for the next data unit. This is used to make
|
||||
* sure that discrete chunks have their full number of
|
||||
* segments saved.
|
||||
*/
|
||||
public synchronized void newRawData(PamDataUnit unit, double[] rawDataChunk, int iChan, boolean forcesave) {
|
||||
public synchronized void newRawData(PamDataUnit unit, double[] rawDataChunk, int iChan, int rawSampleSize, int rawSampleHop, boolean forcesave) {
|
||||
|
||||
long timeMilliseconds = unit.getTimeMilliseconds();
|
||||
long startSampleTime = unit.getStartSample();
|
||||
@ -555,7 +565,7 @@ public class SegmenterProcess extends PamProcess {
|
||||
if (currentRawChunks[i]==null) {
|
||||
//create a new data unit - should only be called once after initial start.
|
||||
currentRawChunks[i] = new GroupedRawData(timeMilliseconds, getSourceParams().getGroupChannels(i),
|
||||
startSampleTime, dlControl.getDLParams().rawSampleSize, dlControl.getDLParams().rawSampleSize);
|
||||
startSampleTime, rawSampleSize, rawSampleSize);
|
||||
|
||||
currentRawChunks[i].setParentDataUnit(unit);;
|
||||
}
|
||||
@ -615,7 +625,7 @@ public class SegmenterProcess extends PamProcess {
|
||||
|
||||
//segments which do not include any last zero padded segmen- zeros can confuse deep learning models so it may be better to keep use
|
||||
//this instead of zero padding end chunks.
|
||||
int nChunks = (int) Math.ceil((overFlow)/(double) dlControl.getDLParams().sampleHop);
|
||||
int nChunks = (int) Math.ceil((overFlow)/(double) rawSampleHop);
|
||||
|
||||
nChunks = Math.max(nChunks, 1); //cannot be less than one (if forceSave is used then can be zero if no overflow)
|
||||
nextRawChunks[i]=new GroupedRawData[nChunks];
|
||||
@ -638,11 +648,11 @@ public class SegmenterProcess extends PamProcess {
|
||||
|
||||
//go from current raw chunks tim millis to try and minimise compounding time errors.
|
||||
// long timeMillis = (long) (currentRawChunks[i].getTimeMilliseconds() + j*(1000.*(dlControl.getDLParams().sampleHop)/this.getSampleRate()));
|
||||
long startSample = lastRawDataChunk.getStartSample() + dlControl.getDLParams().sampleHop;
|
||||
long startSample = lastRawDataChunk.getStartSample() + rawSampleHop;
|
||||
long timeMillis = this.absSamplesToMilliseconds(startSample);
|
||||
|
||||
nextRawChunks[i][j] = new GroupedRawData(timeMillis, getSourceParams().getGroupChannels(i),
|
||||
startSample, dlControl.getDLParams().rawSampleSize, dlControl.getDLParams().rawSampleSize);
|
||||
startSample, rawSampleSize, rawSampleSize);
|
||||
nextRawChunks[i][j].setParentDataUnit(unit);
|
||||
|
||||
}
|
||||
|
33
src/test/export/ExportTest.java
Normal file
@ -0,0 +1,33 @@
|
||||
package test.export;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import clickDetector.ClickDetection;
|
||||
|
||||
|
||||
/**
|
||||
* Tests for export functionality.
|
||||
*/
|
||||
public class ExportTest {
|
||||
|
||||
|
||||
/**
|
||||
* Test exporting detections to mat files.
|
||||
*/
|
||||
@Test
|
||||
public void matFileTest() {
|
||||
|
||||
System.out.println("Matched template classifier test: match corr");
|
||||
|
||||
//create a list of click detections.
|
||||
ClickDetection clickDetection = new ClickDetection(0, 0, 0, null, null, 0);
|
||||
|
||||
|
||||
//now open the mat file and check that we have all the data from these click detections.
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -83,8 +83,9 @@ public class MatchedTemplateClassifierTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the match correlation algorithm combined with click length algorithm. Here we awant to test that
|
||||
* a long waveform
|
||||
* Test the match correlation algorithm combined with click length algorithm. Here we want to test that
|
||||
* a long waveform can be processed properly - i.e the peak of the click can be found and cross correlation performed
|
||||
* on a shortened section.
|
||||
*/
|
||||
@Test
|
||||
public void testMatchCorrLen() {
|
||||
|
31
src/test/rawDeepLearningClassifier/ClickDLTest.java
Normal file
@ -0,0 +1,31 @@
|
||||
package test.rawDeepLearningClassifier;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import rawDeepLearningClassifier.dlClassification.genericModel.GenericModelParams;
|
||||
import rawDeepLearningClassifier.dlClassification.genericModel.GenericModelWorker;
|
||||
|
||||
public class ClickDLTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void clickDLTest() {
|
||||
//relative paths to the resource folders.
|
||||
System.out.println("*****Click classification Deep Learning*****");
|
||||
|
||||
//relative paths to the resource folders.
|
||||
String relModelPath = "D:/Dropbox/PAMGuard_dev/Deep_Learning/click_classifier_Thomas/best_model/saved_model.pb";
|
||||
|
||||
|
||||
GenericModelWorker genericModelWorker = new GenericModelWorker();
|
||||
|
||||
GenericModelParams genericModelParams = new GenericModelParams();
|
||||
|
||||
genericModelParams.modelPath = relModelPath;
|
||||
|
||||
genericModelWorker.prepModel(genericModelParams, null);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -5,8 +5,8 @@ import org.junit.jupiter.api.Test;
|
||||
public class PamZipDLClassifierTest {
|
||||
|
||||
/**
|
||||
* Test the koogu classifier and tests are working properly. This tests loading the koogu model and also using
|
||||
* functions in KooguWorker.
|
||||
* Test the koogu classifier and tests are working properly for a PAMGuard zip model - i.e. this is a very similar model to Koogu but zipped with a .zip
|
||||
* filename instead of .kgu.
|
||||
*/
|
||||
@Test
|
||||
public void zipClassifierTest() {
|
||||
@ -20,5 +20,8 @@ public class PamZipDLClassifierTest {
|
||||
//metadata says it should be used with Koogu classifier.
|
||||
KooguDLClassifierTest.runKooguClassifier( relModelPath, relWavPath, relMatPath);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -150,8 +150,7 @@ public class DBXMLConnect {
|
||||
*/
|
||||
public boolean postAndLog(Object nilusObject, String documentName) throws TethysException
|
||||
{
|
||||
boolean ok = NilusChecker.warnEmptyFields(tethysControl.getGuiFrame(), nilusObject);
|
||||
|
||||
// boolean ok = NilusChecker.warnEmptyFields(tethysControl.getGuiFrame(), nilusObject);
|
||||
|
||||
TethysException e = null;
|
||||
boolean success = false;
|
||||
|
@ -39,6 +39,9 @@ public class WMDDataSelector extends DataSelector {
|
||||
|
||||
@Override
|
||||
public double scoreData(PamDataUnit pamDataUnit) {
|
||||
if (getParams().getCombinationFlag() == DataSelectParams.DATA_SELECT_DISABLE) {
|
||||
return 1;
|
||||
}
|
||||
ConnectedRegionDataUnit crDataUnit = (ConnectedRegionDataUnit) pamDataUnit;
|
||||
return (wantWhistle(crDataUnit) ? 1: 0);
|
||||
}
|
||||
|