mirror of
https://github.com/PAMGuard/PAMGuard.git
synced 2025-05-14 02:47:53 +00:00
Merge branch 'main' of https://github.com/PAMGuard/PAMGuard
This commit is contained in:
commit
ccc59c7b79
README.html
src
PamView
PamguardMVC
Spectrogram
annotation
annotationMark/spectrogram
detectiongrouplocaliser
help/classifiers/whistleClassifierHelp/docs
mapgrouplocaliser
printscreen
rawDeepLearningClassifier
rocca
RoccaControl.javaRoccaGraphics.javaRoccaLoggingDataBlock.javaRoccaLoggingDataUnit.javaRoccaProcess.javaRoccaSymbolManager.java
tethys
134
README.html
134
README.html
@ -383,7 +383,7 @@ PAMGuardBeta_ViewerMode.exe):</p>
|
||||
<p class=MsoNormal><em><span style='font-family:"Calibri",sans-serif'> </span></em></p>
|
||||
|
||||
<h2><em><span style='font-size:12.0pt;font-family:"Cambria",serif;font-style:
|
||||
normal'><a href="#_Version_2.02.16_February">Latest Version 2.02.16 February
|
||||
normal'><a href="#_Version_2.02.16_February">Latest Version 2.02.16 March
|
||||
2025 </a></span></em></h2>
|
||||
|
||||
<h2><em><span style='font-size:12.0pt;font-family:"Cambria",serif;font-style:
|
||||
@ -434,7 +434,7 @@ 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><a name="_Version_2.02.14_October"></a><a
|
||||
name="_2.02.15_December_2014"></a><a name="_Version_2.02.16_February"></a>Version
|
||||
2.02.16 February 2025</h1>
|
||||
2.02.16 March 2025</h1>
|
||||
|
||||
<h2>New Features</h2>
|
||||
|
||||
@ -444,6 +444,11 @@ name="_2.02.15_December_2014"></a><a name="_Version_2.02.16_February"></a>Versio
|
||||
2 and Nilus 3.2. PAMGuard is no longer compatible with 3.1, the pre-release
|
||||
version. </p>
|
||||
|
||||
<p class=MsoNormal>Added Tethys functionality for the following modules:
|
||||
Whistle Classifier, Detection Group Localiser, Rocca, Click Train Detector, GPL
|
||||
Detector. IF the Detection Group Localiser is used with Logger Form
|
||||
annotations, species codes can be taken from the logger form. </p>
|
||||
|
||||
<p class=MsoNormal>Made export of data (Calibrations, Deployments, Detections,
|
||||
and Localisations) available as ‘offline tasks’. This is not useful when
|
||||
running Tethys on a single dataset, since all tasks can be easily performed
|
||||
@ -462,6 +467,14 @@ data to Tethys. </p>
|
||||
<p class=MsoNormal>Multiple management changes to support batch processing of
|
||||
offline tasks. Compatible with batch processor 2.0. </p>
|
||||
|
||||
<p class=MsoNormal>Added clip display for Deep Learning module.</p>
|
||||
|
||||
<p class=MsoNormal>Added optional display of impulse response function to IIR
|
||||
Filter design dialog in place of the pole-zero diagram. </p>
|
||||
|
||||
<p class=MsoNormal>Added ROCCA graphics, so ROCCA output can be displayed on
|
||||
the spectrogram display. </p>
|
||||
|
||||
<h2>Bug Fixes</h2>
|
||||
|
||||
<p class=MsoNormal>Issue 190. Array Files exported from array manager were not
|
||||
@ -481,7 +494,7 @@ time, meaning you got an invalid file path. This has been fixed. </p>
|
||||
channel list from acquisition module and automatically removes channels that
|
||||
were selected in the FFT module, but are not available from the acquisition. </p>
|
||||
|
||||
<p class=MsoNormal>Dealt with issue in Tethys module looking up IT IS species
|
||||
<p class=MsoNormal>Dealt with issue in Tethys module looking up ITIS species
|
||||
codes where the progress dialog would not close. </p>
|
||||
|
||||
<p class=MsoNormal>Project Information abstract field was not saving /
|
||||
@ -793,8 +806,8 @@ processing.</span></p>
|
||||
<h2><span lang=EN-US>New Features</span></h2>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US>New sound type for simulated sounds which
|
||||
generates random chirps between around 200 and 800Hz, roughly the frequency you'd
|
||||
expect sound from higher frequency baleen whales, such as humpbacks, to
|
||||
generates random chirps between around 200 and 800Hz, roughly the frequency
|
||||
you'd expect sound from higher frequency baleen whales, such as humpbacks, to
|
||||
vocalise at. </span></p>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US>Hiding tool tips. A menu item to
|
||||
@ -857,8 +870,8 @@ classifier was being trimmed. </span></p>
|
||||
|
||||
<p class=MsoNormal><b><span lang=EN-US>Documentation</span></b></p>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US>Comprehensive help file including description
|
||||
of the algorithm, screen grabs and examples.</span></p>
|
||||
<p class=MsoNormal><span lang=EN-US>Comprehensive help file including
|
||||
description of the algorithm, screen grabs and examples.</span></p>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US>Bug fixes</span></p>
|
||||
|
||||
@ -992,8 +1005,8 @@ href="http://www.PAMGuard.org/downloads.php?cat_id=3">here</a>.</p>
|
||||
<p class=MsoNormal><b><span lang=EN-US>Detection Group Localiser</span></b><span
|
||||
lang=EN-US> </span></p>
|
||||
|
||||
<p class=MsoNormal>This module has been renamed "Detection Grouper", so
|
||||
as to avoid confusion with the Group 3D localizer. This is because the
|
||||
<p class=MsoNormal>This module has been renamed "Detection Grouper",
|
||||
so as to avoid confusion with the Group 3D localizer. This is because the
|
||||
Detection Grouper is more for organizing data into groups to be localized than
|
||||
it is for doing localization.</p>
|
||||
|
||||
@ -1137,10 +1150,11 @@ name="_Latest_Beta_Version_2.01.05"></a><span lang=EN-US> </span></p>
|
||||
|
||||
<h1><span lang=EN-US>Version 2.01.05 October 2020</span></h1>
|
||||
|
||||
<p class=MsoNormal><b>If you are upgrading from a PAMGuard core release (1.15.xx),
|
||||
PAMGuard Version 2 contains major updates. You should read and understand the
|
||||
notes listed for <a href="#_Latest_Beta_Version_2.00.10">Beta Version 2.00.10</a>
|
||||
before proceeding with installation and use of this version.</b></p>
|
||||
<p class=MsoNormal><b>If you are upgrading from a PAMGuard core release
|
||||
(1.15.xx), PAMGuard Version 2 contains major updates. You should read and
|
||||
understand the notes listed for <a href="#_Latest_Beta_Version_2.00.10">Beta
|
||||
Version 2.00.10</a> before proceeding with installation and use of this
|
||||
version.</b></p>
|
||||
|
||||
<p class=MsoNormal>This version of PAMGuard has been bundled with Java 13
|
||||
(release 13.0.1). PSFX files generated in previous beta releases (2.xx.xx)
|
||||
@ -1706,8 +1720,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>7. </span><span
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>
|
||||
</span>Bug 420. The Click Classifier set was not getting updated properly in Viewer
|
||||
mode.</p>
|
||||
</span>Bug 420. The Click Classifier set was not getting updated properly in
|
||||
Viewer mode.</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'>
|
||||
@ -2018,9 +2032,9 @@ see new options in main menu.</p>
|
||||
|
||||
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>2. </span><span
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> </span><span
|
||||
lang=EN-US> </span>Added Matched Template Click Classifier. Classifies clicks based
|
||||
on an ideal template to match and a template to reject. An example of this is
|
||||
to classify beaked whale clicks in an environment with dolphin clicks.</p>
|
||||
lang=EN-US> </span>Added Matched Template Click Classifier. Classifies clicks
|
||||
based on an ideal template to match and a template to reject. An example of
|
||||
this is to classify beaked whale clicks in an environment with dolphin clicks.</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>
|
||||
@ -2614,9 +2628,9 @@ dependencies)</span></p>
|
||||
|
||||
<p class=MsoNormal><b><span lang=EN-US>Other Changes</span></b></p>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US>The installer has been updated to handle both
|
||||
64 bit and 32 bit installations. PAMGuard psf files are now registered in the
|
||||
Windows Registry, so double-clicking on a psf file should run PAMGuard in
|
||||
<p class=MsoNormal><span lang=EN-US>The installer has been updated to handle
|
||||
both 64 bit and 32 bit installations. PAMGuard psf files are now registered in
|
||||
the Windows Registry, so double-clicking on a psf file should run PAMGuard in
|
||||
normal mode (as opposed to Viewer or Mixed modes). Note that the Windows
|
||||
Registry can only hold a single executable reference for psf files; therefore,
|
||||
for users with multiple installations of PAMGuard, double-clicking on a psf
|
||||
@ -2768,10 +2782,10 @@ the online help. Users of the Click Detector will notice the following changes:<
|
||||
|
||||
<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><span lang=EN-US>There is now a choice of least squares and Simplex based
|
||||
algorithms for real-time animal tracking. The improved algorithms also provide
|
||||
better error information both for display on the map and for storage in the
|
||||
database. </span></p>
|
||||
</span><span lang=EN-US>There is now a choice of least squares and Simplex
|
||||
based algorithms for real-time animal tracking. The improved algorithms also
|
||||
provide better error information both for display on the map and for storage in
|
||||
the database. </span></p>
|
||||
|
||||
<p class=MsoListParagraph style='text-indent:-18.0pt'><span lang=EN-US>2.</span><span
|
||||
lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>
|
||||
@ -2812,8 +2826,8 @@ the future. </span></p>
|
||||
|
||||
<p class=MsoNormal><i>Logger Form Design</i></p>
|
||||
|
||||
<p class=MsoNormal>A GUI driven system for designing Logger forms has been
|
||||
released. Currently, this feature has no online help, but is reasonably intuitive
|
||||
<p class=MsoNormal>A GUI driven system for designing Logger forms has been released.
|
||||
Currently, this feature has no online help, but is reasonably intuitive
|
||||
compared to the old method of typing directly into the database. </p>
|
||||
|
||||
<p class=MsoNormal><i><span lang=EN-US>Improved Number handling</span></i></p>
|
||||
@ -3534,8 +3548,8 @@ module. </p>
|
||||
<p class=MsoNormal><i>Sound Recorder Module</i></p>
|
||||
|
||||
<p class=MsoNormal>Now supports writing 8 and 24 bit as well as 16 bit files.
|
||||
Also writes data to dated sub folders, starting a new folder each day (UTC). Also
|
||||
provides additional information on disk space on the main display panel.
|
||||
Also writes data to dated sub folders, starting a new folder each day (UTC).
|
||||
Also provides additional information on disk space on the main display panel.
|
||||
Millisecond time is also now included in the output file names. </p>
|
||||
|
||||
<p class=MsoNormal><i>Datagram Options</i></p>
|
||||
@ -3597,8 +3611,8 @@ whistle.</p>
|
||||
<li class=MsoNormal style='margin-bottom:0cm'>Airgun display. If this was
|
||||
included in the PAMGuard model before the GPS module it would hang
|
||||
PAMGuard. This has been rectified. </li>
|
||||
<li class=MsoNormal style='margin-bottom:0cm'>Fixed occasional exceptions in the
|
||||
sound output modules when playing back from files. </li>
|
||||
<li class=MsoNormal style='margin-bottom:0cm'>Fixed occasional exceptions in
|
||||
the sound output modules when playing back from files. </li>
|
||||
<li class=MsoNormal style='margin-bottom:0cm'>Fixed exceptions in spectrogram
|
||||
user interface. </li>
|
||||
<li class=MsoNormal style='margin-bottom:0cm'>Fixed National Instruments sound
|
||||
@ -3680,8 +3694,8 @@ other data sources for the PAMGuard viewer. </p>
|
||||
storage to the database offline for any module having both binary and database
|
||||
storage. </p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:36.0pt'>Can create a blank MS Access database
|
||||
(2007 and later *.accdb formats only).</p>
|
||||
<p class=MsoNormal style='margin-left:36.0pt'>Can create a blank MS Access
|
||||
database (2007 and later *.accdb formats only).</p>
|
||||
|
||||
<p class=MsoNormal style='margin-left:36.0pt'>Can open MS Access from within
|
||||
PAMGuard to make it easier to view database content. </p>
|
||||
@ -3764,8 +3778,8 @@ margin-left:36.0pt'> </p>
|
||||
<p class=MsoListParagraph style='margin-left:54.0pt;text-indent:-18.0pt'><i>Ishmael
|
||||
Detection Modules</i></p>
|
||||
|
||||
<p class=MsoListParagraph style='margin-left:54.0pt;text-indent:-18.0pt'>We
|
||||
have implemented database storage for output of these modules. </p>
|
||||
<p class=MsoListParagraph style='margin-left:54.0pt;text-indent:-18.0pt'>We have
|
||||
implemented database storage for output of these modules. </p>
|
||||
|
||||
<p class=MsoNormal><b>Bug fixes</b></p>
|
||||
|
||||
@ -3947,9 +3961,9 @@ length. </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'>
|
||||
</span>The filter module can now also generate finite Impulse Response (FIR)
|
||||
filters. Note however, that FIR filters may require considerably more execution
|
||||
time than IIR filters. </p>
|
||||
</span>The filter module can now also generate finite Impulse Response (FIR) filters.
|
||||
Note however, that FIR filters may require considerably more execution time
|
||||
than IIR filters. </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'>
|
||||
@ -4000,10 +4014,10 @@ source, even if that data source is loaded after the FFT module is created.</p>
|
||||
|
||||
<p class=MsoNormal>1. Binary storage module. </p>
|
||||
|
||||
<p class=MsoNormal>Performs a parallel role to the PAMGAURD database but uses binary
|
||||
files in a proprietary format which is considerably more efficient for data of
|
||||
unknown length such as whistle contours or small clips of click waveform. This
|
||||
feature is currently implemented in the following modules:</p>
|
||||
<p class=MsoNormal>Performs a parallel role to the PAMGAURD database but uses
|
||||
binary files in a proprietary format which is considerably more efficient for
|
||||
data of unknown length such as whistle contours or small clips of click
|
||||
waveform. This feature is currently implemented in the following modules:</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'>
|
||||
@ -4087,9 +4101,9 @@ and recording sounds to the default directory. </p>
|
||||
<p class=MsoNormal><b>Channel numbering</b></p>
|
||||
|
||||
<p class=MsoNormal>A new internal channel numbering scheme for ASIO sound cards
|
||||
was released on 8 March in Alpha version 1.8.02. These changes have now been promoted
|
||||
to this Beta release 1.9.00. These changes were described in an email to
|
||||
PAMGuard User, the text of which is repeated here:</p>
|
||||
was released on 8 March in Alpha version 1.8.02. These changes have now been
|
||||
promoted to this Beta release 1.9.00. These changes were described in an email
|
||||
to PAMGuard User, the text of which is repeated here:</p>
|
||||
|
||||
<p class=MsoNormal>Within PAMGuard, there have been constant problems with
|
||||
lookup tables relating hardware channel numbers to internal channel numbers.
|
||||
@ -4212,8 +4226,8 @@ column was setting to zero. This is now fixed</p>
|
||||
|
||||
<p class=MsoNormal>Ishmael Detectors</p>
|
||||
|
||||
<p class=MsoNormal>Better rendering of detection boxes on spectrogram display
|
||||
and more meaningful names in spectrogram display menu.</p>
|
||||
<p class=MsoNormal>Better rendering of detection boxes on spectrogram display and
|
||||
more meaningful names in spectrogram display menu.</p>
|
||||
|
||||
<p class=MsoNormal>Sound acquisition</p>
|
||||
|
||||
@ -4286,9 +4300,9 @@ Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif
|
||||
|
||||
<p class=MsoListParagraph style='text-indent:-18.0pt'><span style='font-family:
|
||||
Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>
|
||||
</span>False buffer overflows at low sample rates stopped (size of data in
|
||||
individual data blocks had been increased at low sample rates, but when this
|
||||
exceeded 3s a false buffer overflow would occur).</p>
|
||||
</span>False buffer overflows at low sample rates stopped (size of data in individual
|
||||
data blocks had been increased at low sample rates, but when this exceeded 3s a
|
||||
false buffer overflow would occur).</p>
|
||||
|
||||
<p class=MsoNormal> </p>
|
||||
|
||||
@ -4325,8 +4339,8 @@ will be displayed if you select them with the mouse.</p>
|
||||
|
||||
<p class=MsoListParagraph style='text-indent:-18.0pt'><span style='font-family:
|
||||
Symbol'>'</span><span style='font-size:7.0pt;font-family:"Times New Roman",serif'>
|
||||
</span>New click classifier methods, which include extraction of frequency sweep
|
||||
parameters. (Please note that this click is not yet documented. The old
|
||||
</span>New click classifier methods, which include extraction of frequency
|
||||
sweep parameters. (Please note that this click is not yet documented. The old
|
||||
classifier is still available). </p>
|
||||
|
||||
<p class=MsoListParagraph style='text-indent:-18.0pt'><span style='font-family:
|
||||
@ -4462,8 +4476,8 @@ them before proceeding with installation.</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'>
|
||||
</span>Installer now setting permissions on some of the default settings files
|
||||
so that under Vista they can still be written to without needed to be an
|
||||
</span>Installer now setting permissions on some of the default settings files so
|
||||
that under Vista they can still be written to without needed to be an
|
||||
Administrator</p>
|
||||
|
||||
<p class=MsoListParagraph style='text-indent:-18.0pt'><span style='font-family:
|
||||
@ -4536,10 +4550,10 @@ help pages</p>
|
||||
|
||||
<p class=MsoNormal><b>Bug Fixes</b></p>
|
||||
|
||||
<p class=MsoNormal>Memory leak caused by Night / Day colour manager now fixed. This
|
||||
would cause memory leaks when multiple files were being analysed off-line and
|
||||
would eventually crash PAMGuard. The way that colours are managed in PAMGuard
|
||||
has been rewritten. </p>
|
||||
<p class=MsoNormal>Memory leak caused by Night / Day colour manager now fixed.
|
||||
This would cause memory leaks when multiple files were being analysed off-line
|
||||
and would eventually crash PAMGuard. The way that colours are managed in
|
||||
PAMGuard has been rewritten. </p>
|
||||
|
||||
<p class=MsoNormal>Some issues with Swing fixed that might have been causing
|
||||
hang ups on startup especially on Macs/Linux machines</p>
|
||||
@ -4610,8 +4624,8 @@ file)</p>
|
||||
|
||||
<p class=MsoNormal><b>Changes</b></p>
|
||||
|
||||
<p class=MsoNormal>The User Input module (for text entry of information by the user)
|
||||
has been moved from the Displays sub menu of the Add Modules menu, to
|
||||
<p class=MsoNormal>The User Input module (for text entry of information by the
|
||||
user) has been moved from the Displays sub menu of the Add Modules menu, to
|
||||
Utilities. This will not affect how existing settings files are loaded. </p>
|
||||
|
||||
<p class=MsoNormal><b>Multi-screen environments.</b></p>
|
||||
|
@ -704,9 +704,13 @@ public class PamDetectionOverlayGraphics extends PanelOverlayDraw {
|
||||
double[] frequency = pamDetection.getFrequency();
|
||||
Coordinate3d topLeft = generalProjector.getCoord3d(pamDetection.getTimeMilliseconds(),
|
||||
frequency[1], 0);
|
||||
double dur = 0;
|
||||
Double duration = pamDetection.getDurationInMilliseconds();
|
||||
if (duration != null) {
|
||||
dur = duration;
|
||||
}
|
||||
Coordinate3d botRight = generalProjector.getCoord3d(pamDetection.getTimeMilliseconds() +
|
||||
pamDetection.getDurationInMilliseconds(),
|
||||
frequency[0], 0);
|
||||
dur, frequency[0], 0);
|
||||
|
||||
if (botRight.x < topLeft.x){
|
||||
botRight.x = g.getClipBounds().width;
|
||||
|
@ -303,6 +303,10 @@ abstract public class PamProcess implements PamObserver, ProcessAnnotator {
|
||||
* one. Otherwise Pamguard tends to get stuck in a loop of model change
|
||||
* notifications and setting of data blocks.
|
||||
*/
|
||||
boolean instant = (this instanceof PamInstantProcess);
|
||||
if (instant) {
|
||||
reThread = false;
|
||||
}
|
||||
if (parentDataBlock == newParentDataBlock) {
|
||||
return;
|
||||
}
|
||||
@ -312,7 +316,12 @@ abstract public class PamProcess implements PamObserver, ProcessAnnotator {
|
||||
}
|
||||
parentDataBlock = newParentDataBlock;
|
||||
if (parentDataBlock != null) {
|
||||
parentDataBlock.addObserver(this, PamModel.getPamModel().isMultiThread() & reThread);
|
||||
if (instant) {
|
||||
parentDataBlock.addInstantObserver(this);
|
||||
}
|
||||
else {
|
||||
parentDataBlock.addObserver(this, PamModel.getPamModel().isMultiThread() & reThread);
|
||||
}
|
||||
// acousticDataSource = AcousticDataUnit.class.isAssignableFrom(parentDataBlock.getUnitClass());
|
||||
// parentProcess = parentDataBlock.getParentProcess();
|
||||
PamProcess pp = parentDataBlock.getParentProcess();
|
||||
|
@ -2973,7 +2973,7 @@ InternalFrameListener, DisplayPanelContainer, SpectrogramParametersUser, PamSett
|
||||
}
|
||||
int wantedMap = 1<<spectrogramParameters.channelList[panelId];
|
||||
int dataChanMap = dataUnit.getSequenceBitmap();
|
||||
if ((wantedMap & dataChanMap) == 0) {
|
||||
if (dataChanMap != 0 && (wantedMap & dataChanMap) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (dataSelector != null && dataSelector.scoreData(dataUnit) <= 0) {
|
||||
|
@ -31,7 +31,7 @@ public class CentralAnnotationsList {
|
||||
singleInstance.addAnnotationType(new SNRAnnotationType());
|
||||
singleInstance.addAnnotationType(new SPLAnnotationType());
|
||||
singleInstance.addAnnotationType(new TMAnnotationType());
|
||||
singleInstance.addAnnotationType(new UserFormAnnotationType());
|
||||
singleInstance.addAnnotationType(new UserFormAnnotationType(null));
|
||||
singleInstance.addAnnotationType(new WavAnnotationType());
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package annotation;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import PamView.symbol.PamSymbolChooser;
|
||||
import PamView.symbol.modifier.SymbolModifier;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
@ -13,6 +11,7 @@ import annotation.handler.AnnotationOptions;
|
||||
import annotation.xml.AnnotationXMLWriter;
|
||||
import annotation.xml.SQLXMLWriter;
|
||||
import generalDatabase.SQLLoggingAddon;
|
||||
import tethys.species.DataBlockSpeciesManager;
|
||||
|
||||
/**
|
||||
* Something that can tell us a little more about
|
||||
@ -230,5 +229,13 @@ public abstract class DataAnnotationType<TDataAnnotation extends DataAnnotation<
|
||||
this.targetDataBlock = targetDataBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Annotations may have a species manager. Most won't.
|
||||
* @return
|
||||
*/
|
||||
public DataBlockSpeciesManager getDataBlockSpeciesManager() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ public class ManualAnnotationHandler extends OneStopAnnotationHandler {
|
||||
@Override
|
||||
public void createAnnotationTypes() {
|
||||
addAnnotationType(new StringAnnotationType("Text Annotation", 80));
|
||||
addAnnotationType(new UserFormAnnotationType());
|
||||
addAnnotationType(new UserFormAnnotationType(getPamDataBlock()));
|
||||
// now try to add their parameters.
|
||||
AnnotationChoices annotationChoices = getAnnotationChoices();
|
||||
if (annotationChoices == null) {
|
||||
|
@ -4,6 +4,7 @@ import PamController.PamController;
|
||||
import PamView.symbol.AnnotationSymbolChooser;
|
||||
import PamView.symbol.PamSymbolChooser;
|
||||
import PamView.symbol.modifier.SymbolModifier;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
import annotation.AnnotationDialogPanel;
|
||||
import annotation.AnnotationSettingsPanel;
|
||||
import annotation.DataAnnotationType;
|
||||
@ -11,6 +12,7 @@ import annotation.binary.AnnotationBinaryHandler;
|
||||
import annotation.dataselect.AnnotationDataSelCreator;
|
||||
import annotation.handler.AnnotationOptions;
|
||||
import annotation.userforms.datasel.UserFormDataSelCreator;
|
||||
import annotation.userforms.species.FormsAnnotationSpeciesManager;
|
||||
import annotation.xml.AnnotationXMLWriter;
|
||||
import annotation.xml.SQLXMLWriter;
|
||||
import generalDatabase.DBControlUnit;
|
||||
@ -18,6 +20,7 @@ import generalDatabase.SQLLoggingAddon;
|
||||
import loggerForms.FormDescription;
|
||||
import loggerForms.FormsControl;
|
||||
import loggerForms.LoggerForm;
|
||||
import tethys.species.DataBlockSpeciesManager;
|
||||
|
||||
public class UserFormAnnotationType extends DataAnnotationType<UserFormAnnotation<?>> {
|
||||
|
||||
@ -39,11 +42,18 @@ public class UserFormAnnotationType extends DataAnnotationType<UserFormAnnotatio
|
||||
private UserFormBinaryHandler userFormBinaryHandler;
|
||||
|
||||
private UserFormDataSelCreator userFormDataSelCreator;
|
||||
|
||||
private FormsAnnotationSpeciesManager formsAnnotationSpeciesManager;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public UserFormAnnotationType() {
|
||||
this(null);
|
||||
}
|
||||
public UserFormAnnotationType(PamDataBlock pamDataBlock) {
|
||||
super();
|
||||
setTargetDataBlock(pamDataBlock);
|
||||
userFormAnnotationOptions = new UserFormAnnotationOptions(getAnnotationName());
|
||||
userFormSQLAddon = new UserFormSQLAddon(this);
|
||||
|
||||
@ -231,4 +241,12 @@ public class UserFormAnnotationType extends DataAnnotationType<UserFormAnnotatio
|
||||
// TODO Auto-generated method stub
|
||||
return new SQLXMLWriter<>(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataBlockSpeciesManager getDataBlockSpeciesManager() {
|
||||
if (formsAnnotationSpeciesManager == null) {
|
||||
formsAnnotationSpeciesManager = new FormsAnnotationSpeciesManager(this, getTargetDataBlock());
|
||||
}
|
||||
return formsAnnotationSpeciesManager;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,145 @@
|
||||
package annotation.userforms.species;
|
||||
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Vector;
|
||||
|
||||
import PamController.PamControlledUnitSettings;
|
||||
import PamController.PamSettingManager;
|
||||
import PamController.PamSettings;
|
||||
import PamView.dialog.PamDialogPanel;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
import PamguardMVC.PamDataUnit;
|
||||
import annotation.userforms.UserFormAnnotation;
|
||||
import annotation.userforms.UserFormAnnotationType;
|
||||
import generalDatabase.lookupTables.LookupItem;
|
||||
import generalDatabase.lookupTables.LookupList;
|
||||
import loggerForms.controlDescriptions.CdLookup;
|
||||
import loggerForms.controlDescriptions.ControlTypes;
|
||||
import loggerForms.controlDescriptions.InputControlDescription;
|
||||
import tethys.species.DataBlockSpeciesCodes;
|
||||
import tethys.species.DataBlockSpeciesManager;
|
||||
import tethys.species.SpeciesManagerObserver;
|
||||
|
||||
public class FormsAnnotationSpeciesManager extends DataBlockSpeciesManager implements PamSettings {
|
||||
|
||||
private UserFormAnnotationType userFormAnnotationType;
|
||||
|
||||
private FormsSpeciesSettings speciesSettings = new FormsSpeciesSettings();
|
||||
|
||||
private FormsAnnotationSpeciesCodes speciesCodes;
|
||||
|
||||
public FormsAnnotationSpeciesManager(UserFormAnnotationType userFormAnnotationType, PamDataBlock dataBlock) {
|
||||
super(dataBlock);
|
||||
this.userFormAnnotationType = userFormAnnotationType;
|
||||
this.speciesCodes = new FormsAnnotationSpeciesCodes();
|
||||
PamSettingManager.getInstance().registerSettings(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataBlockSpeciesCodes getSpeciesCodes() {
|
||||
return speciesCodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSpeciesCode(PamDataUnit dataUnit) {
|
||||
UserFormAnnotation annot = (UserFormAnnotation) dataUnit.findDataAnnotation(userFormAnnotationType.getAnnotationClass());
|
||||
if (annot == null) {
|
||||
return null;
|
||||
}
|
||||
// now find the control with the right name.
|
||||
Object data[] = annot.getLoggerFormData();
|
||||
int ind = getLoggerItemIndex();
|
||||
if (ind < 0 || ind > data.length) {
|
||||
return null;
|
||||
}
|
||||
Object dat = data[ind];
|
||||
if (dat == null) {
|
||||
return null;
|
||||
}
|
||||
return dat.toString();
|
||||
}
|
||||
|
||||
private int getLoggerItemIndex() {
|
||||
int ctrlInd = userFormAnnotationType.getFormDescription().findInputControlByName(speciesSettings.selectedControl);
|
||||
return ctrlInd;
|
||||
}
|
||||
|
||||
public class FormsAnnotationSpeciesCodes extends DataBlockSpeciesCodes {
|
||||
|
||||
public FormsAnnotationSpeciesCodes() {
|
||||
super(null);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getSpeciesNames() {
|
||||
int ctrlInd = userFormAnnotationType.getFormDescription().findInputControlByName(speciesSettings.selectedControl);
|
||||
ArrayList<InputControlDescription> ipControls = userFormAnnotationType.getFormDescription().getInputControlDescriptions();
|
||||
if (ctrlInd < 0 || ctrlInd >= ipControls.size()) {
|
||||
return null;
|
||||
}
|
||||
InputControlDescription ipCD = ipControls.get(ctrlInd);
|
||||
if (ipCD.getEType() != ControlTypes.LOOKUP) {
|
||||
return null;
|
||||
}
|
||||
CdLookup lutCtrl = (CdLookup) ipCD;
|
||||
LookupList lutList = lutCtrl.getLookupList();
|
||||
Vector<LookupItem> lutItems = lutList.getList();
|
||||
ArrayList<String> names = new ArrayList<>();
|
||||
for (int i = 0; i < lutItems.size(); i++) {
|
||||
names.add(lutItems.get(i).getCode());
|
||||
}
|
||||
return names;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PamDialogPanel getDialogPanel(SpeciesManagerObserver speciesManagerObserver) {
|
||||
return new FormsSpeciesOptionsPanel(this, speciesManagerObserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUnitName() {
|
||||
return userFormAnnotationType.getTargetDataBlock().getLongDataName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUnitType() {
|
||||
return "Forms Annotion Species Settings";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getSettingsReference() {
|
||||
return speciesSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSettingsVersion() {
|
||||
return FormsSpeciesSettings.serialVersionUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
|
||||
speciesSettings = (FormsSpeciesSettings) pamControlledUnitSettings.getSettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the userFormAnnotationType
|
||||
*/
|
||||
public UserFormAnnotationType getUserFormAnnotationType() {
|
||||
return userFormAnnotationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the speciesSettings
|
||||
*/
|
||||
public FormsSpeciesSettings getSpeciesSettings() {
|
||||
return speciesSettings;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package annotation.userforms.species;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import PamView.dialog.PamDialogPanel;
|
||||
import PamView.dialog.PamGridBagContraints;
|
||||
import annotation.userforms.UserFormAnnotationType;
|
||||
import loggerForms.controlDescriptions.ControlTypes;
|
||||
import loggerForms.controlDescriptions.InputControlDescription;
|
||||
import tethys.species.SpeciesManagerObserver;
|
||||
|
||||
public class FormsSpeciesOptionsPanel implements PamDialogPanel {
|
||||
|
||||
private UserFormAnnotationType userFormAnnotationType;
|
||||
private FormsAnnotationSpeciesManager formsAnnotationSpeciesManager;
|
||||
|
||||
private JPanel mainPanel;
|
||||
private JComboBox<String> lookups;
|
||||
private SpeciesManagerObserver speciesManagerObserver;
|
||||
|
||||
private static final String tip = "User Forms annotation species selection options. Select any LOOKUP type control as species";
|
||||
|
||||
public FormsSpeciesOptionsPanel(FormsAnnotationSpeciesManager formsAnnotationSpeciesManager, SpeciesManagerObserver speciesManagerObserver) {
|
||||
this.formsAnnotationSpeciesManager = formsAnnotationSpeciesManager;
|
||||
this.userFormAnnotationType = formsAnnotationSpeciesManager.getUserFormAnnotationType();
|
||||
this.speciesManagerObserver = speciesManagerObserver;
|
||||
|
||||
mainPanel = new JPanel(new GridBagLayout());
|
||||
GridBagConstraints c = new PamGridBagContraints();
|
||||
JLabel label;
|
||||
mainPanel.add(label = new JLabel("User form control for species ", JLabel.RIGHT), c);
|
||||
lookups = new JComboBox<>();
|
||||
lookups.setToolTipText("Select a drop down list that you use for species identity");
|
||||
c.gridx++;
|
||||
mainPanel.add(lookups, c);
|
||||
// fill with names of controls that are lookups.
|
||||
lookups.addItem("--no selection--");
|
||||
ArrayList<InputControlDescription> ipControls = userFormAnnotationType.getFormDescription().getInputControlDescriptions();
|
||||
for (InputControlDescription aCtrl : ipControls) {
|
||||
if (aCtrl.getEType() != ControlTypes.LOOKUP) {
|
||||
continue;
|
||||
}
|
||||
lookups.addItem(aCtrl.getTitle());
|
||||
}
|
||||
label.setToolTipText(tip);
|
||||
lookups.setToolTipText(tip);
|
||||
setParams();
|
||||
}
|
||||
|
||||
protected void selectionChanged() {
|
||||
getParams();
|
||||
if (speciesManagerObserver != null) {
|
||||
speciesManagerObserver.update();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getDialogComponent() {
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParams() {
|
||||
String sel = formsAnnotationSpeciesManager.getSpeciesSettings().selectedControl;
|
||||
if (sel != null) {
|
||||
lookups.setSelectedItem(sel);
|
||||
}
|
||||
lookups.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
selectionChanged();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getParams() {
|
||||
String item = (String) lookups.getSelectedItem();
|
||||
formsAnnotationSpeciesManager.getSpeciesSettings().selectedControl = item;
|
||||
return (item != null);
|
||||
}
|
||||
|
||||
}
|
25
src/annotation/userforms/species/FormsSpeciesSettings.java
Normal file
25
src/annotation/userforms/species/FormsSpeciesSettings.java
Normal file
@ -0,0 +1,25 @@
|
||||
package annotation.userforms.species;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class FormsSpeciesSettings implements Cloneable, Serializable{
|
||||
|
||||
|
||||
public static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Control used for species selection - will be a dropdown.
|
||||
*/
|
||||
public String selectedControl;
|
||||
|
||||
@Override
|
||||
protected FormsSpeciesSettings clone() {
|
||||
try {
|
||||
return (FormsSpeciesSettings) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -70,7 +70,7 @@ public class SpectrogramAnnotationModule extends MarkModule implements PamSettin
|
||||
annotationHandler.addAnnotationType(splAnnotationType =new SPLAnnotationType());
|
||||
annotationHandler.addAnnotationType(stringAnnotationType = new StringAnnotationType("Note", 50));
|
||||
annotationHandler.addAnnotationType(labelAnnotationType = new StringAnnotationType("Label", 50));
|
||||
annotationHandler.addAnnotationType(new UserFormAnnotationType());
|
||||
annotationHandler.addAnnotationType(new UserFormAnnotationType(getAnnotationProcess().getMarkDataBlock()));
|
||||
// spectrogramMarkObserver = new SpecMarkObserver();
|
||||
// SpectrogramMarkObservers.addSpectrogramMarkObserver(spectrogramMarkObserver);
|
||||
|
||||
|
@ -24,6 +24,8 @@ import annotation.DataAnnotationType;
|
||||
import detectiongrouplocaliser.dialogs.DetectionGroupDialog;
|
||||
import detectiongrouplocaliser.dialogs.DetectionGroupTableProvider;
|
||||
import detectiongrouplocaliser.dialogs.DisplayOptionsHandler;
|
||||
import detectiongrouplocaliser.tethys.DetectionGroupSpeciesManager;
|
||||
import tethys.species.DataBlockSpeciesManager;
|
||||
import userDisplay.UserDisplayControl;
|
||||
|
||||
/**
|
||||
@ -46,6 +48,8 @@ public class DetectionGroupControl extends PamControlledUnit implements PamSetti
|
||||
|
||||
private DisplayOptionsHandler displayOptionsHandler;
|
||||
|
||||
private DetectionGroupSpeciesManager detectionGroupSpeciesManager;
|
||||
|
||||
public DetectionGroupControl(String unitName) {
|
||||
super(unitType, unitName);
|
||||
this.detectionGroupProcess = new DetectionGroupProcess(this);
|
||||
@ -186,4 +190,25 @@ public class DetectionGroupControl extends PamControlledUnit implements PamSetti
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public DataBlockSpeciesManager<DetectionGroupDataUnit> getDataBlockSpeciesManager() {
|
||||
DetectionGroupDataBlock dataBlock = detectionGroupProcess.getDetectionGroupDataBlock();
|
||||
if (detectionGroupSpeciesManager == null) {
|
||||
detectionGroupSpeciesManager = new DetectionGroupSpeciesManager(dataBlock);
|
||||
}
|
||||
// see if any of the annotations have a species manager and use that by preference.
|
||||
GroupAnnotationHandler annHandler = detectionGroupProcess.getAnnotationHandler();
|
||||
if (annHandler == null) {
|
||||
return detectionGroupSpeciesManager;
|
||||
}
|
||||
List<DataAnnotationType<?>> usedAnnotations = annHandler.getUsedAnnotationTypes();
|
||||
for (DataAnnotationType<?> aType : usedAnnotations) {
|
||||
DataBlockSpeciesManager sppManager = aType.getDataBlockSpeciesManager();
|
||||
if (sppManager != null) {
|
||||
return sppManager;
|
||||
}
|
||||
}
|
||||
return detectionGroupSpeciesManager;
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,6 @@ public class DetectionGroupDataBlock extends SuperDetDataBlock<DetectionGroupDat
|
||||
|
||||
private DetectionGroupTethysProvider detectionGroupTethysProvider;
|
||||
|
||||
private DetectionGroupSpeciesManager detectionGroupSpeciesManager;
|
||||
|
||||
private DetectionGroupControl detectionGroupControl;
|
||||
|
||||
public DetectionGroupDataBlock(String dataName, DetectionGroupControl detectionGroupControl, DetectionGroupProcess detectionGroupProcess) {
|
||||
@ -119,10 +117,7 @@ public class DetectionGroupDataBlock extends SuperDetDataBlock<DetectionGroupDat
|
||||
|
||||
@Override
|
||||
public DataBlockSpeciesManager<DetectionGroupDataUnit> getDatablockSpeciesManager() {
|
||||
if (detectionGroupSpeciesManager == null) {
|
||||
detectionGroupSpeciesManager = new DetectionGroupSpeciesManager(this);
|
||||
}
|
||||
return detectionGroupSpeciesManager;
|
||||
return detectionGroupControl.getDataBlockSpeciesManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ public class GroupAnnotationHandler extends AnnotationChoiceHandler {
|
||||
super(pamDataBlock);
|
||||
this.detectionGroupControl = detectionGroupControl;
|
||||
addAnnotationType(new StringAnnotationType("Text Annotation", 80));
|
||||
addAnnotationType(new UserFormAnnotationType());
|
||||
addAnnotationType(new UserFormAnnotationType(pamDataBlock));
|
||||
addAnnotationType(new TMAnnotationType());
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,12 @@ web site, it is highly likely that whistles of a given species will vary between
|
||||
regions and sub species and may also evolve over time. The Whistle Classifier therefore
|
||||
allows you to train it using your own samples of whistles from known species.</p>
|
||||
|
||||
<p>The workings of the classifier are described in the paper
|
||||
Douglas Gillespie, Marjolaine Caillat, Jonathan Gordon, Paul White; Automatic detection and classification of odontocete whistles.
|
||||
J. Acoust. Soc. Am. 1 September 2013; 134 (3): 2427–2437. <a href="https://doi.org/10.1121/1.4816555">DOI 10.1121/1.4816555</a> </p>
|
||||
<p>Trained classifier models from the paper, which can be imported into your own PAMGuard configuration are
|
||||
available at <a href="https://www.pamguard.org/whistleclassifier.html">www.pamguard.org/whistleclassifier.html</a>.
|
||||
|
||||
|
||||
<h3>Creating a Whistle Classifier</h3>
|
||||
<p>From the <strong><em>File>Add modules>Detectors</em></strong>
|
||||
|
@ -15,7 +15,7 @@ public class MapGroupAnnotationHandler extends AnnotationChoiceHandler {
|
||||
super(pamDataBlock);
|
||||
this.mapGroupLocaliserControl = mapGroupLocaliserControl;
|
||||
addAnnotationType(new StringAnnotationType("Text Annotation", 80));
|
||||
addAnnotationType(new UserFormAnnotationType());
|
||||
addAnnotationType(new UserFormAnnotationType(mapGroupLocaliserControl.getMarkGroupProcess().getMarkGroupDataBlock()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -241,4 +241,11 @@ public class MarkGroupProcess extends PamProcess implements OverlayMarkObserver
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the markGroupDataBlock
|
||||
*/
|
||||
public MarkGroupDataBlock getMarkGroupDataBlock() {
|
||||
return markGroupDataBlock;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ public class PrintScreenControl extends PamControlledUnit implements PamSettings
|
||||
annotationHandler = new PrintScreenAnnotationChoiceHandler(this, printScreenDataBlock);
|
||||
printScreenDataBlock.setAnnotationHandler(annotationHandler);
|
||||
printScreenDataBlock.addDataAnnotationType(new StringAnnotationType("Comment", 50));
|
||||
printScreenDataBlock.addDataAnnotationType(new UserFormAnnotationType());
|
||||
printScreenDataBlock.addDataAnnotationType(new UserFormAnnotationType(printScreenDataBlock));
|
||||
|
||||
PamSettingManager.getInstance().registerSettings(this);
|
||||
}
|
||||
|
@ -26,6 +26,11 @@ import PamguardMVC.dataSelector.DataSelector;
|
||||
import ai.djl.engine.Engine;
|
||||
import annotation.handler.AnnotationHandler;
|
||||
import clickTrainDetector.layout.ClickTrainSymbolManager;
|
||||
import clipgenerator.ClipDataUnit;
|
||||
import clipgenerator.ClipDisplayDataBlock;
|
||||
import clipgenerator.clipDisplay.ClipDisplayDecorations;
|
||||
import clipgenerator.clipDisplay.ClipDisplayParent;
|
||||
import clipgenerator.clipDisplay.ClipDisplayUnit;
|
||||
import dataPlotsFX.data.TDDataProviderRegisterFX;
|
||||
import detectionPlotFX.data.DDPlotRegister;
|
||||
import generalDatabase.SQLLoggingAddon;
|
||||
@ -41,6 +46,7 @@ import rawDeepLearningClassifier.dlClassification.DLClassNameManager;
|
||||
import rawDeepLearningClassifier.dlClassification.DLClassiferModel;
|
||||
import rawDeepLearningClassifier.dlClassification.DLClassifierChooser;
|
||||
import rawDeepLearningClassifier.dlClassification.DLClassifyProcess;
|
||||
import rawDeepLearningClassifier.dlClassification.DLDetectionDataBlock;
|
||||
import rawDeepLearningClassifier.dlClassification.animalSpot.SoundSpotClassifier;
|
||||
import rawDeepLearningClassifier.dlClassification.archiveModel.PamZipModelClassifier;
|
||||
import rawDeepLearningClassifier.dlClassification.delphinID.DelphinIDClassifier;
|
||||
@ -63,6 +69,9 @@ import rawDeepLearningClassifier.logging.DLResultBinarySource;
|
||||
import rawDeepLearningClassifier.logging.DLResultLogging;
|
||||
import rawDeepLearningClassifier.offline.DLOfflineProcess;
|
||||
import rawDeepLearningClassifier.segmenter.SegmenterProcess;
|
||||
import rawDeepLearningClassifier.swing.DLClipDecorations;
|
||||
import rawDeepLearningClassifier.swing.DLClipDisplayProvider;
|
||||
import userDisplay.UserDisplayControl;
|
||||
|
||||
/**
|
||||
* Module which uses an external deep learning classifier to identify any data
|
||||
@ -107,7 +116,7 @@ import rawDeepLearningClassifier.segmenter.SegmenterProcess;
|
||||
* @author Jamie Macaulay
|
||||
*
|
||||
*/
|
||||
public class DLControl extends PamControlledUnit implements PamSettings {
|
||||
public class DLControl extends PamControlledUnit implements PamSettings, ClipDisplayParent {
|
||||
|
||||
/**
|
||||
* PLUGIN_BUILD boolean is set to true so that the class loader isn't changed. When
|
||||
@ -367,6 +376,8 @@ public class DLControl extends PamControlledUnit implements PamSettings {
|
||||
//create the classiifer chooser.
|
||||
dlClassifierChooser = new DLClassifierChooser(this);
|
||||
|
||||
UserDisplayControl.addUserDisplayProvider(new DLClipDisplayProvider(this));
|
||||
|
||||
// ensure everything is updated.
|
||||
updateParams(rawDLParmas);
|
||||
}
|
||||
@ -742,6 +753,34 @@ public class DLControl extends PamControlledUnit implements PamSettings {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ClipDisplayDataBlock<ClipDataUnit> getClipDataBlock() {
|
||||
|
||||
Object dlBlock = dlClassifyProcess.getDLDetectionDatablock();
|
||||
ClipDisplayDataBlock<ClipDataUnit> clipBlock = (ClipDisplayDataBlock<ClipDataUnit>) dlBlock;
|
||||
return clipBlock;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return getUnitName() + " Clips";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ClipDisplayDecorations getClipDecorations(ClipDisplayUnit clipDisplayUnit) {
|
||||
return new DLClipDecorations(this, clipDisplayUnit);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void displaySettingChange() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -13,7 +13,9 @@ import PamguardMVC.DataUnitBaseData;
|
||||
import PamguardMVC.PamDataUnit;
|
||||
import PamguardMVC.PamInstantProcess;
|
||||
import PamguardMVC.PamObservable;
|
||||
import PamguardMVC.PamProcess;
|
||||
import binaryFileStorage.DataUnitFileInformation;
|
||||
import clipgenerator.ClipProcess;
|
||||
import pamScrollSystem.AbstractScrollManager;
|
||||
import rawDeepLearningClassifier.DLControl;
|
||||
import rawDeepLearningClassifier.RawDLParams;
|
||||
@ -39,7 +41,7 @@ import rawDeepLearningClassifier.segmenter.SegmenterDetectionGroup;
|
||||
* @author Jamie Macaulay
|
||||
*
|
||||
*/
|
||||
public class DLClassifyProcess extends PamInstantProcess {
|
||||
public class DLClassifyProcess extends PamProcess {
|
||||
|
||||
|
||||
/**
|
||||
@ -95,7 +97,7 @@ public class DLClassifyProcess extends PamInstantProcess {
|
||||
private DLGroupDataBlock dlGroupDetectionDataBlock;
|
||||
|
||||
public DLClassifyProcess(DLControl dlControl, SegmenterDataBlock parentDataBlock) {
|
||||
super(dlControl);
|
||||
super(dlControl, null);
|
||||
|
||||
this.setParentDataBlock(parentDataBlock);
|
||||
|
||||
@ -689,7 +691,7 @@ public class DLClassifyProcess extends PamInstantProcess {
|
||||
basicData.setSampleDuration((long) (groupDataBuffer.size()*dlControl.getDLParams().rawSampleSize));
|
||||
|
||||
// System.out.println("Model result: " + modelResult.size());
|
||||
DLDetection dlDetection = new DLDetection(basicData, rawdata);
|
||||
DLDetection dlDetection = new DLDetection(basicData, rawdata, getSampleRate());
|
||||
addDLAnnotation(dlDetection,modelResult);
|
||||
|
||||
//create the data unit
|
||||
|
@ -12,6 +12,7 @@ import PamguardMVC.RawDataHolder;
|
||||
import PamguardMVC.RawDataTransforms;
|
||||
import annotation.DataAnnotation;
|
||||
import bearinglocaliser.annotation.BearingAnnotation;
|
||||
import clipgenerator.ClipDataUnit;
|
||||
import clipgenerator.ClipSpectrogram;
|
||||
import rawDeepLearningClassifier.logging.DLAnnotation;
|
||||
|
||||
@ -23,7 +24,7 @@ import rawDeepLearningClassifier.logging.DLAnnotation;
|
||||
* @author Jamie Macaulay
|
||||
*
|
||||
*/
|
||||
public class DLDetection extends PamDataUnit implements PamDetection, RawDataHolder {
|
||||
public class DLDetection extends ClipDataUnit implements PamDetection, RawDataHolder {
|
||||
|
||||
/**
|
||||
* The abstract localisation
|
||||
@ -51,8 +52,8 @@ public class DLDetection extends PamDataUnit implements PamDetection, RawDataHol
|
||||
*/
|
||||
@Deprecated
|
||||
public DLDetection(long timeMilliseconds, int channelBitmap, long startSample, long durationSamples,
|
||||
ArrayList<PredictionResult> modelResults, double[][] waveData) {
|
||||
super(timeMilliseconds, channelBitmap, startSample, durationSamples);
|
||||
ArrayList<PredictionResult> modelResults, double[][] waveData, float sampleRate) {
|
||||
super(timeMilliseconds, timeMilliseconds, startSample, (int) durationSamples, channelBitmap, null, null, waveData, sampleRate);
|
||||
DLAnnotation annotation = new DLAnnotation(null, modelResults);
|
||||
this.addDataAnnotation(annotation);
|
||||
this.waveData=waveData;
|
||||
@ -68,9 +69,17 @@ public class DLDetection extends PamDataUnit implements PamDetection, RawDataHol
|
||||
* @param probdata - the probability data.
|
||||
* @param waveData - the wave data.
|
||||
*/
|
||||
public DLDetection(DataUnitBaseData baseData, double[][] waveData) {
|
||||
super(baseData);
|
||||
//System.out.println("Load DL deteciton: " + this.getChannelBitmap());
|
||||
public DLDetection(DataUnitBaseData baseData, double[][] waveData, float sampleRate) {
|
||||
// super(baseData);
|
||||
/*
|
||||
* public ClipDataUnit(long timeMilliseconds, long triggerMilliseconds,
|
||||
long startSample, int durationSamples, int channelMap, String fileName,
|
||||
String triggerName, double[][] rawData, float sourceSampleRate) {
|
||||
super(timeMilliseconds, channelMap, startSample, durationSamples);
|
||||
*/
|
||||
super(baseData.getTimeMilliseconds(), baseData.getTimeMilliseconds(), baseData.getStartSample(), waveData == null ? 0 : waveData[0].length, baseData.getChannelBitmap(), null,
|
||||
null, waveData, sampleRate);
|
||||
//System.out.println("Load DL detection: " + this.getChannelBitmap());
|
||||
this.waveData=waveData;
|
||||
rawDataTransforms= new RawDataTransforms(this);
|
||||
setAmplitude();//must set amplitude as this is not stored in binary files.
|
||||
@ -139,7 +148,7 @@ public class DLDetection extends PamDataUnit implements PamDetection, RawDataHol
|
||||
* @param channel
|
||||
* @return
|
||||
*/
|
||||
private double[] getWaveData(int channel) {
|
||||
public double[] getWaveData(int channel) {
|
||||
if (waveData!=null) {
|
||||
return this.getWaveData()[channel];
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import PamView.GroupedSourceParameters;
|
||||
import PamguardMVC.AcousticDataBlock;
|
||||
import PamguardMVC.dataSelector.DataSelectorCreator;
|
||||
import clickTrainDetector.dataselector.CTDataSelectCreator;
|
||||
import clipgenerator.ClipDataBlock;
|
||||
import clipgenerator.ClipDisplayDataBlock;
|
||||
import rawDeepLearningClassifier.DLControl;
|
||||
import rawDeepLearningClassifier.dataSelector.DLDataSelectCreator;
|
||||
import rawDeepLearningClassifier.tethys.DLSpeciesManager;
|
||||
@ -19,7 +21,7 @@ import tethys.species.DataBlockSpeciesManager;
|
||||
* @author Jamie Macaulay
|
||||
*
|
||||
*/
|
||||
public class DLDetectionDataBlock extends AcousticDataBlock<DLDetection> implements GroupedDataSource {
|
||||
public class DLDetectionDataBlock extends ClipDisplayDataBlock<DLDetection> implements GroupedDataSource {
|
||||
|
||||
/**
|
||||
* Reference to the deep learning classifier process.
|
||||
|
@ -198,7 +198,7 @@ public class OrcaSpotClassifier implements DLClassiferModel, PamSettings {
|
||||
modelResults.add(modelResult);
|
||||
dlControl.getDLClassifyProcess().getDLDetectionDatablock().addPamData(new DLDetection(groupedRawData.getTimeMilliseconds(),
|
||||
groupedRawData.getChannelBitmap(), groupedRawData.getStartSample(),
|
||||
groupedRawData.getSampleDuration(), modelResults, null));
|
||||
groupedRawData.getSampleDuration(), modelResults, null, dlControl.getDLClassifyProcess().getSampleRate()));
|
||||
}
|
||||
|
||||
groupedRawData= null; //just in case
|
||||
|
@ -134,7 +134,7 @@ public class DLDetectionBinarySource extends BinaryDataSource {
|
||||
if (baseData.getChannelBitmap()==0) {
|
||||
baseData.setChannelBitmap(1);
|
||||
}
|
||||
DLDetection newUnit = new DLDetection(baseData, rawData);
|
||||
DLDetection newUnit = new DLDetection(baseData, rawData, clipDataBlock.getSampleRate());
|
||||
|
||||
return newUnit;
|
||||
}
|
||||
|
85
src/rawDeepLearningClassifier/swing/DLClipDecorations.java
Normal file
85
src/rawDeepLearningClassifier/swing/DLClipDecorations.java
Normal file
@ -0,0 +1,85 @@
|
||||
package rawDeepLearningClassifier.swing;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import PamView.dialog.PamGridBagContraints;
|
||||
import clipgenerator.clipDisplay.ClipDisplayDecorations;
|
||||
import clipgenerator.clipDisplay.ClipDisplayUnit;
|
||||
import rawDeepLearningClassifier.DLControl;
|
||||
import rawDeepLearningClassifier.dlClassification.DLDetection;
|
||||
import rawDeepLearningClassifier.dlClassification.PredictionResult;
|
||||
|
||||
public class DLClipDecorations extends ClipDisplayDecorations {
|
||||
|
||||
private Color normalGrey;
|
||||
|
||||
private DLDetection dlDetection;
|
||||
|
||||
private JPanel dataPanel;
|
||||
|
||||
private PredictionResult result;
|
||||
|
||||
public DLClipDecorations(DLControl dlControl, ClipDisplayUnit clipDisplayUnit) {
|
||||
super(clipDisplayUnit);
|
||||
JPanel panel = new JPanel();
|
||||
normalGrey = panel.getBackground();
|
||||
this.dlDetection = (DLDetection) clipDisplayUnit.getClipDataUnit();
|
||||
|
||||
|
||||
result = dlControl.getDLClassifyProcess().getBestModelResult(dlDetection);
|
||||
if (result != null) {
|
||||
dataPanel = new JPanel(new BorderLayout());
|
||||
// GridBagConstraints c = new PamGridBagContraints();
|
||||
// String res = result.getResultString();
|
||||
double best = 0;
|
||||
int bestInd = -1;
|
||||
float[] prediction = result.getPrediction();
|
||||
if (prediction != null) {
|
||||
for (int i = 0; i < prediction.length; i++) {
|
||||
if (prediction[i] > best) {
|
||||
best = prediction[i];
|
||||
bestInd = i;
|
||||
}
|
||||
}
|
||||
String p = String.format("Class %d, score %3.2f", bestInd, best);
|
||||
dataPanel.add(BorderLayout.WEST, new JLabel(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClipDisplayUnit getClipDisplayUnit() {
|
||||
return super.getClipDisplayUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getClipBackground() {
|
||||
return Color.darkGray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOnClipAxis(Graphics g) {
|
||||
super.drawOnClipAxis(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOnClipBorder(Graphics g) {
|
||||
super.drawOnClipBorder(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decorateDisplay() {
|
||||
super.decorateDisplay();
|
||||
if (dataPanel != null) {
|
||||
getClipDisplayUnit().add(dataPanel, BorderLayout.NORTH);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package rawDeepLearningClassifier.swing;
|
||||
|
||||
import clipgenerator.clipDisplay.ClipDisplayPanel;
|
||||
import rawDeepLearningClassifier.DLControl;
|
||||
import userDisplay.UserDisplayComponent;
|
||||
import userDisplay.UserDisplayControl;
|
||||
import userDisplay.UserDisplayProvider;
|
||||
|
||||
public class DLClipDisplayProvider implements UserDisplayProvider {
|
||||
|
||||
private DLControl dlControl;
|
||||
|
||||
public DLClipDisplayProvider(DLControl dlControl) {
|
||||
super();
|
||||
this.dlControl = dlControl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return dlControl.getUnitName() + " clips";
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDisplayComponent getComponent(UserDisplayControl userDisplayControl, String uniqueDisplayName) {
|
||||
return new ClipDisplayPanel(dlControl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getComponentClass() {
|
||||
return ClipDisplayPanel.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxDisplays() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCreate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeDisplay(UserDisplayComponent component) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -22,6 +22,7 @@
|
||||
package rocca;
|
||||
|
||||
import java.awt.Frame;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.Serializable;
|
||||
@ -30,20 +31,27 @@ import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
|
||||
import PamController.DataIntegrityChecker;
|
||||
import PamController.DataOutputStore;
|
||||
import PamController.PamControlledUnit;
|
||||
import PamController.PamControlledUnitSettings;
|
||||
import PamController.PamController;
|
||||
import PamController.PamControllerInterface;
|
||||
import PamController.PamSettingManager;
|
||||
import PamController.PamSettings;
|
||||
import PamController.fileprocessing.StoreStatus;
|
||||
import PamUtils.PamCalendar;
|
||||
import PamView.PamGui;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
import PamguardMVC.PamDataUnit;
|
||||
import PamguardMVC.dataOffline.OfflineDataLoadInfo;
|
||||
import clickDetector.ClickControl;
|
||||
import clickDetector.ClickDetection;
|
||||
import clickDetector.offlineFuncs.OfflineEventDataBlock;
|
||||
import clickDetector.offlineFuncs.OfflineEventDataUnit;
|
||||
import dataGram.DatagramManager;
|
||||
import dataMap.OfflineDataMapPoint;
|
||||
import pamScrollSystem.ViewLoadObserver;
|
||||
|
||||
|
||||
/**
|
||||
@ -504,6 +512,61 @@ public class RoccaControl extends PamControlledUnit implements PamSettings {
|
||||
public RoccaProcess getRoccaProcess() {
|
||||
return roccaProcess;
|
||||
}
|
||||
/*
|
||||
* Consider implementing the DataStore interface so that ROCCA data can be deleted on reprocessing.
|
||||
@Override
|
||||
public void createOfflineDataMap(Window parentFrame) {
|
||||
// not used, but part of required interface.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDataSourceName() {
|
||||
return getUnitName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDataLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadData(PamDataBlock dataBlock, OfflineDataLoadInfo offlineDataLoadInfo,
|
||||
ViewLoadObserver loadObserver) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveData(PamDataBlock dataBlock) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean rewriteIndexFile(PamDataBlock dataBlock, OfflineDataMapPoint dmp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramManager getDatagramManager() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoreStatus getStoreStatus(boolean getDetail) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteDataFrom(long timeMillis) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataIntegrityChecker getInegrityChecker() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
@ -21,11 +21,15 @@
|
||||
package rocca;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import PamView.GeneralProjector;
|
||||
import PamView.PamDetectionOverlayGraphics;
|
||||
import PamView.PamSymbol;
|
||||
import PamView.PamSymbolType;
|
||||
import PamView.symbol.SymbolData;
|
||||
import PamguardMVC.PamDataUnit;
|
||||
|
||||
/**
|
||||
* @author Michael Oswald
|
||||
@ -46,8 +50,8 @@ public class RoccaGraphics extends PamDetectionOverlayGraphics {
|
||||
|
||||
int iCol = 0;
|
||||
|
||||
public RoccaGraphics(RoccaProcess roccaProcess) {
|
||||
super(roccaProcess.fftDataBlockIn, new PamSymbol(defaultSymbol));
|
||||
public RoccaGraphics(RoccaProcess roccaProcess, RoccaLoggingDataBlock rldb) {
|
||||
super(rldb, new PamSymbol(defaultSymbol));
|
||||
this.roccaProcess = roccaProcess;
|
||||
// if (getPamSymbol() == null) {
|
||||
// PamSymbol mapSymbol = new PamSymbol(PamSymbolType.SYMBOL_STAR, 8, 8, true,
|
||||
@ -56,10 +60,11 @@ public class RoccaGraphics extends PamDetectionOverlayGraphics {
|
||||
// }
|
||||
}
|
||||
|
||||
// @Override
|
||||
// protected Rectangle drawOnSpectrogram(Graphics g, PamDataUnit pamDataUnit, GeneralProjector generalProjector) {
|
||||
// return drawContourShape(g, (RoccaSightingDataUnit) pamDataUnit, generalProjector);
|
||||
// }
|
||||
@Override
|
||||
protected Rectangle drawOnSpectrogram(Graphics g, PamDataUnit pamDataUnit, GeneralProjector generalProjector) {
|
||||
return super.drawOnSpectrogram(g, pamDataUnit, generalProjector);
|
||||
}
|
||||
|
||||
//
|
||||
// Rectangle drawContourShape(Graphics g, RoccaSightingDataUnit rsdu,
|
||||
// GeneralProjector projector) {
|
||||
|
@ -64,6 +64,7 @@ public class RoccaLoggingDataBlock extends PamDataBlock<RoccaLoggingDataUnit> {
|
||||
this.roccaControl = roccaControl;
|
||||
//this.setNaturalLifetime(Integer.MAX_VALUE/1000);
|
||||
this.setNaturalLifetime(10);
|
||||
setPamSymbolManager(new RoccaSymbolManager(this, RoccaGraphics.defaultSymbol));
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,10 +21,16 @@
|
||||
|
||||
package rocca;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.protobuf.Duration;
|
||||
|
||||
import PamDetection.PamDetection;
|
||||
import PamguardMVC.PamDataUnit;
|
||||
import rocca.RoccaContourStats.ParamIndx;
|
||||
import tethys.pamdata.AutoTethysProvider;
|
||||
|
||||
|
||||
/**
|
||||
@ -248,6 +254,88 @@ public class RoccaLoggingDataUnit extends PamDataUnit<PamDataUnit,PamDataUnit> i
|
||||
public void setLongitude(double longitude) {
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSummaryString() {
|
||||
String base = super.getSummaryString();
|
||||
|
||||
// if (detectionCount != 0) {
|
||||
// base += String.format("Detection count: %d<br>", detectionCount);
|
||||
// }
|
||||
if (classifiedAs != null) {
|
||||
base += "Classified as: " + classifiedAs + "<br>";
|
||||
}
|
||||
if (classifierUsed != null) {
|
||||
base += "Classifier used: " + classifierUsed + "<br>";
|
||||
}
|
||||
if (classifier2Used != null) {
|
||||
base += "Second Classifier: " + classifier2Used + "<br>";
|
||||
}
|
||||
|
||||
|
||||
if (contourStats == null) {
|
||||
return base;
|
||||
}
|
||||
EnumMap<ParamIndx, Double> lst = contourStats.getContour();
|
||||
if (lst == null) {
|
||||
return base;
|
||||
}
|
||||
|
||||
int npRow = 3;
|
||||
Set<ParamIndx> keys = lst.keySet();
|
||||
int i = 0;
|
||||
for (ParamIndx aKey : keys) {
|
||||
Double data = lst.get(aKey);
|
||||
if (data == null) {
|
||||
continue;
|
||||
}
|
||||
data = AutoTethysProvider.roundDecimalPlaces(data, 3);
|
||||
base += String.format("%s: %s", aKey.toString(), data.toString());
|
||||
if (++i % npRow == 0) {
|
||||
base += ",<br>";
|
||||
}
|
||||
else {
|
||||
base += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getFrequency() {
|
||||
double[] fr = super.getFrequency();
|
||||
if (fr != null && fr.length == 2 && fr[1] > 0) {
|
||||
return fr;
|
||||
}
|
||||
if (contourStats.getContour() == null) {
|
||||
return null;
|
||||
}
|
||||
ParamIndx[] ps = {RoccaContourStats.ParamIndx.FREQMIN, RoccaContourStats.ParamIndx.FREQMAX};
|
||||
fr = new double[2];
|
||||
for (int i = 0; i < 2; i++) {
|
||||
Double f = contourStats.getContour().get(ps[i]);
|
||||
if (f == null) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
fr[i] = f;
|
||||
}
|
||||
}
|
||||
return fr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getDurationInMilliseconds() {
|
||||
if (contourStats.getContour() == null) {
|
||||
return null;
|
||||
}
|
||||
Double dur = contourStats.getContour().get(RoccaContourStats.ParamIndx.DURATION);
|
||||
if (dur == null) {
|
||||
return null;
|
||||
}
|
||||
return dur*1000.;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -152,6 +152,7 @@ public class RoccaProcess extends PamProcess {
|
||||
roccaClassifier = new RoccaClassifier(this);
|
||||
rldb = new RoccaLoggingDataBlock(roccaControl, this, 0);
|
||||
|
||||
rldb.setOverlayDraw(new RoccaGraphics(this, rldb));
|
||||
rldb.SetLogging(new RoccaStatsLogger(roccaControl, rldb));
|
||||
rldb.setMixedDirection(PamDataBlock.MIX_INTODATABASE);
|
||||
addOutputDataBlock(rldb);
|
||||
|
14
src/rocca/RoccaSymbolManager.java
Normal file
14
src/rocca/RoccaSymbolManager.java
Normal file
@ -0,0 +1,14 @@
|
||||
package rocca;
|
||||
|
||||
import PamView.symbol.StandardSymbolManager;
|
||||
import PamView.symbol.SymbolData;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
|
||||
public class RoccaSymbolManager extends StandardSymbolManager {
|
||||
|
||||
public RoccaSymbolManager(PamDataBlock pamDataBlock, SymbolData defaultSymbol) {
|
||||
super(pamDataBlock, defaultSymbol);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,12 +1,9 @@
|
||||
package tethys.species;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import PamController.PamControlledUnitSettings;
|
||||
import PamController.PamController;
|
||||
import PamController.PamSettingManager;
|
||||
import PamController.PamSettings;
|
||||
import PamView.dialog.PamDialogPanel;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
import PamguardMVC.PamDataUnit;
|
||||
import tethys.species.swing.DataBlockSpeciesDialog;
|
||||
@ -26,7 +23,7 @@ import tethys.species.swing.DataBlockSpeciesDialog;
|
||||
* @author dg50
|
||||
*
|
||||
*/
|
||||
abstract public class DataBlockSpeciesManager<T extends PamDataUnit> /*implements PamSettings*/ {
|
||||
abstract public class DataBlockSpeciesManager<T extends PamDataUnit> {
|
||||
|
||||
/**
|
||||
* The serialised bit. Always exists (or should be created) even if there
|
||||
@ -264,6 +261,15 @@ abstract public class DataBlockSpeciesManager<T extends PamDataUnit> /*implement
|
||||
}
|
||||
datablockSpeciesMap.clearMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a (preferably) small dialog panel that can contain
|
||||
* options for the species manager.
|
||||
* @return
|
||||
*/
|
||||
public PamDialogPanel getDialogPanel(SpeciesManagerObserver speciesManagerObserver) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
@Override
|
||||
|
12
src/tethys/species/SpeciesManagerObserver.java
Normal file
12
src/tethys/species/SpeciesManagerObserver.java
Normal file
@ -0,0 +1,12 @@
|
||||
package tethys.species;
|
||||
|
||||
/**
|
||||
* Observe changes in a spcies managers options.
|
||||
* @author dg50
|
||||
*
|
||||
*/
|
||||
public interface SpeciesManagerObserver {
|
||||
|
||||
public void update();
|
||||
|
||||
}
|
@ -64,7 +64,9 @@ public class SpeciesMapManager implements PamSettings {
|
||||
|
||||
private SpeciesMapManager() {
|
||||
PamSettingManager.getInstance().registerSettings(this);
|
||||
globalSpeciesMap = new GlobalSpeciesMap();
|
||||
if (globalSpeciesMap == null) {
|
||||
globalSpeciesMap = new GlobalSpeciesMap();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,7 +171,7 @@ public class SpeciesMapManager implements PamSettings {
|
||||
return new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
exportSpeciesMaps(parentFrame);
|
||||
exportSpeciesMaps(parentFrame, null);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -186,12 +188,13 @@ public class SpeciesMapManager implements PamSettings {
|
||||
/**
|
||||
* Export all species maps to a serialized object file.
|
||||
* @param parentFrame
|
||||
* @param singleDataBlock name of datablock to automatically check.
|
||||
* @return
|
||||
*/
|
||||
public boolean exportSpeciesMaps(Window parentFrame) {
|
||||
public boolean exportSpeciesMaps(Window parentFrame, String singleDataBlock) {
|
||||
// gather the species maps from the data blocks...
|
||||
gatherSpeciesMaps();
|
||||
GlobalSpeciesMap toExport = SpeciesMapIODialog.showDialog(parentFrame, globalSpeciesMap, true, null);
|
||||
GlobalSpeciesMap toExport = SpeciesMapIODialog.showDialog(parentFrame, globalSpeciesMap, true, singleDataBlock);
|
||||
if (toExport == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -10,13 +10,16 @@ import javax.swing.JScrollPane;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
import PamView.dialog.PamDialogPanel;
|
||||
import PamView.panel.PamAlignmentPanel;
|
||||
import PamView.panel.WestAlignedPanel;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
import tethys.species.DataBlockSpeciesManager;
|
||||
import tethys.species.DataBlockSpeciesMap;
|
||||
import tethys.species.SpeciesManagerObserver;
|
||||
import tethys.species.DataBlockSpeciesCodes;
|
||||
import tethys.species.SpeciesMapItem;
|
||||
|
||||
public class DataBlockSpeciesPanel implements PamDialogPanel {
|
||||
public class DataBlockSpeciesPanel implements PamDialogPanel, SpeciesManagerObserver {
|
||||
|
||||
private JPanel mainPanel;
|
||||
|
||||
@ -28,6 +31,8 @@ public class DataBlockSpeciesPanel implements PamDialogPanel {
|
||||
|
||||
private String singleSpecies;
|
||||
|
||||
private DataBlockSpeciesManager speciesManager;
|
||||
|
||||
/**
|
||||
* Panel of info about a species name in PAMGuard relating it to a call type and ITIS
|
||||
* code for output to Tethys.
|
||||
@ -38,7 +43,19 @@ public class DataBlockSpeciesPanel implements PamDialogPanel {
|
||||
super();
|
||||
this.dataBlock = dataBlock;
|
||||
this.singleSpecies = singleSpecies;
|
||||
|
||||
speciesManager = dataBlock.getDatablockSpeciesManager();
|
||||
|
||||
mainPanel = new JPanel(new BorderLayout());
|
||||
if (singleSpecies == null) {
|
||||
// only add additional options if it's the more global use of this dialog.
|
||||
PamDialogPanel dialogPanel = speciesManager.getDialogPanel(this);
|
||||
if (dialogPanel != null) {
|
||||
JPanel nwPanel = new WestAlignedPanel(dialogPanel.getDialogComponent());
|
||||
mainPanel.add(BorderLayout.NORTH, nwPanel);
|
||||
}
|
||||
}
|
||||
|
||||
speciesPanel = new JPanel();
|
||||
JScrollPane scrollPane = new JScrollPane(speciesPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
mainPanel.add(scrollPane, BorderLayout.CENTER);
|
||||
@ -57,7 +74,6 @@ public class DataBlockSpeciesPanel implements PamDialogPanel {
|
||||
speciesPanel.setLayout(new BoxLayout(speciesPanel, BoxLayout.Y_AXIS));
|
||||
subPanels.clear();
|
||||
|
||||
DataBlockSpeciesManager speciesManager = dataBlock.getDatablockSpeciesManager();
|
||||
// DataBlockSpeciesCodes speciesTypes = speciesManager.getSpeciesCodes();
|
||||
ArrayList<String> speciesNames = speciesManager.getAllSpeciesCodes();
|
||||
DataBlockSpeciesMap speciesMap = speciesManager.getDatablockSpeciesMap();
|
||||
@ -92,4 +108,9 @@ public class DataBlockSpeciesPanel implements PamDialogPanel {
|
||||
return errors == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
setParams();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package tethys.swing.export;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
@ -16,6 +17,7 @@ import javax.swing.border.TitledBorder;
|
||||
|
||||
import PamController.PamController;
|
||||
import PamView.component.PamSettingsIconButton;
|
||||
import PamView.dialog.PamDialogPanel;
|
||||
import PamView.dialog.PamGridBagContraints;
|
||||
import PamView.dialog.warn.WarnOnce;
|
||||
import PamView.panel.PamAlignmentPanel;
|
||||
@ -25,6 +27,7 @@ import tethys.TethysControl;
|
||||
import tethys.output.StreamExportParams;
|
||||
import tethys.species.DataBlockSpeciesManager;
|
||||
import tethys.species.DataBlockSpeciesMap;
|
||||
import tethys.species.SpeciesManagerObserver;
|
||||
import tethys.species.SpeciesMapItem;
|
||||
import tethys.species.SpeciesMapManager;
|
||||
import tethys.species.swing.DataBlockSpeciesDialog;
|
||||
@ -35,7 +38,7 @@ import tethys.species.swing.DataBlockSpeciesDialog;
|
||||
* @author dg50
|
||||
*
|
||||
*/
|
||||
public class CallTypeCard extends ExportWizardCard {
|
||||
public class CallTypeCard extends ExportWizardCard implements SpeciesManagerObserver {
|
||||
|
||||
private DataBlockSpeciesManager speciesManager;
|
||||
// private DataBlockSpeciesCodes codes;
|
||||
@ -53,18 +56,63 @@ public class CallTypeCard extends ExportWizardCard {
|
||||
|
||||
private DataBlockSpeciesMap speciesMap;
|
||||
|
||||
private JPanel speciesPanel;
|
||||
|
||||
public CallTypeCard(TethysControl tethysControl, PamWizard pamWizard, String title, PamDataBlock dataBlock) {
|
||||
super(tethysControl, pamWizard, title, dataBlock);
|
||||
speciesManager = dataBlock.getDatablockSpeciesManager();
|
||||
speciesMap = speciesManager.getDatablockSpeciesMap();
|
||||
speciesPanel = new JPanel();
|
||||
speciesPanel.setLayout(new GridBagLayout());
|
||||
speciesPanel.setToolTipText(bitTip);
|
||||
fillSpeciesPanel();
|
||||
JPanel nPanel = new PamAlignmentPanel(speciesPanel, BorderLayout.NORTH);
|
||||
JScrollPane scrollPane = new JScrollPane(nPanel);
|
||||
this.setBorder(new TitledBorder("Species / Call types to export"));
|
||||
this.setLayout(new BorderLayout());
|
||||
this.add(scrollPane, BorderLayout.CENTER);
|
||||
|
||||
JPanel northPanel = new JPanel(new BorderLayout());
|
||||
PamDialogPanel dialogComp = speciesManager.getDialogPanel(this);
|
||||
if (dialogComp != null) {
|
||||
northPanel.add(BorderLayout.WEST, dialogComp.getDialogComponent());
|
||||
this.add(BorderLayout.NORTH, northPanel);
|
||||
}
|
||||
|
||||
|
||||
JPanel southPanel = new JPanel(new BorderLayout());
|
||||
// southPanel.setBorder(new TitledBorder("Controls"));
|
||||
JButton importButton = new JButton("Import species map");
|
||||
importButton.setToolTipText("Import a species map previously saved from another PAMGuard configuration");
|
||||
importButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
importSpeciesMap(importButton);
|
||||
}
|
||||
});
|
||||
JButton exportButton = new JButton("Export species map");
|
||||
exportButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
exportSpeciesMap(exportButton);
|
||||
}
|
||||
});
|
||||
JPanel swPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||
southPanel.add(swPanel, BorderLayout.WEST);
|
||||
swPanel.add(importButton);
|
||||
swPanel.add(exportButton);
|
||||
this.add(southPanel, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
private void fillSpeciesPanel() {
|
||||
speciesPanel.removeAll();
|
||||
|
||||
names = speciesManager.getAllSpeciesCodes();
|
||||
speciesSelection = new JCheckBox[names.size()];
|
||||
itisLabels = new JLabel[names.size()];
|
||||
speciesNames = new JLabel[names.size()];
|
||||
callTypes = new JLabel[names.size()];
|
||||
JPanel spPanel = new JPanel();
|
||||
spPanel.setLayout(new GridBagLayout());
|
||||
spPanel.setToolTipText(bitTip);
|
||||
|
||||
PamGridBagContraints c = new PamGridBagContraints();
|
||||
commonNames = new JCheckBox("Species");
|
||||
commonNames.addActionListener(new ActionListener() {
|
||||
@ -78,10 +126,10 @@ public class CallTypeCard extends ExportWizardCard {
|
||||
for (int i = 0; i < tits.length; i++) {
|
||||
JComponent lab;
|
||||
if (i == 3) {
|
||||
spPanel.add(lab=commonNames, c);
|
||||
speciesPanel.add(lab=commonNames, c);
|
||||
}
|
||||
else {
|
||||
spPanel.add(lab = new JLabel(tits[i], JLabel.LEFT), c);
|
||||
speciesPanel.add(lab = new JLabel(tits[i], JLabel.LEFT), c);
|
||||
}
|
||||
lab.setToolTipText(tips[i]);
|
||||
c.gridx++;
|
||||
@ -90,43 +138,26 @@ public class CallTypeCard extends ExportWizardCard {
|
||||
c.gridx = 0;
|
||||
c.gridy++;
|
||||
speciesSelection[i] = new JCheckBox();
|
||||
spPanel.add(speciesSelection[i], c);
|
||||
speciesPanel.add(speciesSelection[i], c);
|
||||
c.gridx++;
|
||||
spPanel.add(new JLabel(names.get(i)), c);
|
||||
speciesPanel.add(new JLabel(names.get(i)), c);
|
||||
c.gridx++;
|
||||
spPanel.add(itisLabels[i] = new JLabel(), c);
|
||||
speciesPanel.add(itisLabels[i] = new JLabel(), c);
|
||||
c.gridx++;
|
||||
spPanel.add(speciesNames[i] = new JLabel(), c);
|
||||
speciesPanel.add(speciesNames[i] = new JLabel(), c);
|
||||
c.gridx++;
|
||||
spPanel.add(callTypes[i] = new JLabel(), c);
|
||||
speciesPanel.add(callTypes[i] = new JLabel(), c);
|
||||
fillItemInfo(i);
|
||||
|
||||
c.gridx++;
|
||||
PamSettingsIconButton but = new PamSettingsIconButton();
|
||||
but.setToolTipText("Edit species id and call type");
|
||||
but.addActionListener(new SpeciesAction(i));
|
||||
spPanel.add(but, c);
|
||||
speciesPanel.add(but, c);
|
||||
}
|
||||
JPanel nPanel = new PamAlignmentPanel(spPanel, BorderLayout.NORTH);
|
||||
JScrollPane scrollPane = new JScrollPane(nPanel);
|
||||
this.setBorder(new TitledBorder("Species / Call types to export"));
|
||||
this.setLayout(new BorderLayout());
|
||||
this.add(scrollPane, BorderLayout.CENTER);
|
||||
|
||||
JPanel southPanel = new JPanel(new BorderLayout());
|
||||
// southPanel.setBorder(new TitledBorder("Controls"));
|
||||
JButton importButton = new JButton("Import species mapping");
|
||||
importButton.setToolTipText("Import a species map previously saved from another PAMGuard configuration");
|
||||
importButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
importSpeciesMap(importButton);
|
||||
}
|
||||
});
|
||||
southPanel.add(importButton, BorderLayout.WEST);
|
||||
this.add(southPanel, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
|
||||
private void fillAllItemInfo() {
|
||||
for (int i = 0; i < names.size(); i++) {
|
||||
fillItemInfo(i);
|
||||
@ -165,6 +196,11 @@ public class CallTypeCard extends ExportWizardCard {
|
||||
}
|
||||
}
|
||||
|
||||
private void exportSpeciesMap(JButton exportButton) {
|
||||
SpeciesMapManager mapManager = SpeciesMapManager.getInstance();
|
||||
mapManager.exportSpeciesMaps(getPamWizard(), getDataBlock().getLongDataName());
|
||||
}
|
||||
|
||||
private class SpeciesAction implements ActionListener {
|
||||
|
||||
private int itemIndex;
|
||||
@ -229,4 +265,9 @@ public class CallTypeCard extends ExportWizardCard {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
fillSpeciesPanel();
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user