diff --git a/README.html b/README.html index a8b1ad86..f39f4964 100644 --- a/README.html +++ b/README.html @@ -388,7 +388,10 @@ PamguardBeta_ViewerMode.exe):

LATEST VERSION 2.02.08 May 2023

+href="#_Version_2.02.09_June">Latest Version 2.02.09 June 2023 + +

Version 2.02.08 May 2023

Version 2.02.07 January 2023

@@ -454,7 +457,17 @@ Version 2.00.10 June 2017

Latest Version 2.02.08 May +name="_Latest_Version_2.02.08">Version 2.02.09 June 2023

+ +

Bug Fixes

+ +

Time zone displays: Fixed some bugs +associated with options to have PAMGuard display times in local time, rather +than UTC. This was affecting times typed into the scroll bars of displays which +were reading local time, even when set to use UTC.

+ +

Version 2.02.08 May 2023

Bug Fixes

@@ -463,25 +476,41 @@ name="_Latest_Version_2.02.08">Latest Version 2.02.08 May which mostly occurred when processing large datasets of many offline files, has been fixed.

+

Data Map: “Scroll To Data” pop-up menu, +which didn’t always scroll to the correct place, is now fixed.

+ +

Bearing Localiser offline: If reprocessing +bearings, the localizer was not correctly loading required raw or FFT data to +input to the cross correlation algorithm. This is now fixed so that you can +reprocess bearings in viewer mode.

+ +

Map files: Added additional exception handlers +to handle corrupt map files.

+

New Features

Restart Options: When you restart processing of offline files, if output data already exist (binary data of -within database tables) you will be asked if you want to overwrite the data, cancel, -or try to continue from where to left off.

+within database tables) you will be asked if you want to overwrite the data, +cancel, or try to continue from where to left off.

Updated SoundTrap sud file interface so that PAMGuard now extracts and stores the Click Detector settings from the sud files and stores them within the PAMGuard configuration. This does not affect processing, but is important for record keeping.

+

GPS options to use any valid RMC or GGA +string. Not all GPS receivers output their RMC data as GPRMC – e.g. some may +output as GNRMC. A new option allows the GPS module to use any string, whatever +the first two characters of the string name may be.

+

Version 2.02.07 January 2023

Bug Fixes

-

Use of localization sensor and orientation -data for static hydrophones had a bug whereby it would continually ‘forget’ -angle offsets applied to static hydrophones in viewer mode. This is now fixed.

+

Use of localization sensor and orientation data +for static hydrophones had a bug whereby it would continually ‘forget’ angle +offsets applied to static hydrophones in viewer mode. This is now fixed.

Click tool bar: Correctly shows event selection options even if no species classification options are in place.

@@ -491,8 +520,8 @@ selection options even if no species classification options are in place.

ROCCA: Fixed (another) memory leak which -caused PAMGuard to crash when processing large data sets with the ROCCA classifier. -

+caused PAMGuard to crash when processing large data sets with the ROCCA +classifier.

Ishmael Modules: Fixed bug which occasionally caused crashes when processing many files offline.

@@ -534,10 +563,10 @@ whistle classification module.

SoundTrap SUD file reading. If you’re using SoundTrap autonomous recorders from Ocean Instruments, you no longer need to decompress the SoundTrap files prior to processing. This will save time and a -lot of disk space. Extraction of clicks from the inbuilt SoundTrap Click -detector can also happen while processing SUD file data with other detectors, -thereby streamlining the whole processing chain. Read the online Help for -details.   

+lot of disk space. Extraction of clicks from the inbuilt SoundTrap Click detector +can also happen while processing SUD file data with other detectors, thereby +streamlining the whole processing chain. Read the online Help for details. +  

Version 2.02.05 October 2022

@@ -640,9 +669,9 @@ selections from drop down lists within any form.

 

-

Note that updates have also been made to the Matlab -interface to PAMGuard binary files, which has now also been migrated to GitHub -at https://github.com/PAMGuard/PAMGuardMatlab. +

Note that updates have also been made to the Matlab interface +to PAMGuard binary files, which has now also been migrated to GitHub at https://github.com/PAMGuard/PAMGuardMatlab.

 

@@ -800,9 +829,9 @@ Update whistle and moan detector to better handle small stubs or spurs coming off the side of whistles

13.        -Extend the Hyperbolic Localiser to handle 2D planar arrays (previously limited -to 3D volumetric arrays)

+lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>       Extend the Hyperbolic Localiser to handle 2D planar arrays +(previously limited to 3D volumetric arrays)

14.        @@ -816,20 +845,20 @@ decimating/upsampling by a non-integer amount

16.        Noise Level Outputs - as an aid to performance diagnosis, some detectors -(currently the GPL, Click Detector and Whistle and Moan Detector) are outputting -additional noise metrics to their binary output files. These can be read with -the PAMGuard -Matlab library and used to diagnose system performance in varying noise -conditions. Improved displays within PAMGuard for these noise metrics will be -included in a future release.

+(currently the GPL, Click Detector and Whistle and Moan Detector) are +outputting additional noise metrics to their binary output files. These can be +read with the PAMGuard +Matlab library and used to diagnose system performance in varying noise conditions. +Improved displays within PAMGuard for these noise metrics will be included in a +future release.

17.        -An implementation of the Generalized Power Law Detector, developed by Tyler -Helble ([Helble et al., ‘A generalized power-law detection algorithm for humpback -whale vocalizationsĂ‚Â’, The Journal of the Acoustical Society of America, vol. -131, no. 4, pp. 2682–2699, 2012) is now available. For details, see the -online help

+lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>       An implementation of the Generalized Power Law Detector, +developed by Tyler Helble ([Helble et al., ‘A generalized power-law detection +algorithm for humpback whale vocalizationsĂ‚Â’, The Journal of the Acoustical +Society of America, vol. 131, no. 4, pp. 2682–2699, 2012) is now available. +For details, see the online help

18.        @@ -941,9 +970,10 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> &nb lang=EN-US> Better auto-scaling in Ishmael Detector graphics window.

7.        -Change to Windows temporary folder location, to get around Windows Security -settings that were preventing some modules from working properly.

+lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>       Change to Windows temporary folder location, to get around +Windows Security settings that were preventing some modules from working +properly.

@@ -1171,8 +1201,8 @@ lang=EN-US> Bug 436. Bug in Serial Port interface was occassionally causing PAMGuard to crash without error message.

5.        -Bug 437. Right whale detector crashing if no input was set.

+lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>       Bug 437. Right whale detector crashing if no input was set.

6.        @@ -1449,8 +1479,8 @@ Upgrades to the Group Localiser, including better error estimation.

2.        Click Train Detector upgrades, including ability to import -time chunks from csv file for batch processing.

+lang=EN-US> Click Train Detector upgrades, including ability to import time +chunks from csv file for batch processing.

3.        Better way of coupling scrollers in User Display panels - see new options in main menu.

2.        -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.

+lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>       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.

3.        @@ -1840,11 +1870,11 @@ to work with whistles.

3.        -Added option to export all settings and parameters as an XML-formatted file. -Note that this required changes to the structure of the Array Manager, and as -such any settings (psf) files created with this version of Pamguard cannot be -used in older versions. Older psf files can be loaded with this version, but -will be converted.

+Added option to export all settings and parameters as an XML-formatted file. Note +that this required changes to the structure of the Array Manager, and as such +any settings (psf) files created with this version of Pamguard cannot be used +in older versions. Older psf files can be loaded with this version, but will be +converted.

4.       

Upgrades

1.        -User is now able to specify Soundtrap date/time format

+lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>       User is now able to specify Soundtrap date/time format

@@ -2096,11 +2126,11 @@ the PAMGuard Viewer the older data will be converted to the new format (see below for details).

The most significant change in the binary -file format is the addition of a Unique Data Identifier (UID) to each unit of -data. This is intended to aid in offline analysis by making it easier for the -user to link what they are seeing on different PAMGuard displays and also to -link with any data post processed in Matlab or other custom analysis software. -UIDĂ‚Â’s are also added to PAMGuard database tables.

+file format is the addition of a Unique Data Identifier (UID) to each unit of data. +This is intended to aid in offline analysis by making it easier for the user to +link what they are seeing on different PAMGuard displays and also to link with +any data post processed in Matlab or other custom analysis software. UIDĂ‚Â’s +are also added to PAMGuard database tables.

Converting Old Data

@@ -2161,10 +2191,10 @@ so they will no longer work with older PAMGuard versions.

2.                   -Display colour options will be lost and most data displayed -on the map may default to black. This is due to the above changes to how -colours are managed. Changing back to the colours of your choice is relatively -simple through the PAMGuard GUI.

+Display colour options will be lost and most data +displayed on the map may default to black. This is due to the above changes to +how colours are managed. Changing back to the colours of your choice is +relatively simple through the PAMGuard GUI.

 

@@ -2206,8 +2236,8 @@ lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'> &nb

3.       -Rocca Module: added StartHr, ProportionWhists and ProportionClicks -parameters to Event classifier

+Rocca Module: added StartHr, ProportionWhists and ProportionClicks parameters +to Event classifier

4.       @@ -2358,10 +2388,10 @@ high sample rate.

2.       -Bug 305. Date and Time not being correctly -extracted from wav files created using SoundTrap recorders. Fixed by correctly -finding and unpacking information in the accompanying xml log files that come -with SoundTrap files.

+Bug 305. Date and Time not being correctly extracted +from wav files created using SoundTrap recorders. Fixed by correctly finding +and unpacking information in the accompanying xml log files that come with +SoundTrap files.

Version 1.15.06 November 2016

@@ -2488,8 +2518,8 @@ detector has been tidied up so that there are a) All Click, b) Tracked Clicks lang=EN-US style='font-size:7.0pt;font-family:"Times New Roman",serif'>       When tracking online, all the click marking information is written to the same database tables as are used for offline target motion -analysis. This means than when reviewing data offline, the tracks created in real -time are now available for review and further analysis.

+analysis. This means than when reviewing data offline, the tracks created in +real time are now available for review and further analysis.

4.       @@ -2719,8 +2749,8 @@ same click multiple times

1.       -Bug 253. Database import fails when Access database -contains queries. Fixed.

+Bug 253. Database import fails when Access database contains +queries. Fixed.

2.       @@ -3099,8 +3129,9 @@ to read on a time. Fixed

Menu Layout

-

The PAMGuard menus have been rearranged into a more intuitive -grouping which we believe will help users find functionality more easily.

+

The PAMGuard menus have been rearranged into a more +intuitive grouping which we believe will help users find functionality more +easily.

'Detection' menu has been renamed to 'Settings' since many menu items within this menu were not directly to do with 'Detection'.

@@ -3166,23 +3197,23 @@ whistles as well.

This module, funded by NOAA for the South West Fisheries Science Centre (SWFSC), measures pitch and roll from analogue accelerometer sensors in a hydrophone. Data are fed real time into the updated hydrophone -array manager in order that bearings from a tetrahedral tracking array are -correctly calculated in real world coordinates.

+array manager in order that bearings from a tetrahedral tracking array are correctly +calculated in real world coordinates.

Wild ArcGIS Interface (Maps and Mapping group)

This module, developed by Michael Oswald / SWFSC, allows -PAMGuard to output data in a format suitable for display in the WILD ArcGIS marine -mammal survey package. See online help for details.

+PAMGuard to output data in a format suitable for display in the WILD ArcGIS +marine mammal survey package. See online help for details.

Alarms (Utilities Group)

-

This is a general system of visual and audio alarms -developed by Doug Gillespie for use on a variety of projects. The alarms can be -coupled to any module or detector in PAMGuard. Where appropriate, modules can -control which of their data will cause an alarm action (e.g. in the Click -detector you can set which types of classified click will fire the alarm). See -online help for details.  

+

This is a general system of visual and audio alarms developed +by Doug Gillespie for use on a variety of projects. The alarms can be coupled +to any module or detector in PAMGuard. Where appropriate, modules can control +which of their data will cause an alarm action (e.g. in the Click detector you +can set which types of classified click will fire the alarm). See online help +for details.  

Noise Band Monitor (Sound Processing Group)

@@ -3230,9 +3261,9 @@ different. Details are available in the online help.

Can now read raw audio data direct from FLAC files. FLAC is a lossless compression -algorithm for audio data. Files, or folders of files are accessed in the same -way as WAV and AIFF files in the Sound Acquisition module. In a future release -we also hope to provide support for writing FLAC files from the sound recorder +algorithm for audio data. Files, or folders of files are accessed in the same way +as WAV and AIFF files in the Sound Acquisition module. In a future release we +also hope to provide support for writing FLAC files from the sound recorder module.

Sound Recorder Module

@@ -3276,9 +3307,8 @@ shaped Finite Impulse Response filters (see online help for details).

Radar Display

-

Can now show bearings relative to true North OR the vessel -heading. Also has the option of only showing certain types of click and -whistle.

+

Can now show bearings relative to true North OR the vessel heading. +Also has the option of only showing certain types of click and whistle.

Bug Fixes

@@ -3357,8 +3387,8 @@ survey software package.

Core Functionality

-

New storage options have been -implemented which give the user greater control of where data are stored.

+

New storage options have been implemented +which give the user greater control of where data are stored.

Modules have been arranged into different groups in the configuration menus and tool tip texts have been added @@ -3445,8 +3475,8 @@ inter-detection interval.

margin-left:36.0pt'> 

Target Motion Analysis: Updated target motion analysis -module so that it works in three (as opposed to two) dimensions.

+margin-left:36.0pt'>Target Motion Analysis: Updated target motion analysis module +so that it works in three (as opposed to two) dimensions.

 

@@ -3475,9 +3505,9 @@ have implemented database storage for output of these modules.

'         -Radar Display: A bug which stopped the radar display from correctly displaying -bearings to whistles from arrays containing more than two hydrophone elements -has been fixed.

+Radar Display: A bug which stopped the radar display from correctly +displaying bearings to whistles from arrays containing more than two hydrophone +elements has been fixed.

'         @@ -3683,8 +3713,8 @@ the correct data stream. This has been fixed.

'         Whistle classifier has some new features in the classifier training -panel. It is also now possible to export training data files directly from -binary data files.

+panel. It is also now possible to export training data files directly from binary +data files.

'         @@ -3746,8 +3776,8 @@ frequency division (i.e. previous versions would convert well from 96kHz to

Bug fixes

-

1. Placement of axes on some displays (array manager and depth -side panel). Problem in 1.9.01 Beta now fixed.

+

1. Placement of axes on some displays (array manager and +depth side panel). Problem in 1.9.01 Beta now fixed.

2. Fixed problems of NMEA read out not restarting after a serial drop out. NMEA now restarts correctly.

@@ -3935,12 +3965,12 @@ port is closed. Might prevent a few problems when using a GPS.

Bug Fixes

Crashes caused in real time or Mixed Mode if the number of -software channels exceeds the number of hydrophones configured in the array -manager. It is of course illogical to have software channels which are not -assigned to a hydrophone, so rather than entirely prevent PAMGUARD from -crashing I have inserted additional checks into the hydrophone array dialog -which will prevent the user from closing that dialog unless all software -channels are assigned to a hydrophone.

+software channels exceeds the number of hydrophones configured in the array manager. +It is of course illogical to have software channels which are not assigned to a +hydrophone, so rather than entirely prevent PAMGUARD from crashing I have +inserted additional checks into the hydrophone array dialog which will prevent +the user from closing that dialog unless all software channels are assigned to +a hydrophone.

Version 1.8.01 Beta February 2010

@@ -3990,9 +4020,9 @@ Symbol'>''         -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).

+
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).

 

@@ -4022,10 +4052,10 @@ synchronisation.

'         -Wigner time-frequency plot for the click detector. Clicks are NOT automatically -displayed in the Winger window as they are for the waveform and spectrum -windows since the Wigner transformation is very time consuming. Clicks will be -displayed if you select them with the mouse.

+Wigner time-frequency plot for the click detector. Clicks are NOT +automatically displayed in the Winger window as they are for the waveform and +spectrum windows since the Wigner transformation is very time consuming. Clicks +will be displayed if you select them with the mouse.

'         @@ -4042,8 +4072,8 @@ arrays to give two polar angle coordinates. this can be used to resolve left right ambiguity and is implemented for both the click and the whistle/moan detectors. As a result, the click detector bearing time display can now be set to go from -180 to 180 degrees rather than 0 - 180 degrees. In this case, -clicks in the upper half of the bearing display will be to port and clicks in -the right half will be to starboard. As you pass a whale which is to port, the +clicks in the upper half of the bearing display will be to port and clicks in the +right half will be to starboard. As you pass a whale which is to port, the clicks will move UP the display. In the long term, I hope to turn this display around so that time is up the screen rather than across. 

@@ -4120,9 +4150,9 @@ Symbol'>''         -Channel lists in output data streams of Decimator and other modules fixed, -so that when channel numbers change, downstream modules configurations get the -correct list of available channels.

+
Channel lists in output data streams of Decimator and other modules +fixed, so that when channel numbers change, downstream modules configurations +get the correct list of available channels.

'         @@ -4334,8 +4364,8 @@ acquisition. 

Bug fixes

-

Speed up of graphics, particularly regarding large -quantities of gps track  data

+

Speed up of graphics, particularly regarding large quantities +of gps track  data

National Instruments cards with names > 20 characters long are now correctly  recognised.

@@ -4701,7 +4731,8 @@ Symbol'>''1.0Beta 22 Jan 2008 - Pamguard -starts two releases, core and beta release,

+class=Heading2Char>1.0Beta 22 Jan 2008 - +Pamguard starts two releases, core and beta release,

this is the beta release

@@ -4763,8 +4794,8 @@ Symbol'>''         -Multi animal click tracking with least squares fit calculation of position -on map

+
Multi animal click tracking with least squares fit calculation of +position on map

'         @@ -4817,12 +4848,12 @@ and Ishmael-type detectors and localisers.

Information from above modules can be displayed on configurable user displays which support real time scrolling spectrograms and radar displays. Detection and localisation information can be optionally -displayed on the map display.Map enhancements include improved scrolling -whereby the user can click and drag to pan the area. PamGuard can now interface -with MySQL database servers and users can easily select which information is -logged. (This replaces the previous 'flat-file' logging feature). A simulation -module allows virtual vocalising animals to be placed on the map to assist in -training and development. Extensive online user help has been added to PamGuard +displayed on the map display.Map enhancements include improved scrolling whereby +the user can click and drag to pan the area. PamGuard can now interface with +MySQL database servers and users can easily select which information is logged. +(This replaces the previous 'flat-file' logging feature). A simulation module +allows virtual vocalising animals to be placed on the map to assist in training +and development. Extensive online user help has been added to PamGuard Application

0.03b - first version used in a real 'at sea' environment.18/08/06

diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml index a0157ae4..b5d893d2 100644 --- a/dependency-reduced-pom.xml +++ b/dependency-reduced-pom.xml @@ -4,7 +4,7 @@ org.pamguard Pamguard Pamguard Java12+ - 2.02.08 + 2.02.09 Pamguard for Java 12+, using Maven to control dependcies www.pamguard.org diff --git a/pom.xml b/pom.xml index 41f6aa34..6bae56a9 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.pamguard Pamguard - 2.02.08 + 2.02.09a Pamguard Java12+ Pamguard for Java 12+, using Maven to control dependcies www.pamguard.org diff --git a/src/Acquisition/FolderInputSystem.java b/src/Acquisition/FolderInputSystem.java index 3eed96ec..f3a33ed4 100644 --- a/src/Acquisition/FolderInputSystem.java +++ b/src/Acquisition/FolderInputSystem.java @@ -104,9 +104,13 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D boolean ans = super.prepareInputFile(); if (ans == false && ++currentFile < allFiles.size()) { System.out.println("Failed to open sound file. Try again with file " + allFiles.get(currentFile).getName()); - + /* + * jumping striaght to the next file messes it up if it thinks the files + * are continuous, so we HAVE to stop and restart. + */ +// return prepareInputFile(); PamController.getInstance().pamStop(); - PamController.getInstance().startLater(); + PamController.getInstance().startLater(false); } return ans; } @@ -614,16 +618,16 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D long currFileEnd = 0; if (currentFile >= 0) { try { - WavFileType currentWav = allFiles.get(currentFile); - currFileStart = getFileStartTime(currentWav.getAbsoluteFile()); - if (audioStream != null) { - fileSamples = audioStream.getFrameLength(); - currFileLength = (long) (fileSamples * 1000 / audioStream.getFormat().getFrameRate()); - currFileEnd = currFileStart + currFileLength; - } + WavFileType currentWav = allFiles.get(currentFile); + currFileStart = getFileStartTime(currentWav.getAbsoluteFile()); + if (audioStream != null) { + fileSamples = audioStream.getFrameLength(); + currFileLength = (long) (fileSamples * 1000 / audioStream.getFormat().getFrameRate()); + currFileEnd = currFileStart + currFileLength; + } } catch (Exception e) { - + } } if (currFileEnd == 0) { @@ -648,7 +652,17 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D } setFolderProgress(); // sayEta(); - ans = prepareInputFile(); + /* + * I think that here, we just need a check of the file. the prepareInputFile in + * this class will (on failure) move straight to the next file and also issue a + * stop/start, which is not good if it's trying a continuous file, where this is + * being called, if false is returned it should manage moving onto the next file by + * itself if we use the super.prep .... + */ + ans = super.prepareInputFile(); + if (ans == false) { + return false; + } currentFileStart = System.currentTimeMillis(); // if (ans && audioFormat.getSampleRate() != currentSampleRate && currentFile > 0) { // acquisitionControl.getDaqProcess().setSampleRate(currentSampleRate = audioFormat.getSampleRate(), true); diff --git a/src/Acquisition/filetypes/SUDFileType.java b/src/Acquisition/filetypes/SUDFileType.java index 80fd0a36..ef1d8a7a 100644 --- a/src/Acquisition/filetypes/SUDFileType.java +++ b/src/Acquisition/filetypes/SUDFileType.java @@ -22,7 +22,7 @@ public class SUDFileType extends SoundFileType { if (isShown) { return; } - WarnOnce.showWarning("SoundTrap SUD Files", sudInfoText, WarnOnce.OK_OPTION); +// WarnOnce.showWarning("SoundTrap SUD Files", sudInfoText, WarnOnce.OK_OPTION); isShown = true; } diff --git a/src/Acquisition/pamAudio/SudAudioFile.java b/src/Acquisition/pamAudio/SudAudioFile.java index b496301d..70c3eb46 100644 --- a/src/Acquisition/pamAudio/SudAudioFile.java +++ b/src/Acquisition/pamAudio/SudAudioFile.java @@ -48,9 +48,9 @@ public class SudAudioFile extends WavAudioFile { } // don't do anything and it will try the built in Audiosystem catch (UnsupportedAudioFileException e) { - System.err.println("Could not open sud file: not a supported file " + soundFile.getName()); - - e.printStackTrace(); + System.err.println("UnsupportedAudioFileException: Could not open sud file: not a supported file " + soundFile.getName()); + System.err.println(e.getMessage()); +// e.printStackTrace(); } catch (IOException e) { System.err.println("Could not open sud file: IO Exception: " + soundFile.getName()); diff --git a/src/Acquisition/pamAudio/SudAudioFileReader.java b/src/Acquisition/pamAudio/SudAudioFileReader.java index ba407e54..07de8053 100644 --- a/src/Acquisition/pamAudio/SudAudioFileReader.java +++ b/src/Acquisition/pamAudio/SudAudioFileReader.java @@ -46,7 +46,8 @@ public class SudAudioFileReader { try { sudAudioInputStream = SudAudioInputStream.openInputStream(file, sudParams, false); } catch (Exception e) { - e.printStackTrace(); + String msg = String.format("Corrupt sud file %s: %s", file.getName(), e.getMessage()); + throw new UnsupportedAudioFileException(msg); } return sudAudioInputStream; } diff --git a/src/GPS/GPSControl.java b/src/GPS/GPSControl.java index d4434f5a..4bbca604 100644 --- a/src/GPS/GPSControl.java +++ b/src/GPS/GPSControl.java @@ -245,6 +245,31 @@ public class GPSControl extends PamControlledUnit implements PamSettings, Positi public GpsDataUnit getShipPosition(long timeMilliseconds) { return getGpsDataBlock().getClosestUnitMillis(timeMilliseconds); } + /** + * Do we want this string ? It will be either RMC or GGA and may want wildcarding + * @param stringId + * @return + */ + public boolean wantString(String stringId) { + if (stringId == null || stringId.length() < 6) { + return false; + } + if (gpsControl.gpsParameters.allowWildcard) { + String lastBit = stringId.substring(3, 6); + switch (gpsControl.gpsParameters.mainString) { + case GPSParameters.READ_RMC: + return lastBit.equals("RMC"); + case GPSParameters.READ_GGA: + return lastBit.equals("GGA"); + default: + return false; + } + } + else { + String wantedString = gpsControl.getWantedString(); + return stringId.equals(wantedString); + } + } /** * Get the name of the string we're wanting. diff --git a/src/GPS/GPSParameters.java b/src/GPS/GPSParameters.java index 1046907f..719a59ca 100644 --- a/src/GPS/GPSParameters.java +++ b/src/GPS/GPSParameters.java @@ -59,6 +59,8 @@ public class GPSParameters implements Serializable, Cloneable, ManagedParameters public String rmcInitials = "GP"; public String ggaInitials = "GP"; + public boolean allowWildcard = true; + /** * Attempt to read true heading information */ diff --git a/src/GPS/GPSParametersDialog.java b/src/GPS/GPSParametersDialog.java index 73180239..6c54f139 100644 --- a/src/GPS/GPSParametersDialog.java +++ b/src/GPS/GPSParametersDialog.java @@ -149,9 +149,9 @@ public class GPSParametersDialog extends PamDialog { } } public static GPSParameters showDialog(Frame parentFrame, GPSParameters gpsParameters) { - if (parentFrame != lastFrame || gpsParametersDialog == null) { +// if (parentFrame != lastFrame || gpsParametersDialog == null) { gpsParametersDialog = new GPSParametersDialog(parentFrame); - } +// } gpsParametersDialog.gpsParameters = gpsParameters.clone(); gpsParametersDialog.setParams(); gpsParametersDialog.setVisible(true); @@ -335,6 +335,7 @@ public class GPSParametersDialog extends PamDialog { JRadioButton ggaString; JTextField rmcInitials; JTextField ggaInitials; + JCheckBox allowWildcard; public MainStringPanel() { super(); setBorder(new TitledBorder("Main Nav' data string")); @@ -344,9 +345,17 @@ public class GPSParametersDialog extends PamDialog { c.fill = GridBagConstraints.HORIZONTAL; ButtonGroup buttonGroup = new ButtonGroup(); - + + c.gridx = 0; + c.gridy++; + c.gridwidth = 5; + this.add(allowWildcard = new JCheckBox("Allow any string initials"), c); + allowWildcard.setToolTipText("Use RMC or GGA data from any source independent of the string initials (e.g. GP, GN, etc.)"); + c.gridy ++; + c.gridwidth = 1; + c.gridx=0; addComponent(this, new JLabel("RMC String"), c); - c.gridx++; + c.gridx ++; addComponent(this, rmcString = new JRadioButton(""), c); c.gridx++; addComponent(this, rmcInitials = new JTextField(2), c); @@ -355,6 +364,7 @@ public class GPSParametersDialog extends PamDialog { c.gridx = 0; c.gridy ++; + c.gridwidth = 1; addComponent(this, new JLabel("GGA String"), c); c.gridx++; addComponent(this, ggaString = new JRadioButton(""), c); @@ -363,6 +373,7 @@ public class GPSParametersDialog extends PamDialog { c.gridx++; addComponent(this, new JLabel(" GGA"), c); + allowWildcard.addActionListener(this); rmcString.addActionListener(this); ggaString.addActionListener(this); buttonGroup.add(rmcString); @@ -374,10 +385,12 @@ public class GPSParametersDialog extends PamDialog { ggaString.setSelected(gpsParameters.mainString == GPSParameters.READ_GGA); rmcInitials.setText(gpsParameters.rmcInitials); ggaInitials.setText(gpsParameters.ggaInitials); + allowWildcard.setSelected(gpsParameters.allowWildcard); enableControls(); } public boolean getParams() { + gpsParameters.allowWildcard = allowWildcard.isSelected(); if (ggaString.isSelected()) { gpsParameters.mainString = GPSParameters.READ_GGA; } @@ -385,12 +398,12 @@ public class GPSParametersDialog extends PamDialog { gpsParameters.mainString = GPSParameters.READ_RMC; } gpsParameters.rmcInitials = rmcInitials.getText(); - if (gpsParameters.rmcInitials.length() != 2) { - return false; + if (gpsParameters.rmcInitials.length() != 2 && !gpsParameters.allowWildcard) { + return showWarning("Expecting a two character identifier for RMC strings"); } gpsParameters.ggaInitials = ggaInitials.getText(); - if (gpsParameters.ggaInitials.length() != 2) { - return false; + if (gpsParameters.ggaInitials.length() != 2 && !gpsParameters.allowWildcard) { + return showWarning("Expecting a two character identifier for GGA strings"); } return true; } @@ -400,8 +413,9 @@ public class GPSParametersDialog extends PamDialog { } private void enableControls() { - rmcInitials.setEnabled(rmcString.isSelected()); - ggaInitials.setEnabled(ggaString.isSelected()); + boolean wild = allowWildcard.isSelected(); + rmcInitials.setEnabled(rmcString.isSelected() & !wild); + ggaInitials.setEnabled(ggaString.isSelected() & !wild); } diff --git a/src/GPS/ProcessNmeaData.java b/src/GPS/ProcessNmeaData.java index ca1d4cd3..b293a0c6 100644 --- a/src/GPS/ProcessNmeaData.java +++ b/src/GPS/ProcessNmeaData.java @@ -57,7 +57,7 @@ public class ProcessNmeaData extends PamProcess { private GpsLogger gpsLogger; - private String wantedString = "$GPRMC"; +// private String wantedString = "$GPRMC"; private GpsDataUnit previousUnit = null; @@ -161,7 +161,7 @@ public class ProcessNmeaData extends PamProcess { @Override public void noteNewSettings() { findNMEADataBlock(); - setWantedString(); +// setWantedString(); double minRate = Math.max(.2, 1./gpsController.gpsParameters.readInterval); processCheck.getOutputCounter().setMinRate(minRate); } @@ -179,7 +179,8 @@ public class ProcessNmeaData extends PamProcess { StringBuffer nmeaString = nmeaData.getCharData(); String stringId = NMEADataBlock.getSubString(nmeaString, 0); - if (stringId.equalsIgnoreCase(wantedString)) { +// if (stringId.equalsIgnoreCase(wantedString)) { + if (gpsController.wantString(stringId)) { gpsData = new GpsData(nmeaString, gpsController.gpsParameters.mainString); // GpsData constructor which // unpacks the string. if (gpsData.isDataOk()) { @@ -316,13 +317,13 @@ public class ProcessNmeaData extends PamProcess { super.clearOldData(); } - public String getWantedString() { - return wantedString; - } - - public void setWantedString() { - wantedString = gpsController.getWantedString(); - } +// public String getWantedString() { +// return wantedString; +// } +// +// public void setWantedString() { +// wantedString = gpsController.getWantedString(); +// } public GPSControl getGpsController() { return gpsController; diff --git a/src/GPS/UpdateClockDialog.java b/src/GPS/UpdateClockDialog.java index 9c266b64..03a33bf1 100644 --- a/src/GPS/UpdateClockDialog.java +++ b/src/GPS/UpdateClockDialog.java @@ -221,9 +221,8 @@ public class UpdateClockDialog extends JDialog implements ActionListener, PamObs // NMEADataBlock nmeaDataBlock = (NMEADataBlock) o; NMEADataUnit nmeaDataUnit = (NMEADataUnit) arg; StringBuffer nmeaData = nmeaDataUnit.getCharData(); - String wantedString = gpsControl.getWantedString(); String stringId = NMEADataBlock.getSubString(nmeaData, 0); - if (wantedString.equals(stringId) == false) { + if (gpsControl.wantString(stringId) == false) { return; } if (gpsControl.gpsParameters.mainString == GPSParameters.READ_GGA) { @@ -232,6 +231,8 @@ public class UpdateClockDialog extends JDialog implements ActionListener, PamObs newRMCData(nmeaData); } } + + @Override public void updateData(PamObservable observable, PamDataUnit pamDataUnit) { // TODO Auto-generated method stub diff --git a/src/Localiser/detectionGroupLocaliser/TMGroupLocInfo.java b/src/Localiser/detectionGroupLocaliser/TMGroupLocInfo.java index ace2b8aa..5ceef849 100644 --- a/src/Localiser/detectionGroupLocaliser/TMGroupLocInfo.java +++ b/src/Localiser/detectionGroupLocaliser/TMGroupLocInfo.java @@ -810,6 +810,9 @@ public class TMGroupLocInfo implements GroupLocInfo { for (int i = 0; i < nSubDetections; i++) { localisation = getParentDetection().getSubDetection(i).getLocalisation(); + if (localisation == null) { + continue; + } angles = localisation.getAngles(); angleErrors = localisation.getAngleErrors(); @@ -879,6 +882,10 @@ public class TMGroupLocInfo implements GroupLocInfo { totalVectors += nVectors; } + if (totalVectors == 0) { + return; + } + //now create the separate arrays for different ambiguities. /** * diff --git a/src/PamController/PamguardVersionInfo.java b/src/PamController/PamguardVersionInfo.java index b83f6404..b7e3b529 100644 --- a/src/PamController/PamguardVersionInfo.java +++ b/src/PamController/PamguardVersionInfo.java @@ -31,12 +31,12 @@ public class PamguardVersionInfo { * Version number, major version.minorversion.sub-release. * Note: can't go higher than sub-release 'f' */ - static public final String version = "2.02.08"; + static public final String version = "2.02.09a"; /** * Release date */ - static public final String date = "9 May 2023"; + static public final String date = "29 June 2023"; // /** // * Release type - Beta or Core diff --git a/src/PamController/command/CommandManager.java b/src/PamController/command/CommandManager.java index 87f4b888..d6b06fc0 100644 --- a/src/PamController/command/CommandManager.java +++ b/src/PamController/command/CommandManager.java @@ -42,6 +42,7 @@ public abstract class CommandManager extends PamControlledUnit { commandsList.add(new SetXMLSettings()); commandsList.add(new BatchStatusCommand()); commandsList.add(new BatchCommand(this)); + commandsList.add(new FindGUICommand()); } diff --git a/src/PamController/command/FindGUICommand.java b/src/PamController/command/FindGUICommand.java new file mode 100644 index 00000000..526e7e2f --- /dev/null +++ b/src/PamController/command/FindGUICommand.java @@ -0,0 +1,27 @@ +package PamController.command; + +import PamController.PamController; +import PamView.GuiFrameManager; + +public class FindGUICommand extends ExtCommand { + + public FindGUICommand() { + super("findgui", true); + } + + @Override + public String execute(String command) { + GuiFrameManager frameManager = PamController.getInstance().getGuiFrameManager(); + if (frameManager == null) { + return "No GUI to move"; + } + frameManager.findGUI(); + return "GUI Moved"; + } + + @Override + public String getHint() { + return "Move GUI components to the main monitor"; + } + +} diff --git a/src/PamController/settings/SettingsImport.java b/src/PamController/settings/SettingsImport.java index ac4736a9..2269b3f7 100644 --- a/src/PamController/settings/SettingsImport.java +++ b/src/PamController/settings/SettingsImport.java @@ -1,5 +1,6 @@ package PamController.settings; +import java.io.ByteArrayInputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; @@ -14,6 +15,7 @@ import PamController.PamController; import PamController.PamSettingManager; import PamController.PamSettings; import PamController.PamSettingsGroup; +import PamModel.PamModel; import PamModel.PamModuleInfo; import PamModel.SMRUEnable; import PamView.dialog.PamFileBrowser; @@ -226,7 +228,13 @@ public class SettingsImport { ownerClass = Class.forName(aSet.getOwnerClassName()); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block - e.printStackTrace(); +// e.printStackTrace(); + // this is happening since the ownerclassname is not set correctly in psfx files + // so we have to deserialise the data to find the class. +// ownerClass = getClassFromData(aSet.getSerialisedByteArray()); +// ownerClass = PamModuleInfo.findModuleClass(aSet.getUnitType()); + } + if (ownerClass == null) { continue; } if (PamControlledUnit.class.isAssignableFrom(ownerClass)) { @@ -263,6 +271,17 @@ public class SettingsImport { return groupedSettings; } + + private Class getClassFromData(byte[] data) { + try { + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data)); + Object obj = ois.readObject(); + return obj.getClass(); + } catch (Exception e) { + return null; + } + + } private SettingsImportGroup findGroup(ArrayList groupedSettings, String unitName) { for (SettingsImportGroup iG:groupedSettings) { diff --git a/src/PamModel/PamModel.java b/src/PamModel/PamModel.java index 4ce627dc..8c2b3bda 100644 --- a/src/PamModel/PamModel.java +++ b/src/PamModel/PamModel.java @@ -45,14 +45,10 @@ import fftManager.FFTDataUnit; import fftManager.PamFFTControl; import group3dlocaliser.Group3DLocaliserControl; import meygenturbine.MeygenTurbine; -import networkTransfer.receive.BuoyStatusDataUnit; -import networkTransfer.receive.NetworkReceiver; import printscreen.PrintScreenControl; import rockBlock.RockBlockControl; import turbineops.TurbineOperationControl; import GPS.GpsDataUnit; -import Map.MapController; -import Map.gridbaselayer.GridbaseControl; import NMEA.NMEADataUnit; import PamController.PamControlledUnitSettings; import PamController.PamController; @@ -66,7 +62,6 @@ import PamguardMVC.PamDataBlock; import analogarraysensor.ArraySensorControl; import backupmanager.BackupManager; import beamformer.continuous.BeamFormerControl; -import beamformer.localiser.BeamFormLocaliserControl; import bearinglocaliser.BearingLocaliserControl; import binaryFileStorage.SecondaryBinaryStore; import cepstrum.CepstrumControl; @@ -1067,7 +1062,7 @@ final public class PamModel implements PamModelInterface, PamSettings { // clear the current list pluginList.clear(); daqList.clear(); - + /* * If developing a new PAMPlugin in eclipse, the easiest way to do it is to make a new * Eclipse project for your plugin code. Within that project, copy this PamModel class @@ -1082,7 +1077,6 @@ final public class PamModel implements PamModelInterface, PamSettings { * When you export the code for your plugin to a jar file, remember to NOT inlcude the copy of * PamModel ! */ - // Load up whatever default classloader was used to create this class. Must use the same classloader // for all plugins, or else we will not be able to create proper dependencies between them or be able @@ -1150,30 +1144,11 @@ final public class PamModel implements PamModelInterface, PamSettings { // to add that URL to the default classloader path. URL newURL = jarList.get(i).toURI().toURL(); - // original method -// Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); -// method.setAccessible(true); -// method.invoke(cl, newURL); - - // first fix attempt - create a brand new URLClassLoader. As expected, we get a ClassCastException when trying - // to load the parameters so we can't save params using this method -// URL[] newURLArray = new URL[1]; -// newURLArray[0] = newURL; -// cl = new URLClassLoader(newURLArray); // second attempt - custom class loader with the system app loader specified as the parent. Loads controlled unit, but // as before it doesn't load the parameters classLoader.addURL(newURL); - // third attempt -// Class genericClass = cl.getClass(); -// Method method = genericClass.getSuperclass().getDeclaredMethod("addURL", new Class[] {URL.class}); -// method.setAccessible(true); -// method.invoke(cl, new Object[] {newURL}); - - - - // Save the name of the class to the global pluginBeingLoaded variable, and load the class. this.setPluginBeingLoaded(className); // Class c = cl.loadClass(className); @@ -1254,9 +1229,8 @@ final public class PamModel implements PamModelInterface, PamSettings { "for help.

" + "This plug-in will not be available for loading"; String help = null; - int ans = WarnOnce.showWarning(PamController.getMainFrame(), title, msg, WarnOnce.WARNING_MESSAGE, help, e1); + int ans = WarnOnce.showWarning(PamController.getInstance().getGuiFrameManager().getFrame(0), title, msg, WarnOnce.WARNING_MESSAGE, help, e1); System.err.println("Exception while loading " + className); - System.err.println(e1.getMessage()); continue; } } @@ -1269,7 +1243,7 @@ final public class PamModel implements PamModelInterface, PamSettings { "for help.

" + "This plug-in will not be available for loading"; String help = null; - int ans = WarnOnce.showWarning(PamController.getMainFrame(), title, msg, WarnOnce.WARNING_MESSAGE, help, ex); + int ans = WarnOnce.showWarning(PamController.getInstance().getGuiFrameManager().getFrame(0), title, msg, WarnOnce.WARNING_MESSAGE, help, ex); System.err.println("Exception while loading " + jarList.get(i).getName()); continue; } @@ -1294,7 +1268,7 @@ final public class PamModel implements PamModelInterface, PamSettings { // instantiate the plugin control class using the custom class loader try { - File classFile = new File(pf.getJarFile()); +// File classFile = new File(pf.getJarFile()); //URLClassLoader cl = new URLClassLoader(new URL[]{classFile.toURI().toURL()}); // mi = PamModuleInfo.registerControlledUnit(pf.getClassName(), pf.getDescription(),cl); mi = PamModuleInfo.registerControlledUnit(pf.getClassName(), pf.getDescription(),classLoader); @@ -1360,7 +1334,7 @@ final public class PamModel implements PamModelInterface, PamSettings { "for help.

" + "This plug-in will not be available for loading"; String help = null; - int ans = WarnOnce.showWarning(PamController.getMainFrame(), title, msg, WarnOnce.WARNING_MESSAGE, help, e1); + int ans = WarnOnce.showWarning(PamController.getInstance().getGuiFrameManager().getFrame(0), title, msg, WarnOnce.WARNING_MESSAGE, help, e1); System.err.println("Exception while loading " + pf.getDefaultName()); pluginList.remove(pf); continue; diff --git a/src/PamModel/PamModuleInfo.java b/src/PamModel/PamModuleInfo.java index 1f4edc3a..8284e145 100644 --- a/src/PamModel/PamModuleInfo.java +++ b/src/PamModel/PamModuleInfo.java @@ -282,6 +282,7 @@ public class PamModuleInfo implements PamDependent{ return moduleClass; } + public static JMenu getModulesMenu(Frame parentFrame) { diff --git a/src/PamUtils/PamCalendar.java b/src/PamUtils/PamCalendar.java index d41aa018..452e06e5 100644 --- a/src/PamUtils/PamCalendar.java +++ b/src/PamUtils/PamCalendar.java @@ -47,7 +47,10 @@ public class PamCalendar { public static TimeZone defaultTimeZone = TimeZone.getTimeZone("UTC"); - private static TimeZone localTimeZone = TimeZone.getDefault(); + /* + * Not used: all now handled in PamCalendar. + */ +// private static TimeZone localTimeZone = defaultTimeZone;// TimeZone.getDefault(); public static final long millisPerDay = 1000L*24L*3600L; @@ -60,7 +63,7 @@ public class PamCalendar { private static boolean soundFile; /** - * time from the start of the file to the currentmoment. + * time from the start of the file to the current moment. * This is updated every time data re read from the file, so is * accurate to about 1/10 second. * For accurate timing within detectors, always try to use sample number @@ -177,8 +180,44 @@ public class PamCalendar { public static TimeZone getDisplayTimeZone(boolean useLocal) { // return TimeZone.getTimeZone("UTC"); -// return useLocal ? CalendarControl.getInstance().getChosenTimeZone() : defaultTimeZone; - return useLocal ? localTimeZone : defaultTimeZone; + return useLocal ? CalendarControl.getInstance().getChosenTimeZone() : defaultTimeZone; +// return useLocal ? localTimeZone : defaultTimeZone; + } + + /** + * Get the display time zone offset in milliseconds. + * @param useLocal + * @return + */ + public static long getDisplayTimeZoneOffest(boolean useLocal) { + TimeZone tz = getDisplayTimeZone(useLocal); + return tz.getOffset(getTimeInMillis()); + } + + /** + * Get a short string describing the time zone. This should be less than + * 10 characters. So if the full name of the TZ is long, then write it + * in the format "UTC+..." + * @param useLocal + * @return + */ + public static String getShortDisplayTimeZoneString(boolean useLocal) { + TimeZone tz = getDisplayTimeZone(useLocal); + String str = tz.getDisplayName(); + str = CalendarControl.getInstance().getTZCode(true); + if (str.length() <= 10) { + return str; + } + // otherwise make up a string. + long offset = getDisplayTimeZoneOffest(useLocal) / 1000; + boolean isInt = offset % 3600 == 0; + if (isInt) { + str = String.format("UTC%+d", offset/3600); + } + else { + str = String.format("UTC%+3.1f", (double) offset/3600.); + } + return str; } public static String formatDateTime(Date date) { @@ -391,8 +430,13 @@ public class PamCalendar { public static String formatDBStyleTime(long timeInMillis, boolean showMillis, boolean useLocal) { Calendar c = Calendar.getInstance(); + TimeZone tz = getDisplayTimeZone(useLocal); +// if (tz != null) { +// long offs = tz.getOffset(timeInMillis); +// timeInMillis += tz.getOffset(timeInMillis); +// } c.setTimeInMillis(timeInMillis); - c.setTimeZone(getDisplayTimeZone(useLocal)); + c.setTimeZone(tz); DateFormat df; if (showMillis) { df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); @@ -400,7 +444,7 @@ public class PamCalendar { else { df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } - df.setTimeZone(getDisplayTimeZone(useLocal)); + df.setTimeZone(tz); Date d = c.getTime(); // return String.format("%tY-%Note that all processing and data storage will continue to

use UTC, the selection " + - "you make here \nwill only affect what is displayed on the screen"); + ta.setText("Note that all processing and data storage will continue to use UTC.

The selection " + + "you make here will only affect what is displayed on the screen."); tzPanel.add(ta, c); ButtonGroup bg = new ButtonGroup(); @@ -66,7 +66,7 @@ public class TimeZoneDisplayDialog extends PamDialog { bg.add(usePC); bg.add(useOther); - thisTimeZone = Calendar.getInstance().getTimeZone(); + TimeZone pcTimeZone = TimeZone.getDefault(); timeZoneIds = TimeZone.getAvailableIDs(); Arrays.sort(timeZoneIds, new TimeZoneComparator()); TimeZone tz; @@ -76,7 +76,7 @@ public class TimeZoneDisplayDialog extends PamDialog { if (timeZoneIds[i].equals(PamCalendar.defaultTimeZone.getID())) { utcTZIndex = i; } - if (timeZoneIds[i].equals(thisTimeZone.getID())) { + if (timeZoneIds[i].equals(pcTimeZone.getID())) { pcTZIndex = i; } if (tz.getRawOffset() < 0) { @@ -118,7 +118,8 @@ public class TimeZoneDisplayDialog extends PamDialog { useUTC.setSelected(timeDisplayParameters.zoneType == TimeDisplayParameters.TIME_ZONE_UTC); usePC.setSelected(timeDisplayParameters.zoneType == TimeDisplayParameters.TIME_ZONE_PC); useOther.setSelected(timeDisplayParameters.zoneType == TimeDisplayParameters.TIME_ZONE_OTHER); - pcTimeZone.setText(String.format("(%s / %s)", thisTimeZone.getID(), thisTimeZone.getDisplayName())); + TimeZone defaultTimeZone = TimeZone.getDefault(); + pcTimeZone.setText(String.format("(%s / %s)", defaultTimeZone.getID(), defaultTimeZone.getDisplayName())); enableControls(); showSelection(); } @@ -165,7 +166,7 @@ public class TimeZoneDisplayDialog extends PamDialog { } else if (usePC.isSelected()) { timeDisplayParameters.zoneType = TimeDisplayParameters.TIME_ZONE_PC; - timeDisplayParameters.timeZone = thisTimeZone; + timeDisplayParameters.timeZone = TimeZone.getDefault(); } else if (useOther.isSelected()) { timeDisplayParameters.zoneType = TimeDisplayParameters.TIME_ZONE_OTHER; diff --git a/src/PamView/GuiFrameManager.java b/src/PamView/GuiFrameManager.java index 030628c0..b49da8d7 100644 --- a/src/PamView/GuiFrameManager.java +++ b/src/PamView/GuiFrameManager.java @@ -633,5 +633,26 @@ public class GuiFrameManager implements PamSettings, PAMControllerGUI { return frameIcon; } + /** + * Function that can move GUI frames back onto the main window. + * Can be used to recover a GUI if it's on a monitor that is not present. + */ + public void findGUI() { + if (pamViewList == null) { + return; + } + int loc = 10; + for (PamViewInterface view : pamViewList) { + JFrame frame = view.getGuiFrame(); + if (frame == null) { + continue; + } + frame.setLocation(loc, loc); + frame.setState(JFrame.NORMAL); + frame.setVisible(true); + loc += 20; + } + } + } diff --git a/src/PamView/PamGui.java b/src/PamView/PamGui.java index 34f9b000..548927b0 100644 --- a/src/PamView/PamGui.java +++ b/src/PamView/PamGui.java @@ -223,31 +223,30 @@ public class PamGui extends PamView implements WindowListener, PamSettings { PamSettingManager.getInstance().registerSettings(this); if (guiParameters.bounds != null) { - /* - * now need to check that the frame is visible on the - * current screen - a pain when psf files are sent between - * users, or when I work on two screens at work and then one - * at home ! - */ - // Rectangle screenRect = ScreenSize.getScreenBounds(20000); - Rectangle screenRect = ScreenSize.getScreenBounds(); - // Rectangle intercept = screenRect.intersection(frame.getBounds()); - if (screenRect == null) { - System.out.println("Unable to get screen dimensions from system"); +// /* +// * now need to check that the frame is visible on the +// * current screen - a pain when psf files are sent between +// * users, or when I work on two screens at work and then one +// * at home ! +// */ + + Point topCorner = guiParameters.bounds.getLocation(); + boolean posOK = true; + try { + posOK = ScreenSize.isPointOnScreen(topCorner); + // some weird stuff going down whereby the screen position is + // given as -8 from the corner where it really it. this can return + // false and then push the display onto a different monitor, so alow for this. + if (posOK == false) { + topCorner.x += 10; + topCorner.y += 10; + posOK = ScreenSize.isPointOnScreen(topCorner); + } + } catch (Exception e) { } - else { - while (guiParameters.bounds.x + guiParameters.bounds.width < screenRect.x + 200) { - guiParameters.bounds.x += screenRect.width; - } - while (guiParameters.bounds.x > screenRect.x+screenRect.width) { - guiParameters.bounds.x -= screenRect.width; - } - while (guiParameters.bounds.y + guiParameters.bounds.height < screenRect.y + 200) { - guiParameters.bounds.y += screenRect.height; - } - while (guiParameters.bounds.y > screenRect.y+screenRect.height) { - guiParameters.bounds.y -= screenRect.height; - } + if (!posOK) { + // put it in the top corner of the main screen. + guiParameters.bounds.x = guiParameters.bounds.y = 10; } frame.setBounds(guiParameters.bounds); diff --git a/src/PamView/ScreenSize.java b/src/PamView/ScreenSize.java index a51863a2..4b4d905b 100644 --- a/src/PamView/ScreenSize.java +++ b/src/PamView/ScreenSize.java @@ -3,6 +3,7 @@ package PamView; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; +import java.awt.Point; import java.awt.Rectangle; import java.util.List; @@ -15,7 +16,7 @@ import javafx.scene.layout.Pane; /** * Class to launch a thread which will get the screen size - * (inlcuding the bounds of multiple monitors) + * (including the bounds of multiple monitors) *

* The process of getting the dimensions is launched in a * different thread and can be going on while other PAMGAURD @@ -32,40 +33,6 @@ public class ScreenSize { private static Rectangle[] screenDimensions; -// private volatile static boolean hasRun = false; -// -// private ScreenSize() { -// //Problems with startup on Mac that -// //seem to have been caused by the -// //GetBounds not being invoked from within -// //the Event Display Thread -// //CJB 2009-06-15 -//// SwingUtilities.invokeLater(new GetBounds()); -// //old version -// //Thread thread = new Thread(new GetBounds()); -// //thread.start(); -// long m1 = System.currentTimeMillis(); -// findScreenBounds(); -// long m2 = System.currentTimeMillis(); -// System.out.println("screen bounds took ms: " + (m2-m1)); -// } -// -// /** -// * Only needs to be called once to -// * start the background process which gets -// * the virtual screen size. -// *

-// * Is called from PAMGUARD Main to get it -// * going asap. -// */ -// public static void startScreenSizeProcess() { -// if (hasRun == false) { -// hasRun = true; -// new ScreenSize(); -// } -// -// } -// /** * Gets the screen bounds, sum / union of all screens. * @return Virtual screen size, or null. @@ -103,40 +70,6 @@ public class ScreenSize { return screenDimensions[iScreen]; } -// /** -// * Gets the virtual screen size. Will wait for them to be -// * extracted from the background thread up to some set timeout -// * @param maxWaitMillis Max time to wait. -// * @return virtual screen dimension, or null if unavailable -// * after the set wait period. -// */ -// public static Rectangle getScreenBounds(int maxWaitMillis) { -// -// startScreenSizeProcess(); -// -// long endTime = System.currentTimeMillis() + maxWaitMillis; -// while (System.currentTimeMillis() <= endTime) { -// if (screenDimension != null) { -// return screenDimension; -// } -// try { -// Thread.sleep(100); -// } -// catch (InterruptedException e) { -// return screenDimension; -// } -// } -// return screenDimension; -// } -// -// /** -// * -// * @return true if screen bounds are available. -// */ -// public boolean haveScreenBounds() { -// return (screenDimension != null); -// } - private static Rectangle findScreenBounds() { Rectangle virtualBounds = new Rectangle(); if (PamGUIManager.getGUIType() == PamGUIManager.NOGUI) { @@ -160,40 +93,50 @@ public class ScreenSize { //let PAMGUARD start up a little quicker //CJB 2009-06-15 GraphicsConfiguration dgc = gd.getDefaultConfiguration(); - // System.out.printf("", dgc.getBufferCapabilities().) - // System.out.println(dgc); screenDimensions[j] = dgc.getBounds(); virtualBounds = virtualBounds.union(dgc.getBounds()); } } - // new Pane(); - // List screens = Screen.getScreens(); - // if (screens != null) { - // for (Screen aScreen : screens) { - // System.out.printf("Screen resX %d, resY %d\n", - // aScreen.getResolutionX(), - // aScreen.getResolutionY()); - // } - // } - //System.out.println("virtualBounds="+virtualBounds); + return virtualBounds; } + + + /** + * Pushes a rectangle so that it's visible on the screen. + * @param bounds - will get modified in place. + * @return true if the position was changed. + */ + public static boolean forceBoundToScreen(Rectangle bounds) { + try { + if (isPointOnScreen(bounds.getLocation()) == false) { + bounds.x = bounds.y = 0; + return true; + } + } catch (Exception e) { + return false; + } + return false; + } + + /** + * Test to see if the point is within the bounds of any available monitor + * @param point point + * @return true if it's within the bounds of any montor + * @throws Exception Thrown if there are no monitors. + */ + public static boolean isPointOnScreen(Point point) throws Exception { + if (screenDimensions == null || screenDimensions.length == 0) { + throw new Exception("No attached screens. Can't test point"); + } + for (int i = 0; i < screenDimensions.length; i++) { + if (screenDimensions[i].contains(point)) { + return true; + } + } + return false; + } - // /** - // * Thread to obtain the screen bounds. -// * @author Doug -// * -// */ -// public class GetBounds implements Runnable { -// -// @Override -// public void run() { -// -// screenDimension = findScreenBounds(); -// -// } -// -// } } diff --git a/src/PamView/paneloverlay/overlaymark/OverlayMarkProviders.java b/src/PamView/paneloverlay/overlaymark/OverlayMarkProviders.java index a9d4611e..5bcc67ee 100644 --- a/src/PamView/paneloverlay/overlaymark/OverlayMarkProviders.java +++ b/src/PamView/paneloverlay/overlaymark/OverlayMarkProviders.java @@ -49,7 +49,7 @@ public class OverlayMarkProviders { continue; } String existingName = marker.getMarkerName(); - if (existingName.equals(nameToAdd)) { + if (existingName!=null && existingName.equals(nameToAdd)) { markProviders.remove(i); break; } diff --git a/src/PamView/symbol/PamSymbolManager.java b/src/PamView/symbol/PamSymbolManager.java index 96d74f46..440f3111 100644 --- a/src/PamView/symbol/PamSymbolManager.java +++ b/src/PamView/symbol/PamSymbolManager.java @@ -125,7 +125,7 @@ abstract public class PamSymbolManager implements Pa * This doesn't work since different displays will still need different options based on * their projector - so it can work, but need to set the projector. */ - if (managedSymbolData.useGeneric) { + if (managedSymbolData.useGeneric || displayName==null) { displayName = GENERICNAME; } diff --git a/src/PamguardMVC/dataSelector/DataSelectDialog.java b/src/PamguardMVC/dataSelector/DataSelectDialog.java index 38c4fbc1..5fd7f81f 100644 --- a/src/PamguardMVC/dataSelector/DataSelectDialog.java +++ b/src/PamguardMVC/dataSelector/DataSelectDialog.java @@ -34,7 +34,7 @@ public class DataSelectDialog extends PamDialog { private static final String helpPoint = "displays.dataselect.docs.selectandsymbol"; public DataSelectDialog(Window parentFrame, PamDataBlock pamDataBlock, DataSelector dataSelector, PamSymbolChooser symbolChooser) { - super(parentFrame, pamDataBlock.getDataName(), false); + super(parentFrame, (pamDataBlock==null) ? "Data Selection":pamDataBlock.getDataName(), false); this.dataSelector = dataSelector; this.symbolChooser = symbolChooser; tabPane = new JTabbedPane(); diff --git a/src/PamguardMVC/dataSelector/DataSelectorSettings.java b/src/PamguardMVC/dataSelector/DataSelectorSettings.java index 7d593f4d..f29c8103 100644 --- a/src/PamguardMVC/dataSelector/DataSelectorSettings.java +++ b/src/PamguardMVC/dataSelector/DataSelectorSettings.java @@ -23,7 +23,9 @@ public class DataSelectorSettings implements Serializable, ManagedParameters { if (selectorParams == null) { selectorParams = new Hashtable<>(); } + if (name != null) { selectorParams.put(name, params); + } } /** diff --git a/src/annotation/userforms/UserFormSQLAddon.java b/src/annotation/userforms/UserFormSQLAddon.java index acecc6cc..fb5a20f0 100644 --- a/src/annotation/userforms/UserFormSQLAddon.java +++ b/src/annotation/userforms/UserFormSQLAddon.java @@ -28,6 +28,7 @@ public class UserFormSQLAddon implements SQLLoggingAddon { } ArrayList loggerTableItems = new ArrayList<>(); + private ArrayList controlDescriptions; @Override @@ -38,7 +39,13 @@ public class UserFormSQLAddon implements SQLLoggingAddon { return; } UDFTableDefinition formTableDef = formDescription.getUdfTableDefinition(); - ArrayList controlDescriptions = formDescription.getInputControlDescriptions(); + controlDescriptions = formDescription.getInputControlDescriptions(); + /* + * It's possible the controlDescriptions get rewritten, so hold references to + * the actual items buy copying the list. + */ + controlDescriptions = new ArrayList<>(controlDescriptions); + for (ControlDescription cd:controlDescriptions) { FormsTableItem[] ctrlTableItems = cd.getFormsTableItems(); if (ctrlTableItems != null) { @@ -73,15 +80,25 @@ public class UserFormSQLAddon implements SQLLoggingAddon { // is created. So the inputControls list in FormDescription will only point to the last set of controls created, // which isn't necessarily the ones that this table is pointing to. Instead, load the loggerTableItems with // the data because loggerTableItems and pamTableDefinition both point to the same thing + /* + * That doesn't work though since some controls have > 1 field, so it all gets out of synch. HAVE to + * use the moveDataToTableItems fields for it to work. + */ // ArrayList inputCtrls = formDescription.getInputControlDescriptions(); // ControlDescription cd; // for (int i = 0; i < inputCtrls.size(); i++) { // cd = inputCtrls.get(i); // cd.moveDataToTableItems(datas[i]); // } - for (int i = 0; i < loggerTableItems.size(); i++) { - loggerTableItems.get(i).setValue(datas[i]); + for (int i = 0; i < controlDescriptions.size(); i++) { + controlDescriptions.get(i).moveDataToTableItems(datas[i]); } + + // below doesn't work since some controls have > 1 field (e.g. latlong, +// int n = Math.min(loggerTableItems.size(), datas.length); +// for (int i = 0; i < n; i++) { +// loggerTableItems.get(i).setValue(datas[i]); +// } return true; } diff --git a/src/detectiongrouplocaliser/dialogs/DetectionGroupTable.java b/src/detectiongrouplocaliser/dialogs/DetectionGroupTable.java index 48986214..3dd7ecb8 100644 --- a/src/detectiongrouplocaliser/dialogs/DetectionGroupTable.java +++ b/src/detectiongrouplocaliser/dialogs/DetectionGroupTable.java @@ -10,6 +10,7 @@ import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.ListIterator; @@ -31,10 +32,12 @@ import PamUtils.PamCalendar; import PamView.PamColors; import PamView.PamSymbol; import PamView.PamSymbolType; +import PamView.component.DataBlockTableView; import PamView.dialog.PamGridBagContraints; import PamView.dialog.warn.WarnOnce; import PamView.tables.SwingTableColumnWidths; import PamguardMVC.PamDataBlock; +import PamguardMVC.dataSelector.DataSelector; import annotation.DataAnnotation; import annotation.DataAnnotationType; import detectiongrouplocaliser.DetectionGroupControl; @@ -44,12 +47,11 @@ import detectiongrouplocaliser.DetectionGroupObserver; import detectiongrouplocaliser.DetectionGroupProcess; import detectiongrouplocaliser.GroupAnnotationHandler; import pamScrollSystem.AbstractScrollManager; -import pamScrollSystem.PamScroller; import userDisplay.UserDisplayComponentAdapter; -import warnings.PamWarning; /** - * Panel to show a table of data on all DetectionGroup data units. + * Panel to show a table of data on all DetectionGroup data units. + * * @author dg50 * */ @@ -75,12 +77,17 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements private JButton checkIntegrity; + private JButton dataSelection; + private boolean isViewer; private DisplayOptionsHandler displayOptionsHandler; private SwingTableColumnWidths widthManager; +// private DataBlockTableView groupTableView; + private ArrayList dataCopy; + public DetectionGroupTable(DetectionGroupProcess detectionGroupProcess) { super(); this.detectionGroupProcess = detectionGroupProcess; @@ -104,14 +111,20 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements JPanel lControlPanel = new JPanel(new GridBagLayout()); controlPanel.add(BorderLayout.WEST, lControlPanel); GridBagConstraints c = new PamGridBagContraints(); - lControlPanel.add(showAll = displayOptionsHandler.createButton(DisplayOptionsHandler.SHOW_ALL, "Show all groups in database", false), c); + lControlPanel.add(showAll = displayOptionsHandler.createButton(DisplayOptionsHandler.SHOW_ALL, + "Show all groups in database", false), c); c.gridx++; - lControlPanel.add(showCurrent = displayOptionsHandler.createButton(DisplayOptionsHandler.SHOW_CURRENT, "Show only data currently loaded", false), c); + lControlPanel.add(showCurrent = displayOptionsHandler.createButton(DisplayOptionsHandler.SHOW_CURRENT, + "Show only data currently loaded", false), c); c.gridx++; checkIntegrity = new JButton("Check Data Integrity"); checkIntegrity.setToolTipText("Check and fix start and end times of events against the database data"); + dataSelection = new JButton("Data Selection"); + dataSelection.setToolTipText("Select data to list"); lControlPanel.add(checkIntegrity, c); checkIntegrity.setVisible(detectionGroupControl.isViewer()); + c.gridx++; + lControlPanel.add(dataSelection, c); showAll.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -133,19 +146,39 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements detectionGroupProcess.checkDataIntegrity(); } }); + dataSelection.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dataSelectionButton(e); + } + }); } - - // sortColumnWidths(); + // sortColumnWidths(); } + protected void dataSelectionButton(ActionEvent e) { + DataSelector dataSelector = getDataSelector(); + if (dataSelector != null) { + boolean changed = dataSelector.showSelectDialog(null); + if (changed) { + dataChanged(); + } + } + } + + private DataSelector getDataSelector() { + return detectionGroupDataBlock.getDataSelector(getUniqueName(), isViewer); + } @Override public Component getComponent() { return mainPanel; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see userDisplay.UserDisplayComponentAdapter#openComponent() */ @Override @@ -154,8 +187,9 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements super.openComponent(); } - - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see userDisplay.UserDisplayComponentAdapter#closeComponent() */ @Override @@ -166,7 +200,9 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements private class TableMouseHandler extends MouseAdapter { - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see java.awt.event.MouseAdapter#mouseClicked(java.awt.event.MouseEvent) */ @Override @@ -176,7 +212,9 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements } } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see java.awt.event.MouseAdapter#mousePressed(java.awt.event.MouseEvent) */ @Override @@ -186,7 +224,9 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements } } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see java.awt.event.MouseAdapter#mouseReleased(java.awt.event.MouseEvent) */ @Override @@ -197,9 +237,17 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements } } - @Override public void dataChanged() { + long t1 = 0; + long t2 = Long.MAX_VALUE; + if (showCurrent.isSelected()) { + t1 = detectionGroupDataBlock.getCurrentViewDataStart(); + t2 = detectionGroupDataBlock.getCurrentViewDataEnd(); + } + dataCopy = detectionGroupDataBlock.getDataCopy(t1, t2, false, getDataSelector()); + Collections.sort(dataCopy); + tableModel.fireTableDataChanged(); } @@ -208,17 +256,17 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements } - public void editSelectedEvent() { DetectionGroupDataUnit dgdu = getSelectedDataRow(); - if (dgdu == null) return; + if (dgdu == null) + return; editGroup(dgdu); } - public void showPopupMenu(MouseEvent e) { DetectionGroupDataUnit dgdu = getSelectedDataRow(); - if (dgdu == null) return; + if (dgdu == null) + return; PamSymbol menuIcon = new PamSymbol(detectionGroupControl.getSymbolforMenuItems(dgdu)); JPopupMenu pMenu = new JPopupMenu("Detection Group UID " + dgdu.getUID()); JMenuItem menuItem; @@ -235,23 +283,23 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements menuItem.setIcon(menuIcon); pMenu.add(menuItem); - int[] beforeTimesSecs = {0, 10, 60}; + int[] beforeTimesSecs = { 0, 10, 60 }; pMenu.addSeparator(); for (int i = 0; i < beforeTimesSecs.length; i++) { int before = beforeTimesSecs[i]; String title; if (before == 0) { - title = "Scroll to Group UID " + dgdu.getUID() + " at " + PamCalendar.formatDBDateTime(dgdu.getTimeMilliseconds()); - } - else { + title = "Scroll to Group UID " + dgdu.getUID() + " at " + + PamCalendar.formatDBDateTime(dgdu.getTimeMilliseconds()); + } else { title = String.format("Scroll to %ds before Group UID %d", before, dgdu.getUID()); } menuItem = new JMenuItem(title); - // menuItem.setIcon(menuIcon); + // menuItem.setIcon(menuIcon); menuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - scrollToEvent(dgdu.getTimeMilliseconds()-before*1000); + scrollToEvent(dgdu.getTimeMilliseconds() - before * 1000); } }); pMenu.add(menuItem); @@ -261,24 +309,22 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements } protected void scrollToEvent(long timeMilliseconds) { - // start a it earlier. + // start a it earlier. // timeMilliseconds -= 5000; - // now WTF - how do I tell every scroller to go to this point in time ? + // now WTF - how do I tell every scroller to go to this point in time ? AbstractScrollManager scrollManager = AbstractScrollManager.getScrollManager(); scrollManager.startDataAt(detectionGroupDataBlock, timeMilliseconds); } - protected void editGroup(DetectionGroupDataUnit dgdu) { detectionGroupProcess.editDetectionGroup(dgdu); dataChanged(); } - protected void deleteGroup(DetectionGroupDataUnit dgdu, boolean askFirst) { if (askFirst) { - int ans = WarnOnce.showWarning(PamController.getMainFrame(), "Delete Group Detection", + int ans = WarnOnce.showWarning(PamController.getMainFrame(), "Delete Group Detection", "Are you sure you want to permanently delete this group detection ?", WarnOnce.OK_CANCEL_OPTION); if (ans == WarnOnce.CANCEL_OPTION) { return; @@ -288,17 +334,17 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements dataChanged(); } - /** * - * @return which data row is selected, or null. + * @return which data row is selected, or null. */ private DetectionGroupDataUnit getSelectedDataRow() { int row = table.getSelectedRow(); - if (row < 0) { + if (row < 0 || dataCopy == null || row >= dataCopy.size()) { return null; } - return (DetectionGroupDataUnit) detectionGroupDataBlock.getDataUnit(row, PamDataBlock.REFERENCE_ABSOLUTE); + return dataCopy.get(row); +// return (DetectionGroupDataUnit) detectionGroupDataBlock.getDataUnit(row, PamDataBlock.REFERENCE_ABSOLUTE); } @Override @@ -311,7 +357,7 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements private void sortColumnWidths() { for (int i = 0; i < tableModel.getColumnCount(); i++) { TableColumn tableCol = table.getColumnModel().getColumn(i); - tableCol.setPreferredWidth(tableModel.getRelativeWidth(i)*50); + tableCol.setPreferredWidth(tableModel.getRelativeWidth(i) * 50); } } @@ -319,8 +365,7 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements private int getViewOption() { if (!isViewer) { return DisplayOptionsHandler.SHOW_ALL; - } - else if (showCurrent != null) { + } else if (showCurrent != null) { if (showCurrent.isSelected()) { return displayOptionsHandler.SHOW_CURRENT; } @@ -334,7 +379,7 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements private List> usedAnnotations; private ArrayList columnNames = new ArrayList<>(); private int nBaseColumns = 4; - PamSymbol symbol = new PamSymbol(PamSymbolType.SYMBOL_SQUARE,48,12,true,Color.BLACK,Color.BLUE); + PamSymbol symbol = new PamSymbol(PamSymbolType.SYMBOL_SQUARE, 48, 12, true, Color.BLACK, Color.BLUE); private int firstRowToShow; private int numRowsToShow; @@ -351,7 +396,9 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements return columnNames.size(); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see javax.swing.table.AbstractTableModel#getColumnName(int) */ @Override @@ -361,37 +408,47 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements @Override public int getRowCount() { - // System.out.println("getRowCount()"); - if (getViewOption() == DisplayOptionsHandler.SHOW_ALL) { - firstRowToShow = 0; - return numRowsToShow = detectionGroupDataBlock.getUnitsCount(); - } - else { - // work through datablock and work out the first and n indexes to show. - firstRowToShow = -1; - int lastRowToShow = -1; - int i = 0; - synchronized (detectionGroupDataBlock.getSynchLock()) { - ListIterator it = detectionGroupDataBlock.getListIterator(0); - while (it.hasNext()) { - DetectionGroupDataUnit nextData = (DetectionGroupDataUnit) it.next(); - if (nextData.getSubDetectionsCount() > 0) { - if (firstRowToShow < 0) { - firstRowToShow = i; - } - lastRowToShow = i+1; - } - i++; - } - } - return lastRowToShow - firstRowToShow; + // System.out.println("getRowCount()"); + if (dataCopy == null) { + return 0; } + return dataCopy.size(); + +// if (getViewOption() == DisplayOptionsHandler.SHOW_ALL) { +// firstRowToShow = 0; +// return numRowsToShow = dataCopy.size(); +//// return numRowsToShow = detectionGroupDataBlock.getUnitsCount(); +// } +// else { +// // work through datablock and work out the first and n indexes to show. +// firstRowToShow = -1; +// int lastRowToShow = -1; +// int i = 0; +// synchronized (detectionGroupDataBlock.getSynchLock()) { +// ListIterator it = detectionGroupDataBlock.getListIterator(0); +// while (it.hasNext()) { +// DetectionGroupDataUnit nextData = (DetectionGroupDataUnit) it.next(); +// if (nextData.getSubDetectionsCount() > 0) { +// if (firstRowToShow < 0) { +// firstRowToShow = i; +// } +// lastRowToShow = i+1; +// } +// i++; +// } +// } +// return lastRowToShow - firstRowToShow; +// } } @Override public Object getValueAt(int iRow, int iCol) { + if (dataCopy == null) { + return null; + } try { - DetectionGroupDataUnit dgdu = (DetectionGroupDataUnit) detectionGroupDataBlock.getDataUnit(iRow+firstRowToShow, PamDataBlock.REFERENCE_ABSOLUTE); +// DetectionGroupDataUnit dgdu = (DetectionGroupDataUnit) detectionGroupDataBlock.getDataUnit(iRow+firstRowToShow, PamDataBlock.REFERENCE_ABSOLUTE); + DetectionGroupDataUnit dgdu = dataCopy.get(iRow); if (dgdu == null) { return null; } @@ -403,15 +460,14 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements return symbol; case 1: if (dgdu.getUpdateCount() > 0) { - return "*"+dgdu.getUpdateCount(); - } - else { + return "*" + dgdu.getUpdateCount(); + } else { return null; } case 2: - // if (iRow == 0) { - // System.out.println("getValueAt(0,0)"); - // } + // if (iRow == 0) { + // System.out.println("getValueAt(0,0)"); + // } return dgdu.getUID(); case 3: return PamCalendar.formatDateTime(dgdu.getTimeMilliseconds()); @@ -432,8 +488,7 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements } - } - catch (Exception e) { + } catch (Exception e) { return null; } return null; @@ -447,7 +502,9 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements return super.getColumnClass(col); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see javax.swing.table.AbstractTableModel#fireTableStructureChanged() */ @Override @@ -463,25 +520,25 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements // count columns in each annotation ... annotationHandler = detectionGroupProcess.getAnnotationHandler(); usedAnnotations = annotationHandler.getUsedAnnotationTypes(); - for (DataAnnotationType annotation:usedAnnotations) { + for (DataAnnotationType annotation : usedAnnotations) { columnNames.add(annotation.getAnnotationName()); } super.fireTableStructureChanged(); } - /** - * Attempt to set column widths. + * Attempt to set column widths. + * * @param colIndex * @return relative column widths. */ public int getRelativeWidth(int colIndex) { - switch(colIndex) { + switch (colIndex) { case 0: return 1; case 1: return 1; - case 2: + case 2: return 5; case 3: return 5; @@ -491,7 +548,9 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements } } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see userDisplay.UserDisplayComponentAdapter#setUniqueName(java.lang.String) */ @Override @@ -500,6 +559,4 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements super.setUniqueName(uniqueName); } - - } diff --git a/src/difar/DifarProcess.java b/src/difar/DifarProcess.java index 694c4529..644da952 100644 --- a/src/difar/DifarProcess.java +++ b/src/difar/DifarProcess.java @@ -316,11 +316,19 @@ public class DifarProcess extends PamProcess { sP = difarControl.getDifarParameters().findSpeciesParams(difarDataUnit); } difarDataUnit.setDisplaySampleRate(sP.sampleRate); - if (!sP.useMarkedBandsForSpectrogramClips){ - double[] frequency = {sP.processFreqMin, sP.processFreqMax}; - difarDataUnit.setFrequency(frequency); + if (difarDataUnit.triggerName.equals(difarControl.getUnitName())) { // User detection + if (!sP.useMarkedBandsForSpectrogramClips ){ + double[] frequency = {sP.processFreqMin, sP.processFreqMax}; + difarDataUnit.setFrequency(frequency); + } + } else { //Check whether to override auto detection freq limits with DIFAR limits + if (!sP.useDetectionLimitsForTriggeredDetections ){ // Auto-detection + double[] frequency = {sP.processFreqMin, sP.processFreqMax}; + difarDataUnit.setFrequency(frequency); + } } + demuxDataUnit(difarDataUnit, demuxWorker, startTime); calculateDifarGram(difarDataUnit, demuxWorker, startTime); diff --git a/src/group3dlocaliser/dialog/GroupLocSettingPaneFX.java b/src/group3dlocaliser/dialog/GroupLocSettingPaneFX.java index 3efc949b..da7f91c7 100644 --- a/src/group3dlocaliser/dialog/GroupLocSettingPaneFX.java +++ b/src/group3dlocaliser/dialog/GroupLocSettingPaneFX.java @@ -173,6 +173,9 @@ public class GroupLocSettingPaneFX extends SettingsPane{ algoOptsButton.setDisable(true); return; } + // also enable / disable the more options button ... + algoOptsButton.setDisable(localiserAlgorithm.hasParams() == false); + /** * Need to immediately tell the algorithm which input we're using so that it can * show the correct settings... @@ -208,10 +211,7 @@ public class GroupLocSettingPaneFX extends SettingsPane{ // newPane.setDetectionSource(sourcePanel.getSource()); } algorithmSourcePane = newPane; - - // also enable / disable the more options button ... - algoOptsButton.setDisable(localiserAlgorithm.hasParams() == false); - + repackDialog(); } diff --git a/src/help/mapping/NMEA/docs/ConfiguringGPS.html b/src/help/mapping/NMEA/docs/ConfiguringGPS.html index 29bc1eda..6c2e9ce6 100644 --- a/src/help/mapping/NMEA/docs/ConfiguringGPS.html +++ b/src/help/mapping/NMEA/docs/ConfiguringGPS.html @@ -36,7 +36,10 @@ From the Detection Menu, select GPS>GPS Options

On very rare occasions, if the GPS data have been multiplexed through some other instruments, the first two characters of the string identifier are changed. If this is the case, it may also be necessary to set these -so that the GPS module can identify the appropriate data. +so that the GPS module can identify the appropriate data. As an alternative, select the "Allow and string initials" option +which will use any valid RMC or GGA string. Note however, that with a complex NMEA system there may be more than one GPS and +it is better to select only strings from the most accurate

+

Read Options

Three options for reading and storing GPS data are available.

diff --git a/src/help/mapping/NMEA/docs/images/GPSOptions1.png b/src/help/mapping/NMEA/docs/images/GPSOptions1.png index 02f26ec1..33964051 100644 Binary files a/src/help/mapping/NMEA/docs/images/GPSOptions1.png and b/src/help/mapping/NMEA/docs/images/GPSOptions1.png differ diff --git a/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java b/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java index 930377b1..aebed235 100644 --- a/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java +++ b/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java @@ -107,7 +107,8 @@ public class DLClassifyProcess extends PamInstantProcess { addOutputDataBlock(dlDetectionDataBlock); dlDetectionDataBlock.setNaturalLifetimeMillis(600*1000); //keep this data for a while. dlDetectionDataBlock.addDataAnnotationType(dlAnnotationType); - + //ClipGeneration allows processing of detections by DIFAR module (and possibly others) + dlDetectionDataBlock.setCanClipGenerate(true); //add custom graphics PamDetectionOverlayGraphics overlayGraphics = new DLGraphics(dlModelResultDataBlock); overlayGraphics.setDetectionData(true); @@ -483,7 +484,7 @@ public class DLClassifyProcess extends PamInstantProcess { DataUnitBaseData basicData = groupDataBuffer.get(0).getBasicData().clone(); basicData.setMillisecondDuration(1000.*rawdata[0].length/this.sampleRate); - basicData.setSampleDuration((long) (groupDataBuffer.size()*dlControl.getDLParams().sampleHop)); + basicData.setSampleDuration((long) (groupDataBuffer.size()*dlControl.getDLParams().rawSampleSize)); // System.out.println("Model result: " + modelResult.size()); DLDetection dlDetection = new DLDetection(basicData, rawdata);