Tethys improvements

Better species sel panel in export dialog
updated / corrected help
Sorted 'final' button in export wizard.
This commit is contained in:
Douglas Gillespie 2025-03-05 16:19:21 +00:00
parent cb9b41719f
commit d3907ac8f5
43 changed files with 665 additions and 294 deletions

View File

@ -81,7 +81,10 @@ abstract public class PamWizard extends PamDialog {
boolean isLast = iCard == wizardCards.size()-1;
// getOkButton().setEnabled(!isLast);
getOkButton().setText(isLast ? "Finish" : "Next");
getOkButton().setToolTipText(isLast ? "Check values and close" : "Next page");
prevButton.setToolTipText(iCard == 0 ? null : "Previous page");
}
private boolean checkCurrentCard() {
int iCard = getCardIndex();

View File

@ -883,7 +883,7 @@ public class ClickControl extends PamControlledUnit implements PamSettings, Loca
return true;
}
JMenuBar clickTabMenu = null;
JMenuBar tabMenu = null;
private ClickFFTOrganiser clickFFTDataOrganiser;
@ -893,31 +893,31 @@ public class ClickControl extends PamControlledUnit implements PamSettings, Loca
@Override
public JMenuBar getTabSpecificMenuBar(Frame parentFrame, JMenuBar standardMenu, PamGui pamGui) {
JMenu aMenu;
// start bymaking a completely new copy.
// start by making a completely new copy.
// if (clickTabMenu == null) {
clickTabMenu = standardMenu;
for (int i = 0; i < clickTabMenu.getMenuCount(); i++) {
if (clickTabMenu.getMenu(i).getText().equals("Display")) {
tabMenu = standardMenu;
for (int i = 0; i < tabMenu.getMenuCount(); i++) {
if (tabMenu.getMenu(i).getText().equals("Display")) {
//clickTabMenu.remove(clickTabMenu.getMenu(i));
aMenu = createDetectionMenu(parentFrame);
String txt = aMenu.getText();
txt = checkMenuTit(txt, "settings");
aMenu.setText(txt);
clickTabMenu.add(aMenu, i+1);
tabMenu.add(aMenu, i+1);
aMenu = tabPanelControl.createMenu(parentFrame);
// aMenu.setText("Click Display");
txt = aMenu.getText();
txt = checkMenuTit(txt, "display");
aMenu.setText(txt);
clickTabMenu.add(aMenu, i+2);
tabMenu.add(aMenu, i+2);
break;
}
}
// }
return clickTabMenu;
return tabMenu;
}
/**

View File

@ -16,7 +16,8 @@ public class ClickTethysDataProvider extends AutoTethysProvider {
@Override
public GranularityEnumType[] getAllowedGranularities() {
return GranularityEnumType.values(); // everything !
GranularityEnumType[] allowed = {GranularityEnumType.CALL, GranularityEnumType.BINNED, GranularityEnumType.ENCOUNTER};
return allowed;
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

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

Binary file not shown.

View File

@ -606,6 +606,8 @@
<mapID target="utilities.SIDEModule.docs.SIDE_OpStat" url="utilities/SIDEModule/docs/SIDE_OpStat.html"/>
<mapID target="utilities.tethys.docs.tethys_granularity" url="utilities/tethys/docs/tethys_granularity.html"/>
<mapID target="localisation.group3d.docs.3doutput" url="localisation/group3d/docs/3doutput.html"/>
<mapID target="detectors.gpl.docs.notes" url="detectors/gpl/docs/notes.html"/>

View File

@ -212,6 +212,8 @@
<tocitem text="Detections and Localizations " target="utilities.tethys.docs.detect_localize" image="topic"/>
<tocitem text="Granularity " target="utilities.tethys.docs.tethys_granularity" image="topic"/>
<tocitem text="ITIS Species Codes " target="utilities.tethys.docs.tethys_speciescodes" image="topic"/>
<tocitem text="PAMGuard Mapping " target="utilities.tethys.docs.tethys_mappings" image="topic"/>

View File

@ -109,6 +109,10 @@
populated. Press new/edit to access the instrument settings
from the Tethys module page.
</p>
<p>Project names and instrument names are important in maintaining the relationship between
a PAMGuard dataset and related documents in Tethys. Read about <a href="tethys_mappings.html">PAMGuard Tethys mappings</a>
for further details.</p>
<br>
<br>

View File

@ -73,14 +73,6 @@ img {
without affecting the selection state of other blocks.
<p>
<p>
<em>
SUGGESTION: It looks like we have to highlight these by clicking
on them. As we use select boxes for recording periods, we might
want to do the same thing here... We might want to rename
N PAM Datas to N PAM Data as data are already plural.
</em>
</p>
<h2> Exporting data blocks </h2>
@ -96,14 +88,39 @@ img {
alt="List of details describing the mechanism, parameters, and version of modules used in processing"/>
</div>
<br>
<p>
There is nothing to change in this summary. Press Next once you
have reviewed it. The second panel allows specification of your
have reviewed it. </p>
<img src="./images/stream_species.png">
<br>
<p>The second panel allows you to check <a href="tethys_speciescodes.html">ITIS species codes and call types</a>
and to select which call types you want to export. </p>
<img src="./images/stream_granularity.png">
<br>
<p>The next panel allows you to chose whether to export Detections, Localizations (if available), or both. Here, you
can also select the <a href="tethys_granularity.html">granularity</a>, which will be a choice of "Call", "Encounter", "Binned", or "Grouped", depending on the
type of data. You can also select an optional data filter which will restrict the output using criteria specific to the
detector you're using. Note that there may be overlap between the data filter and the selections you make in the earlier species
selection page. </p>
<img src="./images/stream_description.png">
<br>
<p>This panel allows specification of your
objectives, abstract, and method. Many modules will have
pre-populated the method for you. While it is recommended to populate
the objectives and abstract, these fields are optional.
pre-populated the method for you. It is recommended to populate
the objectives and abstract with as much information as possible.
</p>
<img src="./images/stream_parameters.png">
<br>
<p>
Press Next to proceed to the next step of the dialog. You will be asked
what details you wish to store within the parameters that were used to
@ -118,7 +135,8 @@ img {
later date or know whether or not the results of different
studies can be used together.
</li>
<li> Data selector only - <strong>not sure what this is</strong> </li>
<li> Data selector only - Output only the details of the data filter (if any), for instance that
selected only a type of sound, or sounds with a received level above a set minimum.
<li>
Module only - Report the parameters that were set with this
module. Only parameters associated with the specific module
@ -131,21 +149,20 @@ img {
parameters as well as anything else that is part of the signal processing chain that leads
to the module. As an example, a module only setting would not report the parameters that were
used to generate a spectrogram that was presented to a module for classification, but the
full process chain would record these details as well. Use this option will dramatically
full process chain would record these details as well. Use of this option will dramatically
increase the potential to reproduce your results, but it will generate a large amount of data
about the signal processing chain, much of which might not be useful.
</li>
</ul>
<img src="./images/stream_export.png">
<br>
<p>
The final page of the dialog has an "Export data" button. Press
this to export the data. The system will begin generating the
Tethys document and the "Export data" button will be relabeled "Export complete"
once it is done. At this point, you can press "Finish" to close
the dialog.
The final page of the dialog has an "Export data" button. Press either
this, or the Export button at the bottom of the dialog, to export the data. The system will begin generating the
Tethys document and display progress as it works through the data. When complete, it will show a message to indicate that export was
successful, or an error message.
<em>Would it make more sense to export when the user presses
Finish (or change the Finish button Export)?</em>
</p>

Binary file not shown.

After

(image error) Size: 6.4 KiB

Binary file not shown.

After

(image error) Size: 27 KiB

Binary file not shown.

After

(image error) Size: 34 KiB

Binary file not shown.

After

(image error) Size: 17 KiB

Binary file not shown.

After

(image error) Size: 20 KiB

Binary file not shown.

Before

(image error) Size: 19 KiB

After

(image error) Size: 11 KiB

Binary file not shown.

After

(image error) Size: 16 KiB

Binary file not shown.

After

(image error) Size: 10 KiB

Binary file not shown.

After

(image error) Size: 19 KiB

Binary file not shown.

After

(image error) Size: 9.6 KiB

Binary file not shown.

After

(image error) Size: 19 KiB

View File

@ -0,0 +1,57 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<link href="../../../pamHelpStylesheet.css" type="text/css"
rel="STYLESHEET">
<title>Detections/Granularity</title>
<style type="text/css">
img.wrap {
float: left
}
img.wrapright {
float: right
}
img {
float: right;
}
</style>
</head>
<link href="../../../pamHelpStylesheet.css" type="text/css"
rel="STYLESHEET">
<body>
<h1>Tethys Granularity</h1>
<h2>Tethys Granularity</h2>
<p>
When exporting Detections to Tethys, you must select the "Granularity" for the exports. This will be one
of the following:
<ul>
<li>Call - each detected call, or noise measurement is individually output to Tethys.</li>
<li>Binned - Counts of calls in fixed time bins are output to Tethys.</li>
<li>Encounter - Counts of calls forming and Encounter, that is a period of calling without a predetermined gap between calls. </li>
<li>Grouped - A Count of groups of calls associated in some other way (for instance through manual grouping of detections).</li>
</ul>
</p>
<p>Binned granularity will require you to enter the duration of each bin, and a minimum number of calls for a bin to be output (e.g. you might set this above
1 if there were occasional false positive detections, but when the animals do call, you tend to get lots of them).</p>
<p>Encounter granularity will require you to enter a minimum gap between calls which would constitute a new encounter. As with Binned, you also enter
a minimum number of calls for a bin to be output</p>
<p>
Encounter and Binned granularities also offer to output separate records for each detection channel (or hydrophone), or to group detections across channels. The former
would be most appropriate for widely spaces hydrophones, where you'd expect different encounters on each hydrophone, whereas the latter would be more suitable if the
hydrophones were spaced close enough together that you'd expect broadly the same detections on them all. </p>
<br>
<p class="prevLink"><a href="detect_localize.html">Previous: Detections and Localizations</a></p>
<p class="prevLink"><a href="tethys_speciescodes.html">Previous: Species Codes</a></p>
<br>
<br>
<br>
</body>
</html>

View File

@ -29,10 +29,10 @@ img {
<img SRC="images/Tethys-200.png" alt="Tethys mosaic"
style="float: right; margin 10px;"/>
</div>
<br>
<p>
PAMGuard is compatible
with <a href="https://doi.org/10.5281/zenodo.13626338">Tethys 3.1</a> or
with <a href="https://doi.org/10.5281/zenodo.13626338">Tethys 3.2 beta 2</a> or
later available for download from <a href="https://doi.org/10.5281/zenodo.13626338">Zenodo.</a>
</p>
<p>

View File

@ -7,186 +7,199 @@
<body>
<h1> Species and Call Type Names </h1>
<br>
<p> When exporting data from PAMGuard to Tethys, some PAMGuard records
will require additional information indicating what type of animal
or phenomena were detected. If a specific call-type was detected,
e.g. "Clicks" or "Whistles", these should be noted as well.</p>
<h2> Species Names </h2>
<p>
Tethys uses the <a href="https:itis.gov">Integrated Taxonomic
Information System</a> (ITIS) to encode species names as taxonomic
serial numbers (TSNs), unique numeric identifiers for species.
These data conform with several international coding systems which
are described on the <a href="https://itis.gov/standard.html">ITIS
standards</a> page.
</p>
<h1>Species and Call Type Names</h1>
<br>
<p>When exporting data from PAMGuard to Tethys, some PAMGuard
records will require additional information indicating what type of
animal or phenomena were detected. If a specific call-type was
detected, e.g. "Clicks" or "Whistles", these should be noted as well.</p>
<p>
It is not uncommon to be unable to describe a call to the genus
level. In such cases, one can use a higher taxonomic level. For
example, beaked whale echolocation clicks are distinctive from the
clicks of other toothed whales as their pulses have a
frequency-modulated component. While they can frequently be
associated with the family Hyperodontidae, it is not always
possible to associate a click to a specific species as many of the
at least twenty-two species remain understudied. In such a case,
we would use the TSN for Hyperodontidae, 770799. While not
currently supported by PAMGuard, each species identifier has an
optional Group attribute that can be used in an ad-hoc manner to
provide additional information. This can be used to add
population markers, tentative genus groups, etc.
</p>
<h2>Species Names</h2>
<p>
Tethys uses the <a href="https:itis.gov">Integrated Taxonomic
Information System</a> (ITIS) to encode species names as taxonomic serial
numbers (TSNs), unique numeric identifiers for species. These data
conform with several international coding systems which are described
on the <a href="https://itis.gov/standard.html">ITIS standards</a>
page.
</p>
<p>
ITIS does not describe abiotic sounds, Tethys records such sounds as follows:
<ol>
<li>
For anthropogenic signals, the Tethys convention is to
use <em>Homo sapiens</em>, TSN 180092, for the species code
and describe the human-generated signal via a call type,
e.g. ship, mid-frequency active sonar, etc.
</li>
<li>
Tethys reserves the TSN -10 for geophonic signals.
The call type is used to describe the source. Examples
include ambient sound, earthquake, rain, etc. Note that negative TSNs
are not part of the ITIS standard.
</li>
</ol>
</p>
<p>It is not uncommon to be unable to describe a call to the genus
level. In such cases, one can use a higher taxonomic level. For
example, beaked whale echolocation clicks are distinctive from the
clicks of other toothed whales as their pulses have a
frequency-modulated component. While they can frequently be associated
with the family Hyperodontidae, it is not always possible to associate
a click to a specific species as many of the at least twenty-two
species remain understudied. In such a case, we would use the TSN for
Hyperodontidae, 770799. While not currently supported by PAMGuard,
each species identifier has an optional Group attribute that can be
used in an ad-hoc manner to provide additional information. This can
be used to add population markers, tentative genus groups, etc.</p>
Note that in general, you do not have to worry about remembering
TSNs. Tethys uses TSNs internally, but will translate TSNs to/from
Latin names or user-defined abbreviations both when querying and
presenting results.
<p>ITIS does not describe abiotic sounds, Tethys records such
sounds as follows:
<ol>
<li>For anthropogenic signals, the Tethys convention is to use <em>Homo
sapiens</em>, TSN 180092, for the species code and describe the
human-generated signal via a call type, e.g. ship, mid-frequency
active sonar, etc.
</li>
<li>Tethys reserves the TSN -10 for geophonic signals. The call
type is used to describe the source. Examples include ambient sound,
earthquake, rain, etc. Note that negative TSNs are not part of the
ITIS standard.</li>
</ol>
</p>
<h2> Call types </h2>
Note that in general, you do not have to worry about remembering TSNs.
Tethys uses TSNs internally, but will translate TSNs to/from Latin
names or user-defined abbreviations both when querying and presenting
results.
<p>
Some detectors identify specific call types. When this is the
case, users will need to specify the call type name. While
species names are standardized in Tethys, call names do not have a
well-defined standard and experts frequently use different names
for the same type of call. Consequently, Tethys does not provide a
standard coding for call types and users are free to choose the call
type names with which they feel most comfortable.
</p>
<h2>Call types</h2>
<p>
That said, the authors of Tethys do however provide a list of recommend call
types for many species. These recommendations can be accessed in the
<a href="https://ars.els-cdn.com/content/image/1-s2.0-S1574954115001983-mmc1.docx">
supplemental information</a> of the open access article "Management of acoustic metadata
for bioacoustics," Roch et al. (2016),
(<a href="https://doi.org/10.1016/j.ecoinf.2015.12.002">DOI:10.1016/j.ecoinf.2015.12.002</a>).
</p>
<h2>
Export dialog
</h2>
<p>Some detectors identify specific call types. When this is the
case, users will need to specify the call type name. While species
names are standardized in Tethys, call names do not have a
well-defined standard and experts frequently use different names for
the same type of call. Consequently, Tethys does not provide a
standard coding for call types and users are free to choose the call
type names with which they feel most comfortable.</p>
<p>
During export of records that are species-specific, a dialog will
appear that lists the types of events that were found by PAMGuard
modules. This dialog permits users to specify how the ad-hoc species
species/call encoding scheme used by PAMGuard modules can be systematically
translated to the TSNs and call types are stored in Tethys.
</p>
<p>
That said, the authors of Tethys do however provide a list of
recommend call types for many species. These recommendations can be
accessed in the <a
href="https://ars.els-cdn.com/content/image/1-s2.0-S1574954115001983-mmc1.docx">
supplemental information</a> of the open access article "Management of
acoustic metadata for bioacoustics," Roch et al. (2016), (<a
href="https://doi.org/10.1016/j.ecoinf.2015.12.002">DOI:10.1016/j.ecoinf.2015.12.002</a>).
</p>
<p>
PAMGuard events typically are a short name that represents the
species and/or potentially a call. Knowledge of the PAMGuard
modules that were run and the data on which they executed will let
a user infer what should be recorded.
The dialog below shows a sample set of events produced by one or more PAMGuard modules
using the names: HP, DO, SON, KW, UNK, and PHP:
<p>
Within PAMGuard, different detectors have different numbers of call
types. Some, such as the <a
href="../../../detectors/whistleMoanHelp/docs/whistleMoan_Overview.html">Whistle
and Moan detector</a>, have only one fixed call type "Tonal", for others
such as the <a
href="../../../detectors/clickDetectorHelp/docs/ClickDetector_clickClassification.html">Click
Detector</a>, the user can define any number of different call types in
the click classification configuration. The Tethys interface allows
the user to map the internal call types from PAMGuard to ITIS species
codes and call types.
</p>
<div>
<img src="./images/species_codes.png" class=".center"/>
</div>
<h2>Export dialog</h2>
The dialog above was produced from detections on data that were
recorded near the mouth of the River Tay in Scotland. Consequently,
we can infer that the harbour porpoise that is denoted by "HP" is
<em>Phocena phocena</em>, the only harbour porpoise endemic to
Scottish waters.
</p>
An ITIS code and call/sound type can be associated with each event. The dialog lists:
<ul>
<li>
Name - The ad-hoc name given by the PAMGuard module. This may not be changed.
</li>
<p>Before you can export records to Tethys, you must complete a
mapping that can translate the ad-hoc encodings defined within
PAMGuard to valid ITIS codes and call types. The dialog for these
mappings can be accessed in two ways, firstly, in the table of
PAMGuard data blocks in the lower left of the display, right click on
any row and select the menu item "PAMGuard ITIS Species mapping ...",
Otherwise, a similar dialog will appear as a page with the export
wizard once you've pressed the "Export ..." button.</p>
<li>
ITIS code -This is the ITIS TSN that is associated with PAMGuard
event code. Click on Find to inovke the TSN
search dialog whose behavior is described in the <a href="#TSNLookup">next
section</a>.
<p>
If you happen to know the TSN, you
can enter it directly. Pressing Find after typing the TNS will
populate the Latin and English vernauclar names so that you may
verify your TSN was entered correctly.
</p>
</li>
<p>PAMGuard events typically are a short name that represents the
species and/or potentially a call. Knowledge of the PAMGuard modules
that were run and the data on which they executed will let a user
infer what should be recorded. The dialog below shows a sample set of
species defined in the PAMGuard click detector, where the user has
defined the codes Porpoise, BWC, Oo, Pm, UNK, and Zc. Note that the
first entry "Click" has been added automatically as a default for when
no classification result was returned.
<div>
<img src="./images/species_codes1a.png" class=".center" />
</div>
<br> In the dialog above, we can infer that the only porpoise
present in the study area was Harbour Porpoise, so have selected ITIS
code 180473,
<em>Phocoena phocoena</em>. However, the identity of species BWC is
unclear, though believed to be some type of beaked whale, so it has
been given the code 770799 for
<em>Hyperoodontidae</em>.
<li> Call / sound type - This will default to the code provided by
the module but should be updated to specify an appropriate call
type or left blank to indicate that the detection is not related
to a specific call type. In the case of a porpoise detector,
the likely call type would be "Clicks".
<strong>We should double check that no Call element is generated when this is blank.</strong>
</li>
</ul>
</p>
<p>
Once all species names and call/sound types have been identified, press the Okay button.
</p>
An ITIS code and call/sound type can be associated with each event. The
dialog lists:
<ul>
<li>Name - The ad-hoc name given by the PAMGuard module. This may
not be changed.</li>
<li>ITIS code -This is the ITIS TSN that is associated with
PAMGuard event code. Click on Find to inovke the TSN search dialog
whose behavior is described in the <a href="#TSNLookup">next
section</a>.
<p>If you happen to know the TSN, you can enter it directly.
Pressing Find after typing the TNS will populate the Latin and
English vernauclar names so that you may verify your TSN was entered
correctly.</p>
</li>
<li>Call / sound type - This will default to the code provided by
the module but should be updated to specify an appropriate call type
or left blank to indicate that the detection is not related to a
specific call type. In the case of a porpoise detector, the likely
call type would be "Clicks". <strong>We should double check
that no Call element is generated when this is blank.</strong>
</li>
</ul>
<p>Once all species names and call/sound types have been
identified, press the Okay button.</p>
<a name="TSNLookup"></a>
<h2> Searching for ITIS Taxonomic Serial Numbers (TSNs) </h2>
<p>
As noted above, pressing Find without typing a TSN will bring up a
search dialog:
</p>
<a name="TSNLookup"></a>
<h2>Searching for ITIS Taxonomic Serial Numbers (TSNs)</h2>
<div>
<image src="./images/species_search.png" class=".center"/>
</div>
<p>
The top of this dialog has a search box where one can enter either
a Latin name or the common name for a species. The Tethys server
will search for all species that match the search-box contents.
For many species, there are common name entries in languages
other than English, and these are searched as well.
</p>
<p>
Once you press the search button, a list will appear with all
matches for your search term. If there are too many, a scroll bar
will permit you to look through the list. Select the entry that
you wish and press OK. The TSN on the species dialog will be
populated along with the Latin name and common names from the ITIS
database.
</p>
<p>As noted above, pressing Find without typing a TSN will bring up
a search dialog:</p>
<div>
<image src="./images/species_search.png" class=".center" />
</div>
<br></br>
<br></br>
<p>The top of this dialog has a search box where one can enter
either a Latin name or the common name for a species. The Tethys
server will search for all species that match the search-box contents.
For many species, there are common name entries in languages other
than English, and these are searched as well.</p>
<p>Once you press the search button, a list will appear with all
matches for your search term. If there are too many, a scroll bar will
permit you to look through the list. Select the entry that you wish
and press OK. The TSN on the species dialog will be populated along
with the Latin name and common names from the ITIS database.</p>
<h2>Export and Import</h2>
<p>
Entering all of these codes can get a little tedious and you'll
hopefully also want to be consistent between your different datasets.
PAMGuard therefore has options to save the species mapping to a file,
which can then be re-imported into a different configuration.
</p>
Mappings are stored individually for each PAMGuard datablock and are identified
by the datablock name. To Export, go to the "Tethys/Export Species Maps ..." menu
and in the dialog, select the maps you want to export.</p>
<br><br>
<div>
<image src="./images/exportmap.png" class=".center" />
</div>
<br>
<p>You will be then be asked for the name of a file to export to and data will be saved to that
file. </p>
<p>Importing is similar: From the Tethys menu, select "Import Species Maps ... ", you will be asked
to select a previously exported file, and can then choose which maps to import.</p>
<br></br>
<br></br>
<p class="prevLink">
<a href="detect_localize.html">Previous: Detections &
Localizations</a>
</p>
<p class="nextLink">
<a href="tethys_mappings.html">Next: Tethys / PAMGuard mappings</a>
</p>
<p class="prevLink">
<a href="detect_localize.html">Previous: Detections & Localizations</a>
</p>
<p class="nextLink">
<a href="tethys_mappings.html">Next: Tethys / PAMGuard mappings</a>
</p>
</body>
</body>

View File

@ -7,6 +7,7 @@ import org.json.JSONArray;
import org.json.JSONObject;
import PamguardMVC.PamDataUnit;
import annotation.xml.AnnotationXMLWriter;
import generalDatabase.EmptyTableDefinition;
import generalDatabase.PamTableItem;
import generalDatabase.SQLLoggingAddon;
@ -163,8 +164,10 @@ public class DLAnnotationSQL implements SQLLoggingAddon {
//to make this a matrix
JSONArray classIDArray = new JSONArray();
short[] classID = arrayList.get(0).getClassNames();
for (short aClassID : classID) {
classIDArray.put(aClassID);
if (classID != null) {
for (short aClassID : classID) {
classIDArray.put(aClassID);
}
}
jsonObject.put(PREDICTIONS_JSON_KEY, matrixArray);

View File

@ -5,6 +5,7 @@ import annotation.CentralAnnotationsList;
import annotation.DataAnnotationType;
import annotation.binary.AnnotationBinaryHandler;
import annotation.dataselect.AnnotationDataSelCreator;
import annotation.xml.AnnotationXMLWriter;
import generalDatabase.SQLLoggingAddon;
import rawDeepLearningClassifier.DLControl;
import rawDeepLearningClassifier.dataPlotFX.DLSymbolModifier;
@ -105,6 +106,12 @@ public class DLAnnotationType extends DataAnnotationType<DLAnnotation> {
return dlDataSelectorCreator;
}
@Override
public AnnotationXMLWriter<DLAnnotation> getXMLWriter() {
// override since the SQLLogging one seems to output a load of Json. could replace
// with something a bit nicer that makes xml.
return null;
}

View File

@ -18,6 +18,7 @@ import java.util.ArrayList;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
@ -31,6 +32,7 @@ import PamController.PamSettingManager;
import PamController.PamSettings;
import PamModel.SMRUEnable;
import PamUtils.PamFileFilter;
import PamView.PamGui;
import PamView.PamTabPanel;
import PamView.dialog.warn.WarnOnce;
import PamguardMVC.PamDataBlock;
@ -161,7 +163,7 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
* @param parentFrame
* @return
*/
public JMenuItem createTethysMenu(Frame parentFrame) {
public JMenu createTethysMenu(Frame parentFrame) {
JMenu tethysMenu = new JMenu("Tethys");
// JMenuItem tethysExport = new JMenuItem("Export ...");
// tethysMenu.add(tethysExport);
@ -216,24 +218,24 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
});
tethysMenu.add(showDeps);
JMenuItem cals = new JMenuItem("Export calibrations");
cals.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
calibrationHandler.exportAllCalibrations();
}
});
tethysMenu.add(cals);
// JMenuItem cals = new JMenuItem("Export calibrations");
// cals.addActionListener(new ActionListener() {
//
// @Override
// public void actionPerformed(ActionEvent e) {
// calibrationHandler.exportAllCalibrations();
// }
// });
// tethysMenu.add(cals);
tethysMenu.addSeparator();
JMenuItem mapItem = new JMenuItem("Export species maps ...");
mapItem.setToolTipText("Export all species maps (PAMGuard codes to ITIS codes to file for import into other configurations");
mapItem.setToolTipText("Export species maps (save PAMGuard species names to ITIS codes mapping to file for import into other configurations)");
mapItem.addActionListener(SpeciesMapManager.getInstance().getExportAction(parentFrame));
tethysMenu.add(mapItem);
mapItem = new JMenuItem("Import species maps ...");
mapItem.setToolTipText("Import species maps (PAMGuard codes to ITIS codes to file for import into other configurations");
mapItem.setToolTipText("Import species maps (PAMGuard species names to ITIS code mappings exported from other configurations)");
mapItem.addActionListener(SpeciesMapManager.getInstance().getImportAction(parentFrame));
tethysMenu.add(mapItem);
@ -248,6 +250,32 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
return tethysMenu;
}
public JMenuBar getTabSpecificMenuBar(Frame parentFrame, JMenuBar standardMenu, PamGui pamGui) {
JMenuItem aMenu;
// start by making a completely new copy.
// if (clickTabMenu == null) {
JMenuBar tabMenu = standardMenu;
try {
for (int i = 0; i < tabMenu.getMenuCount(); i++) {
if (tabMenu.getMenu(i).getText().equals("Settings")) {
//clickTabMenu.remove(clickTabMenu.getMenu(i));
aMenu = createDetectionMenu(parentFrame);
String txt = aMenu.getText();
tabMenu.add(aMenu, i+1);
break;
}
}
}
catch (Exception e) {
return standardMenu;
}
// }
return tabMenu;
}
protected void openTempDocuments() {
File tempFolder = dbxmlConnect.checkTempFolder();
if (tempFolder == null) {
@ -509,6 +537,12 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
tethysTaskManager.generateTasks();
}
break;
case PamControllerInterface.ADD_CONTROLLEDUNIT:
case PamControllerInterface.REMOVE_CONTROLLEDUNIT:
if (PamController.getInstance().isInitializationComplete()) {
sendStateUpdate(new TethysState(StateType.UPDATESERVER));
}
break;
}
}

View File

@ -94,6 +94,7 @@ public class CalibrationProcessCard extends CalibrationsCard {
c.gridx++;
c.gridwidth = 2;
processPanel.add(version, c);
version.setToolTipText("Serial number of calibration equipment");
c.gridx = 0;
c.gridy++;
c.gridwidth = 1;
@ -107,7 +108,9 @@ public class CalibrationProcessCard extends CalibrationsCard {
c.gridwidth = 2;
processPanel.add(qaComment, c);
this.add(BorderLayout.CENTER, makeScrollablePanel(software, "Calibration method"));
JScrollPane pane;
this.add(BorderLayout.CENTER, pane = makeScrollablePanel(software, "Software / method detail"));
pane.setToolTipText("Method detail, including details of any software used / references to published methods, etc.");
}

View File

@ -811,15 +811,15 @@ public class DetectionsHandler extends CollectionHandler {
/**
* Check the species map is OK before doing anything.
*/
DataBlockSpeciesManager spManager = dataBlock.getDatablockSpeciesManager();
if (spManager != null) {
String error = spManager.checkSpeciesMapError();
if (error != null) {
PamDialog.showWarning(PamController.getMainFrame(), "Datablock species manager error", error);
spManager.showSpeciesDialog();
return;
}
}
// DataBlockSpeciesManager spManager = dataBlock.getDatablockSpeciesManager();
// if (spManager != null) {
// String error = spManager.checkSpeciesMapError();
// if (error != null) {
// PamDialog.showWarning(PamController.getMainFrame(), "Datablock species manager error", error);
// spManager.showSpeciesDialog();
// return;
// }
// }
DetectionsExportWizard.showDialog(tethysControl.getGuiFrame(), tethysControl, dataBlock, true);

View File

@ -190,7 +190,7 @@ abstract public class DataBlockSpeciesManager<T extends PamDataUnit> /*implement
}
public void showSpeciesDialog() {
DataBlockSpeciesDialog.showDialog(PamController.getMainFrame(), dataBlock);
DataBlockSpeciesDialog.showDialog(PamController.getMainFrame(), dataBlock, null);
}
/**
@ -253,6 +253,18 @@ abstract public class DataBlockSpeciesManager<T extends PamDataUnit> /*implement
return null;
}
/**
* Used only in debug mode to clear the species map. Just used while
* debugging so that I can check that it's easy to recreate the map
* and that dialogs don't go screwy when it's empty.
*/
public void clearMap() {
if (datablockSpeciesMap == null) {
return;
}
datablockSpeciesMap.clearMap();
}
/*
@Override
public String getUnitName() {

View File

@ -177,7 +177,7 @@ public class SpeciesMapManager implements PamSettings {
return new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
importSpeciesMaps(parentFrame);
importSpeciesMaps(parentFrame, null);
}
};
}
@ -190,7 +190,7 @@ public class SpeciesMapManager implements PamSettings {
public boolean exportSpeciesMaps(Window parentFrame) {
// gather the species maps from the data blocks...
gatherSpeciesMaps();
GlobalSpeciesMap toExport = SpeciesMapIODialog.showDialog(parentFrame, globalSpeciesMap, true);
GlobalSpeciesMap toExport = SpeciesMapIODialog.showDialog(parentFrame, globalSpeciesMap, true, null);
if (toExport == null) {
return false;
}
@ -238,9 +238,10 @@ public class SpeciesMapManager implements PamSettings {
/**
* Import global species maps from selected file.
* @param parentFrame
* @param selectedBlock specific block, which will get checked by default in the dialog. Can be null
* @return
*/
public boolean importSpeciesMaps(Window parentFrame) {
public boolean importSpeciesMaps(Window parentFrame, String selectedBlock) {
JFileChooser chooser = getFileChooser();
int ans = chooser.showOpenDialog(parentFrame);
if (ans != JFileChooser.APPROVE_OPTION) {
@ -264,7 +265,7 @@ public class SpeciesMapManager implements PamSettings {
return false;
}
GlobalSpeciesMap keptMaps = SpeciesMapIODialog.showDialog(parentFrame, readSpeciesMap, false);
GlobalSpeciesMap keptMaps = SpeciesMapIODialog.showDialog(parentFrame, readSpeciesMap, false, selectedBlock);
if (keptMaps == null) {
return false;
}

View File

@ -18,16 +18,27 @@ import PamView.panel.PamNorthPanel;
import PamguardMVC.PamDataBlock;
import tethys.species.SpeciesMapManager;
/**
* Dialog to edit ITIS species codes for a datablock.
* @author dg50
*
*/
public class DataBlockSpeciesDialog extends PamDialog {
private static final long serialVersionUID = 1L;
private DataBlockSpeciesPanel speciesPanel;
private DataBlockSpeciesDialog(Window parentFrame, PamDataBlock dataBlock) {
/**
* Dialog to edit ITIS species codes.
* @param parentFrame parent window
* @param dataBlock data block
* @param singleSpecies single species if only one species to be shown. null for all species.
*/
private DataBlockSpeciesDialog(Window parentFrame, PamDataBlock dataBlock, String singleSpecies) {
super(parentFrame, dataBlock.getDataName() + " species", false);
JPanel mainPanel = new JPanel(new BorderLayout());
speciesPanel = new DataBlockSpeciesPanel(dataBlock);
speciesPanel = new DataBlockSpeciesPanel(dataBlock, singleSpecies);
mainPanel.add(BorderLayout.CENTER, speciesPanel.getDialogComponent());
JButton itisButton = new JButton("Go to ITIS web site");
@ -39,7 +50,7 @@ public class DataBlockSpeciesDialog extends PamDialog {
}
});
JPanel nPanel = new JPanel(new BorderLayout());
nPanel.setBorder(new TitledBorder("Code management"));
nPanel.setBorder(new TitledBorder("ITIS Code Management"));
nPanel.add(BorderLayout.EAST, new PamNorthPanel(itisButton));
String otherMsg =
"<html>Specify an ITIS taxonomic serial number (coding)."
@ -61,8 +72,15 @@ public class DataBlockSpeciesDialog extends PamDialog {
PamGui.openURL("https://www.itis.gov");
}
public static void showDialog(Window parentFrame, PamDataBlock dataBlock) {
DataBlockSpeciesDialog speciesDialog = new DataBlockSpeciesDialog(parentFrame, dataBlock);
/**
*
* Open Dialog to edit ITIS species codes.
* @param parentFrame parent window
* @param dataBlock data block
* @param singleSpecies single species if only one species to be shown. null for all species.
*/
public static void showDialog(Window parentFrame, PamDataBlock dataBlock, String singleSpecies) {
DataBlockSpeciesDialog speciesDialog = new DataBlockSpeciesDialog(parentFrame, dataBlock, singleSpecies);
speciesDialog.setParams();
speciesDialog.setVisible(true);
}

View File

@ -26,9 +26,18 @@ public class DataBlockSpeciesPanel implements PamDialogPanel {
private ArrayList<SpeciesSubPanel> subPanels = new ArrayList<>();
public DataBlockSpeciesPanel(PamDataBlock dataBlock) {
private String singleSpecies;
/**
* Panel of info about a species name in PAMGuard relating it to a call type and ITIS
* code for output to Tethys.
* @param dataBlock Datablock with a DataBlockSpeciesManager
* @param singleSpecies single species if only one species to be shown. null for all species.
*/
public DataBlockSpeciesPanel(PamDataBlock dataBlock, String singleSpecies) {
super();
this.dataBlock = dataBlock;
this.singleSpecies = singleSpecies;
mainPanel = new JPanel(new BorderLayout());
speciesPanel = new JPanel();
JScrollPane scrollPane = new JScrollPane(speciesPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
@ -53,6 +62,9 @@ public class DataBlockSpeciesPanel implements PamDialogPanel {
ArrayList<String> speciesNames = speciesManager.getAllSpeciesCodes();
DataBlockSpeciesMap speciesMap = speciesManager.getDatablockSpeciesMap();
for (String aSpecies : speciesNames) {
if (singleSpecies != null && singleSpecies.equals(aSpecies) == false) {
continue;
}
SpeciesSubPanel subPanel = new SpeciesSubPanel(dataBlock, aSpecies);
subPanels.add(subPanel);
speciesPanel.add(subPanel.getDialogComponent());

View File

@ -34,6 +34,8 @@ public class SpeciesMapIODialog extends PamDialog {
private JPanel boxesPanel;
private String preselectedBlock;
/**
* @param parentFrame
* @param title
@ -48,7 +50,7 @@ public class SpeciesMapIODialog extends PamDialog {
setDialogComponent(boxesPanel);
}
public static GlobalSpeciesMap showDialog(Window parentFrame, GlobalSpeciesMap speciesMap, boolean export) {
public static GlobalSpeciesMap showDialog(Window parentFrame, GlobalSpeciesMap speciesMap, boolean export, String selectedBlock) {
if (singleInstance == null) {
singleInstance = new SpeciesMapIODialog(parentFrame);
}
@ -56,6 +58,7 @@ public class SpeciesMapIODialog extends PamDialog {
singleInstance.showWarning("No Data block species maps are defined");
return speciesMap;
}
singleInstance.preselectedBlock = selectedBlock;
singleInstance.setTitle(export ? "Export species maps" : "Import species maps");
singleInstance.setParams(speciesMap);
singleInstance.setVisible(true);
@ -86,6 +89,9 @@ public class SpeciesMapIODialog extends PamDialog {
c.gridy++;
blockBoxes[iBox] = new JCheckBox(item.getKey());
boxesPanel.add(blockBoxes[iBox], c);
if (item.getKey().equals(preselectedBlock)) {
blockBoxes[iBox].setSelected(true);
}
iBox++;
}

View File

@ -20,10 +20,11 @@ import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;
import javax.swing.table.AbstractTableModel;
import PamModel.SMRUEnable;
import PamUtils.PamCalendar;
import PamView.dialog.warn.WarnOnce;
import PamView.panel.PamPanel;
@ -49,10 +50,8 @@ public class DatablockSynchPanel extends TethysExportPanel {
private ArrayList<DatablockSynchInfo> dataBlockSynchInfo;
private ArrayList<StreamTableObserver> tableObservers = new ArrayList<>();
// private TippedButton exportButton;
// private JLabel exportWarning;
private int selectedRow = -1;
public DatablockSynchPanel(TethysControl tethysControl) {
@ -65,31 +64,13 @@ public class DatablockSynchPanel extends TethysExportPanel {
new SwingTableColumnWidths(tethysControl.getUnitName()+"SynchTable", synchTable);
JScrollPane scrollPane = new JScrollPane(synchTable);
mainPanel.add(BorderLayout.CENTER, scrollPane);
// PamPanel ctrlPanel = new PamPanel(new BorderLayout());
// exportButton = new TippedButton("Export ...", "Export Detections document");
// exportWarning = new JLabel(" ");
// exportWarning.setForeground(Color.RED);
// ctrlPanel.add(BorderLayout.WEST, exportButton);
// ctrlPanel.add(BorderLayout.CENTER, exportWarning);
// mainPanel.add(BorderLayout.NORTH, ctrlPanel);
synchTable.addMouseListener(new MouseActions());
synchTable.addKeyListener(new KeyActions());
synchTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// exportButton.addActionListener(new ActionListener() {
// @Override
// public void actionPerformed(ActionEvent e) {
// exportData();
// }
// });
enableExportButton();
}
// @Override
// public JComponent getComponent() {
// return mainPanel;
// }
private class KeyActions extends KeyAdapter {
@Override
@ -132,6 +113,7 @@ public class DatablockSynchPanel extends TethysExportPanel {
if (row < 0) {
return row;
}
selectedRow = row;
DatablockSynchInfo synchInfo = dataBlockSynchInfo.get(row);
// datablockDetectionsPanel.setDataBlock(synchInfo.getDataBlock());
notifyObservers(synchInfo.getDataBlock());
@ -166,12 +148,15 @@ public class DatablockSynchPanel extends TethysExportPanel {
return;
}
PamDataBlock dataBlock = dataBlockSynchInfo.get(rows[0]).getDataBlock();
String mapError = checkSpeciesManager(dataBlock);
if (mapError != null) {
disableExport("Unable to export due to species map error: " + mapError + ". Right click table row to edit species list");
return;
}
/*
* don't do this any more since the species map can be edited within the export Wizard.
*/
// PamDataBlock dataBlock = dataBlockSynchInfo.get(rows[0]).getDataBlock();
// String mapError = checkSpeciesManager(dataBlock);
// if (mapError != null) {
// disableExport("Unable to export due to species map error: " + mapError + ". Right click table row to edit species list");
// return;
// }
enableExport(true);
}
@ -207,7 +192,7 @@ public class DatablockSynchPanel extends TethysExportPanel {
return;
}
JPopupMenu popMenu = new JPopupMenu();
JMenuItem menuItem = new JMenuItem("Species info ...");
JMenuItem menuItem = new JMenuItem("PAMGuard ITIS Species mapping ...");
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
@ -215,6 +200,19 @@ public class DatablockSynchPanel extends TethysExportPanel {
}
});
popMenu.add(menuItem);
if (SMRUEnable.isDevEnable()) {
menuItem = new JMenuItem("Clear species map");
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int ans = WarnOnce.showWarning("Delete datamap", "Are you sure ?", WarnOnce.YES_NO_OPTION);
if (ans == WarnOnce.OK_OPTION) {
speciesManager.clearMap();
}
}
});
popMenu.add(menuItem);
}
popMenu.show(e.getComponent(), e.getX(), e.getY());
}
@ -263,7 +261,7 @@ public class DatablockSynchPanel extends TethysExportPanel {
private class SynchTableModel extends AbstractTableModel {
String[] columnNames = {"Data Stream", "N PAM Datas", "PAMGuard Time", "Tethys Documents"};//, "Tethys Time", "Options"};
String[] columnNames = {"Select", "Data Stream", "N Data", "PAMGuard Time", "Tethys Documents"};//, "Tethys Time", "Options"};
@Override
public int getRowCount() {
@ -278,25 +276,38 @@ public class DatablockSynchPanel extends TethysExportPanel {
@Override
public String getColumnName(int column) {
return columnNames[column];
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 0) {
return Boolean.class;
}
return super.getColumnClass(columnIndex);
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
DatablockSynchInfo synchInfo = getSychInfos().get(rowIndex);
return getValueAt(synchInfo, columnIndex);
if (columnIndex == 0) {
return rowIndex == selectedRow;
}
else {
DatablockSynchInfo synchInfo = getSychInfos().get(rowIndex);
return getValueAt(synchInfo, columnIndex);
}
}
private Object getValueAt(DatablockSynchInfo synchInfo, int columnIndex) {
OfflineDataMap dataMap = synchInfo.getDataBlock().getPrimaryDataMap();
switch (columnIndex) {
case 0:
return synchInfo.getDataBlock().getLongDataName();
case 1:
return synchInfo.getDataBlock().getLongDataName();
case 2:
if (dataMap == null) {
return null;
}
return synchInfo.getDataBlock().getPrimaryDataMap().getDataCount();
case 2:
case 3:
if (dataMap == null) {
return null;
}
@ -306,7 +317,7 @@ public class DatablockSynchPanel extends TethysExportPanel {
long start = synchInfo.getDataBlock().getPrimaryDataMap().getFirstDataTime();
long stop = synchInfo.getDataBlock().getPrimaryDataMap().getLastDataTime();
return String.format("%s - %s", PamCalendar.formatDBDateTime(start), PamCalendar.formatDBDateTime(stop));
case 3:
case 4:
return synchInfo.getDetectionDocumentCount() + synchInfo.getLocalizationDocumentCount();
}
return null;

View File

@ -17,7 +17,7 @@ public class TethysTabPanel implements PamTabPanel {
@Override
public JMenu createMenu(Frame parentFrame) {
return null;
return tethysContol.createTethysMenu(parentFrame);
}
public TethysTabPanel(TethysControl tethysContol) {

View File

@ -2,15 +2,23 @@ package tethys.swing.export;
import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.TitledBorder;
import PamController.PamController;
import PamView.component.PamSettingsIconButton;
import PamView.dialog.PamGridBagContraints;
import PamView.dialog.warn.WarnOnce;
import PamView.panel.PamAlignmentPanel;
import PamView.wizard.PamWizard;
import PamguardMVC.PamDataBlock;
import tethys.TethysControl;
@ -18,6 +26,8 @@ import tethys.output.StreamExportParams;
import tethys.species.DataBlockSpeciesManager;
import tethys.species.DataBlockSpeciesMap;
import tethys.species.SpeciesMapItem;
import tethys.species.SpeciesMapManager;
import tethys.species.swing.DataBlockSpeciesDialog;
/**
* Wizard card to select call types (species) to export. Only these names will be added to the
@ -31,60 +41,183 @@ public class CallTypeCard extends ExportWizardCard {
// private DataBlockSpeciesCodes codes;
private JCheckBox[] speciesSelection;
private JLabel[] itisLabels;
private JLabel[] speciesNames;
private JLabel[] callTypes;
private JCheckBox commonNames;
private ArrayList<String> names;
private String bitTip = "Select species / call types to export\n"
+ "Only selected types will be added to the Document Effort section";
private DataBlockSpeciesMap speciesMap;
public CallTypeCard(TethysControl tethysControl, PamWizard pamWizard, String title, PamDataBlock dataBlock) {
super(tethysControl, pamWizard, title, dataBlock);
speciesManager = dataBlock.getDatablockSpeciesManager();
DataBlockSpeciesMap spMap = speciesManager.getDatablockSpeciesMap();
speciesMap = speciesManager.getDatablockSpeciesMap();
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.setBorder(new TitledBorder("Species / Call types to export"));
spPanel.setLayout(new GridBagLayout());
spPanel.setToolTipText(bitTip);
PamGridBagContraints c = new PamGridBagContraints();
commonNames = new JCheckBox("Species");
commonNames.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
fillAllItemInfo();
}
});
String[] tits = {"Select", "PAMGuard Name", "ITIS Code", "Species", "Call Type" };
String[] tips = {"Select for export", "Internal PAMGuard Name", "ITIS Species Code", "Species Name (check for common names)", "Call Type (written to Tethys)"};
for (int i = 0; i < tits.length; i++) {
JComponent lab;
if (i == 3) {
spPanel.add(lab=commonNames, c);
}
else {
spPanel.add(lab = new JLabel(tits[i], JLabel.LEFT), c);
}
lab.setToolTipText(tips[i]);
c.gridx++;
}
for (int i = 0; i < names.size(); i++) {
c.gridx = 0;
speciesSelection[i] = new JCheckBox(names.get(i));
spPanel.add(speciesSelection[i], c);
SpeciesMapItem item = spMap.getItem(names.get(i));
if (item != null) {
String latin = item.getLatinName();
int itis = item.getItisCode();
c.gridx++;
spPanel.add(new JLabel(String.format("%d", itis), JLabel.RIGHT), c);
c.gridx++;
if (latin != null) {
spPanel.add(new JLabel(latin));
}
}
c.gridy++;
}
speciesSelection[i] = new JCheckBox();
spPanel.add(speciesSelection[i], c);
c.gridx++;
spPanel.add(new JLabel(names.get(i)), c);
c.gridx++;
spPanel.add(itisLabels[i] = new JLabel(), c);
c.gridx++;
spPanel.add(speciesNames[i] = new JLabel(), c);
c.gridx++;
spPanel.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);
}
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(spPanel, BorderLayout.NORTH);
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);
}
}
private void fillItemInfo(int itemIndex) {
SpeciesMapItem item = speciesMap.getItem(names.get(itemIndex));
if (item == null) {
itisLabels[itemIndex].setText(null);
speciesNames[itemIndex].setText(null);
callTypes[itemIndex].setText(null);
}
else {
itisLabels[itemIndex].setText(Integer.valueOf(item.getItisCode()).toString());
if (commonNames.isSelected()) {
speciesNames[itemIndex].setText(item.getCommonName());
}
else {
speciesNames[itemIndex].setText(item.getLatinName());
}
callTypes[itemIndex].setText(item.getCallType());
}
}
protected void importSpeciesMap(JButton importButton) {
SpeciesMapManager mapManager = SpeciesMapManager.getInstance();
mapManager.importSpeciesMaps(getPamWizard(), getDataBlock().getLongDataName());
// has the map changed ?
DataBlockSpeciesMap newMap = getDataBlock().getDatablockSpeciesManager().getDatablockSpeciesMap();
if (newMap != speciesMap) {
// System.out.println("Map changed");
speciesMap = newMap;
fillAllItemInfo();
}
}
private class SpeciesAction implements ActionListener {
private int itemIndex;
public SpeciesAction(int itemIndex) {
this.itemIndex = itemIndex;
}
@Override
public void actionPerformed(ActionEvent e) {
String name = names.get(itemIndex);
DataBlockSpeciesDialog.showDialog(PamController.getMainFrame(), getDataBlock(), name);
fillItemInfo(itemIndex);
}
}
@Override
public boolean getParams(StreamExportParams cardParams) {
int nSel = 0;
int nError = 0;
for (int i = 0; i < names.size(); i++) {
boolean sel = speciesSelection[i].isSelected();
cardParams.setSpeciesSelection(names.get(i), sel);
if (sel) {
nSel++;
}
if (sel == false) {
continue; // don't check items that are not getting exported.
}
// check that the item has a valid species code and call type
SpeciesMapItem item = speciesMap.getItem(names.get(i));
if (item == null) {
nError++;
continue;
}
if (item.getItisCode() == 0) {
nError ++;
}
if (item.getCallType() == null || item.getCallType().length() == 0) {
nError ++;
}
}
if (nError > 0) {
WarnOnce.showWarning("Species / Call type selection", "One or more selected items do not have a valid ITIS code or a Call Type", WarnOnce.WARNING_MESSAGE);
return false;
}
if (nSel == 0) {
WarnOnce.showWarning("Species / Call type selection", "You must select at least one species or call type for export", WarnOnce.WARNING_MESSAGE);
// return false;
return false;
}
return nSel >= 0;
return true;
}
@Override

View File

@ -11,6 +11,7 @@ import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.TitledBorder;
import PamView.dialog.PamGridBagContraints;
@ -38,6 +39,8 @@ public class ExportWorkerCard extends ExportWizardCard implements DetectionExpor
private StreamExportParams streamExportParams;
private DetectionsExportWizard detectionsExportWizard;
private boolean exportDone = false;
public ExportWorkerCard(DetectionsExportWizard detectionsExportWizard, TethysControl tethysControl, PamDataBlock dataBlock) {
super(tethysControl, detectionsExportWizard, "Export", dataBlock);
@ -103,6 +106,8 @@ public class ExportWorkerCard extends ExportWizardCard implements DetectionExpor
}
protected void exportData() {
exportDone = false;
DetectionsHandler detHandler = getTethysControl().getDetectionsHandler();
detHandler.startExportThread(getDataBlock(), streamExportParams, this);
@ -116,8 +121,13 @@ public class ExportWorkerCard extends ExportWizardCard implements DetectionExpor
@Override
public boolean getParams(StreamExportParams streamExportParams) {
// TODO Auto-generated method stub
return true;
if (exportDone == false) {
exportData();
return false;
}
else {
return true;
}
}
@Override
@ -166,6 +176,7 @@ public class ExportWorkerCard extends ExportWizardCard implements DetectionExpor
detectionsExportWizard.getCancelButton().setText("Close");
detectionsExportWizard.getPreviousButton().setEnabled(false);
// getTethysControl().sendStateUpdate(new TethysState(StateType.EXPORTRDATA));
exportDone = true;
break;
case DetectionExportProgress.STATE_WRITING:
progressText.setText("Writing to Tethys: " + progress.currentDetections.getId());
@ -180,6 +191,19 @@ public class ExportWorkerCard extends ExportWizardCard implements DetectionExpor
cancel.setEnabled(!stopped);
detectionsExportWizard.getCancelButton().setEnabled(stopped);
detectionsExportWizard.getPreviousButton().setEnabled(stopped);
setButtonName();
}
private void setButtonName() {
String name = exportDone ? "Finish" : "Export";
String tip = exportDone ? "Close export wizard" : "Export selected data to Tethys";
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
detectionsExportWizard.getOkButton().setText(name);
detectionsExportWizard.getOkButton().setToolTipText(tip);
}
});
}
@Override
@ -189,7 +213,15 @@ public class ExportWorkerCard extends ExportWizardCard implements DetectionExpor
* we can see here if we're on this or not.
*/
super.setVisible(visible);
detectionsExportWizard.getOkButton().setEnabled(!visible);
// detectionsExportWizard.getOkButton().setEnabled(!visible);
if (visible) {
// doesn't work because it get's overridden by internal call
// to enable controls anyway.
setButtonName();
}
else {
detectionsExportWizard.enableControls(); // sets the button text.
}
}
}

View File

View File

@ -347,8 +347,8 @@ public class UserDisplayControl extends PamControlledUnit implements
@Override
public JMenuBar getTabSpecificMenuBar(Frame parentFrame, JMenuBar standardMenu, PamGui pamGui) {
// always make a new manu - modules may have been added or removed
// start bymaking a completely new copy.
// always make a new menu - modules may have been added or removed
// start by making a completely new copy.
spectrogramTabMenu = standardMenu;//pamGui.makeGuiMenu();
// if (spectrogramTabMenu == null) {
for (int i = 0; i < spectrogramTabMenu.getMenuCount(); i++) {