mirror of
https://github.com/PAMGuard/PAMGuard.git
synced 2024-11-21 22:52:22 +00:00
Deployment and Detections work
Big tidy up of Deployment and Detections output. Think it' spretty close to a functional system now.
This commit is contained in:
parent
3059e087ac
commit
2e29e9cd95
@ -47,7 +47,11 @@ public class ClickEventSpeciesManager extends DataBlockSpeciesManager {
|
||||
@Override
|
||||
public String getSpeciesCode(PamDataUnit dataUnit) {
|
||||
OfflineEventDataUnit eventDataUnit = (OfflineEventDataUnit) dataUnit;
|
||||
return eventDataUnit.getEventType();
|
||||
String eventType = eventDataUnit.getEventType();
|
||||
if (eventType == null) {
|
||||
eventType = "Unknown";
|
||||
}
|
||||
return eventType;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import java.io.Serializable;
|
||||
import PamUtils.LatLong;
|
||||
import nilus.ContactInfo;
|
||||
import nilus.Deployment;
|
||||
import nilus.DeploymentRecoveryDetails;
|
||||
import nilus.DescriptionType;
|
||||
import nilus.Helper;
|
||||
import nilus.MetadataInfo;
|
||||
@ -24,6 +25,8 @@ public class PamguardMetaData implements Serializable {
|
||||
|
||||
private NilusSettingsWrapper<Deployment> deploymentWrapper;
|
||||
|
||||
public boolean useAudioForDeploymentTimes = true;
|
||||
|
||||
// /**
|
||||
// * Deployment time (used if different
|
||||
// */
|
||||
@ -64,6 +67,13 @@ public class PamguardMetaData implements Serializable {
|
||||
if (deployment.getMetadataInfo().getContact().getContactInfo() == null) {
|
||||
deployment.getMetadataInfo().getContact().setContactInfo(new ContactInfo());
|
||||
}
|
||||
|
||||
if (deployment.getDeploymentDetails() == null) {
|
||||
deployment.setDeploymentDetails(new DeploymentRecoveryDetails());
|
||||
}
|
||||
if (deployment.getRecoveryDetails() == null) {
|
||||
deployment.setRecoveryDetails(new DeploymentRecoveryDetails());
|
||||
}
|
||||
return deployment;
|
||||
}
|
||||
|
||||
|
@ -2,27 +2,16 @@ package metadata.swing;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Point;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
import PamController.PamController;
|
||||
import PamView.dialog.PamDialog;
|
||||
import PamView.dialog.PamGridBagContraints;
|
||||
import PamView.panel.PamNorthPanel;
|
||||
import PamView.panel.WestAlignedPanel;
|
||||
import metadata.PamguardMetaData;
|
||||
import nilus.Deployment;
|
||||
@ -30,8 +19,7 @@ import tethys.TethysControl;
|
||||
import tethys.TethysState;
|
||||
import tethys.TethysState.StateType;
|
||||
import tethys.deployment.swing.ProjectInformationPanel;
|
||||
import tethys.swing.NewProjectDialog;
|
||||
import tethys.swing.SelectProjectDialog;
|
||||
import tethys.swing.export.DeploymentPeriodPanel;
|
||||
import tethys.swing.export.DescriptionTypePanel;
|
||||
import tethys.swing.export.ResponsiblePartyPanel;
|
||||
|
||||
@ -44,6 +32,8 @@ public class MetaDataDialog extends PamDialog {
|
||||
private DescriptionTypePanel descriptionPanel;
|
||||
|
||||
private ProjectInformationPanel projectInformationPanel;
|
||||
|
||||
private DeploymentPeriodPanel deploymentPeriodPanel;
|
||||
|
||||
private ResponsiblePartyPanel responsiblePanel;
|
||||
|
||||
@ -60,26 +50,26 @@ public class MetaDataDialog extends PamDialog {
|
||||
|
||||
projectInformationPanel = new ProjectInformationPanel(parentFrame, null);
|
||||
descriptionPanel = new DescriptionTypePanel(null, false, false, false);
|
||||
deploymentPeriodPanel = new DeploymentPeriodPanel(parentFrame);
|
||||
descriptionPanel.getMainPanel().setPreferredSize(new Dimension(400,300));
|
||||
|
||||
|
||||
// JPanel projectPanel = new JPanel(new GridBagLayout());
|
||||
|
||||
responsiblePanel = new ResponsiblePartyPanel();
|
||||
JPanel northPanel = new JPanel();
|
||||
WestAlignedPanel wp;
|
||||
northPanel.setLayout(new BoxLayout(northPanel, BoxLayout.Y_AXIS));
|
||||
|
||||
|
||||
northPanel.add(wp = new WestAlignedPanel(projectInformationPanel.getMainPanel()));
|
||||
wp.setBorder(new TitledBorder("General project information"));
|
||||
northPanel.add(wp = new WestAlignedPanel(responsiblePanel.getMainPanel()));
|
||||
wp.setBorder(new TitledBorder("Contact information"));
|
||||
|
||||
// mainPanel.add(BorderLayout.CENTER, descriptionPanel.getMainPanel());
|
||||
// mainPanel.add(BorderLayout.NORTH, northPanel);
|
||||
JPanel dpPanel = new WestAlignedPanel(deploymentPeriodPanel.getMainPanel());
|
||||
dpPanel.setBorder(new TitledBorder("Deployment period"));
|
||||
|
||||
mainPanel.add(tabbedPane, BorderLayout.CENTER);
|
||||
tabbedPane.add(northPanel, "General");
|
||||
tabbedPane.add(descriptionPanel.getMainPanel(), "Description");
|
||||
tabbedPane.add(dpPanel, "Deployment");
|
||||
|
||||
setResizable(true);
|
||||
|
||||
@ -99,8 +89,10 @@ public class MetaDataDialog extends PamDialog {
|
||||
private void setParams(PamguardMetaData pamguardMetaData) {
|
||||
this.pamguardMetaData = pamguardMetaData;
|
||||
Deployment deployment = pamguardMetaData.getDeployment();
|
||||
projectInformationPanel.setParams(deployment);
|
||||
descriptionPanel.setParams(deployment.getDescription());
|
||||
responsiblePanel.setParams(deployment.getMetadataInfo().getContact());
|
||||
deploymentPeriodPanel.setParams(pamguardMetaData);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -108,6 +100,7 @@ public class MetaDataDialog extends PamDialog {
|
||||
Deployment deployment = pamguardMetaData.getDeployment();
|
||||
boolean ok = descriptionPanel.getParams(deployment.getDescription());
|
||||
ok &= responsiblePanel.getParams(deployment.getMetadataInfo().getContact());
|
||||
ok &= deploymentPeriodPanel.getParams(pamguardMetaData);
|
||||
|
||||
if (tethysControl != null) {
|
||||
tethysControl.sendStateUpdate(new TethysState(StateType.NEWPROJECTSELECTION));
|
||||
|
@ -49,10 +49,7 @@ import tethys.deployment.DeploymentHandler;
|
||||
import tethys.detection.DetectionsHandler;
|
||||
import tethys.niluswraps.PDeployment;
|
||||
import tethys.output.DatablockSynchInfo;
|
||||
//import nilus.Deployment;
|
||||
import tethys.output.TethysExportParams;
|
||||
import tethys.output.TethysExporter;
|
||||
import tethys.output.swing.TethysExportDialog;
|
||||
import tethys.species.ITISFunctions;
|
||||
import tethys.species.SpeciesMapManager;
|
||||
import tethys.swing.ProjectDeploymentsDialog;
|
||||
@ -520,6 +517,8 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
|
||||
public void updateState(TethysState tethysState) {
|
||||
switch (tethysState.stateType) {
|
||||
case NEWPROJECTSELECTION:
|
||||
case EXPORTRDATA:
|
||||
case DELETEDATA:
|
||||
countProjectDetections();
|
||||
break;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import PamController.settings.output.xml.PamguardXMLWriter;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
import dbxml.JerseyClient;
|
||||
import dbxml.Queries;
|
||||
import nilus.DataSourceType;
|
||||
import nilus.Deployment;
|
||||
import nilus.Deployment.Instrument;
|
||||
import nilus.DeploymentRecoveryDetails;
|
||||
@ -587,9 +588,9 @@ public class DBXMLQueries {
|
||||
|
||||
ArrayList<String> detectionDocs = new ArrayList<>();
|
||||
|
||||
NodeList returns = doc.getElementsByTagName("Return");
|
||||
NodeList returns = doc.getElementsByTagName("Record");
|
||||
if (returns.getLength() == 0) {
|
||||
returns = doc.getElementsByTagName("Result");
|
||||
returns = doc.getElementsByTagName("Record");
|
||||
}
|
||||
for (int i = 0; i < returns.getLength(); i++) {
|
||||
Node aNode = returns.item(i);
|
||||
@ -925,7 +926,7 @@ public class DBXMLQueries {
|
||||
* @return
|
||||
*/
|
||||
public Detections getDetectionsDocInfo(String detectionsDocName) {
|
||||
String oldqueryBase = "{\"species\":{\"query\":{\"op\":\"lib:abbrev2tsn\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]},\"return\":{\"op\":\"lib:tsn2abbrev\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]}},\"return\":[\"Detections/Id\",\"Detections/Description\",\"Detections/DataSource\",\"Detections/Algorithm\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Id\",\"DetectionsDocName\"],\"optype\":\"binary\"}],\"enclose\":1}";
|
||||
// String oldqueryBase = "{\"species\":{\"query\":{\"op\":\"lib:abbrev2tsn\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]},\"return\":{\"op\":\"lib:tsn2abbrev\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]}},\"return\":[\"Detections/Id\",\"Detections/Description\",\"Detections/DataSource\",\"Detections/Algorithm\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Id\",\"DetectionsDocName\"],\"optype\":\"binary\"}],\"enclose\":1}";
|
||||
// updated May 23
|
||||
String queryBase = "{\"species\":{\"query\":{\"op\":\"lib:completename2tsn\",\"optype\":\"function\",\"operands\":[\"%s\"]},\"return\":{\"op\":\"lib:tsn2completename\",\"optype\":\"function\",\"operands\":[\"%s\"]}},\"return\":[\"Detections/Id\",\"Detections/Description\",\"Detections/DataSource\",\"Detections/Algorithm\",\"Detections/QualityAssurance\",\"Detections/UserId\",\"Detections/MetadataInfo\",\"Detections/Effort\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Id\",\"DetectionsDocName\"],\"optype\":\"binary\"}],\"enclose\":1}";
|
||||
String query = queryBase.replace("DetectionsDocName", detectionsDocName);
|
||||
@ -971,6 +972,16 @@ public class DBXMLQueries {
|
||||
description.setMethod(getElementData(result, "Description.Method"));
|
||||
description.setObjectives(getElementData(result, "Description.Objectives"));
|
||||
|
||||
String deployment = getElementData(result, "DataSource.DeploymentId");
|
||||
if (deployment != null) {
|
||||
DataSourceType dataSource = detections.getDataSource();
|
||||
if (dataSource == null) {
|
||||
dataSource = new DataSourceType();
|
||||
detections.setDataSource(dataSource);
|
||||
}
|
||||
dataSource.setDeploymentId(deployment);
|
||||
}
|
||||
|
||||
// get the effort start an end
|
||||
String effStart = getElementData(result, "Effort.Start");
|
||||
String effEnd = getElementData(result, "Effort.End");
|
||||
|
@ -13,19 +13,22 @@ public class DeploymentExportOpts implements Serializable, Cloneable {
|
||||
|
||||
public boolean separateDeployments;
|
||||
|
||||
/**
|
||||
* Minimum number of seconds between GPS points in a track.
|
||||
*/
|
||||
public double trackPointInterval;
|
||||
|
||||
/**
|
||||
* Max gap before recording periods are separated, potentially into
|
||||
* separate Deployment documents
|
||||
*/
|
||||
public int maxGapSeconds = 60;
|
||||
public int maxRecordingGapSeconds = 60;
|
||||
|
||||
/**
|
||||
* A recording section after joining with max gap parameter is too short
|
||||
* to be worth keeping.
|
||||
*/
|
||||
public int minLengthSeconds = 10;
|
||||
public int minRecordingLengthSeconds = 10;
|
||||
|
||||
@Override
|
||||
protected DeploymentExportOpts clone() {
|
||||
|
@ -65,6 +65,7 @@ import nilus.DeploymentRecoveryDetails;
|
||||
import nilus.DescriptionType;
|
||||
import nilus.GeometryTypeM;
|
||||
import nilus.Helper;
|
||||
import nilus.MetadataInfo;
|
||||
import nilus.UnknownSensor;
|
||||
import pamMaths.PamVector;
|
||||
import pamMaths.STD;
|
||||
@ -103,6 +104,8 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
public TethysControl getTethysControl() {
|
||||
return tethysControl;
|
||||
}
|
||||
|
||||
private EffortFunctions effortFunctions;
|
||||
|
||||
private DeploymentOverview deploymentOverview;
|
||||
|
||||
@ -110,17 +113,22 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
|
||||
private Helper nilusHelper;
|
||||
|
||||
private DeploymentExportOpts exportOptions = new DeploymentExportOpts();
|
||||
private DeploymentExportOpts deploymentExportOptions = new DeploymentExportOpts();
|
||||
|
||||
public DeploymentHandler(TethysControl tethysControl) {
|
||||
super();
|
||||
|
||||
this.tethysControl = tethysControl;
|
||||
|
||||
this.effortFunctions = new EffortFunctions(tethysControl);
|
||||
|
||||
tethysControl.addStateObserver(this);
|
||||
try {
|
||||
nilusHelper = new Helper();
|
||||
} catch (JAXBException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
PamSettingManager.getInstance().registerSettings(new SettingsHandler());
|
||||
}
|
||||
|
||||
@ -156,6 +164,7 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
updateProjectDeployments();
|
||||
break;
|
||||
case EXPORTRDATA:
|
||||
case DELETEDATA:
|
||||
updateProjectDeployments();
|
||||
break;
|
||||
case UPDATESERVER:
|
||||
@ -198,170 +207,175 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
return projectDeployments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an overview of all the deployments.
|
||||
* @return
|
||||
*/
|
||||
public DeploymentOverview createPamguardOverview() {
|
||||
// first find an acquisition module.
|
||||
PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
|
||||
if (!(aModule instanceof AcquisitionControl)) {
|
||||
// will return if it's null. Impossible for it to be the wrong type.
|
||||
// but it's good practice to check anyway before casting.
|
||||
return null;
|
||||
}
|
||||
// cast it to the right type.
|
||||
AcquisitionControl daqControl = (AcquisitionControl) aModule;
|
||||
AcquisitionParameters daqParams = daqControl.getAcquisitionParameters();
|
||||
/**
|
||||
* The daqParams class has most of what we need about the set up in terms of sample rate,
|
||||
* number of channels, instrument type, ADC input range (part of calibration), etc.
|
||||
* It also has a hydrophone list, which maps the input channel numbers to the hydrophon numbers.
|
||||
* Realistically, this list is always 0,1,2,etc or it goes horribly wrong !
|
||||
*/
|
||||
// so write functions here to get information from the daqParams.
|
||||
// System.out.printf("Sample regime: %s input with rate %3.1fHz, %d channels, gain %3.1fdB, ADCp-p %3.1fV\n", daqParams.getDaqSystemType(),
|
||||
// daqParams.getSampleRate(), daqParams.getNChannels(), daqParams.preamplifier.getGain(), daqParams.voltsPeak2Peak);
|
||||
/**
|
||||
* then there is the actual sampling. This is a bit harder to find. I thought it would be in the data map
|
||||
* but the datamap is a simple count of what's in the databasase which is not quite what we want.
|
||||
* we're going to have to query the database to get more detailed informatoin I think.
|
||||
* I'll do that here for now, but we may want to move this when we better organise the code.
|
||||
* It also seems that there are 'bad' dates in the database when it starts new files, which are the date
|
||||
* data were analysed at. So we really need to check the start and stop records only.
|
||||
*/
|
||||
PamDataBlock<DaqStatusDataUnit> daqInfoDataBlock = daqControl.getAcquisitionProcess().getDaqStatusDataBlock();
|
||||
// just load everything. Probably OK for the acqusition, but will bring down
|
||||
daqInfoDataBlock.loadViewerData(0, Long.MAX_VALUE, null);
|
||||
ArrayList<DaqStatusDataUnit> allStatusData = daqInfoDataBlock.getDataCopy();
|
||||
/**
|
||||
* Due to seird file overlaps we need to resort this by id if we can.
|
||||
*
|
||||
*/
|
||||
Collections.sort(allStatusData, new Comparator<DaqStatusDataUnit>() {
|
||||
|
||||
@Override
|
||||
public int compare(DaqStatusDataUnit o1, DaqStatusDataUnit o2) {
|
||||
if (o1.getDatabaseIndex() == 0) {
|
||||
return (int) (o1.getTimeMilliseconds()-o2.getTimeMilliseconds());
|
||||
}
|
||||
return o1.getDatabaseIndex()-o2.getDatabaseIndex();
|
||||
}
|
||||
});
|
||||
|
||||
ArrayList<RecordingPeriod> tempPeriods = null;
|
||||
|
||||
if (allStatusData == null || allStatusData.size() == 0) {
|
||||
System.out.println("Data appear to have no logged recording periods. Try to extract from raw audio ...");
|
||||
tempPeriods = extractTimesFromFiles(daqControl);
|
||||
}
|
||||
else {
|
||||
tempPeriods = extractTimesFromStatus(allStatusData);
|
||||
}
|
||||
if (tempPeriods == null || tempPeriods.size() == 0) {
|
||||
System.out.println("Data appear to have no logged recording periods available either from the database or the raw recordings.");
|
||||
tempPeriods = extractTimesFromOutputMaps();
|
||||
}
|
||||
if (tempPeriods == null || tempPeriods.size() == 0) {
|
||||
System.out.println("Data appear to have no logged recording periods available either from the database or the raw recordings.");
|
||||
return null;
|
||||
}
|
||||
|
||||
int nPeriods = tempPeriods.size();
|
||||
// int i = 0;
|
||||
// for (RecordingPeriod aP : tempPeriods) {
|
||||
// System.out.printf("Pre merge %d : %s to %s\n", i++, PamCalendar.formatDBDateTime(aP.getRecordStart()),
|
||||
// PamCalendar.formatDBDateTime(aP.getRecordStop()));
|
||||
// /**
|
||||
// * Get an overview of all the deployments.
|
||||
// * @return
|
||||
// */
|
||||
// public DeploymentOverview createPamguardOverview() {
|
||||
// // first find an acquisition module.
|
||||
// PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
|
||||
// if (!(aModule instanceof AcquisitionControl)) {
|
||||
// // will return if it's null. Impossible for it to be the wrong type.
|
||||
// // but it's good practice to check anyway before casting.
|
||||
// return null;
|
||||
// }
|
||||
// now go through those and merge into longer periods where there is no gap between files.
|
||||
ListIterator<RecordingPeriod> iterator = tempPeriods.listIterator();
|
||||
RecordingPeriod prevPeriod = null;
|
||||
while (iterator.hasNext()) {
|
||||
RecordingPeriod nextPeriod = iterator.next();
|
||||
long nextDur = nextPeriod.getRecordStop()-nextPeriod.getRecordStart();
|
||||
if (nextDur == 0) {
|
||||
continue;
|
||||
}
|
||||
if (prevPeriod != null) {
|
||||
long gap = nextPeriod.getRecordStart() - prevPeriod.getRecordStop();
|
||||
long prevDur = prevPeriod.getRecordStop()-prevPeriod.getRecordStart();
|
||||
if (gap < exportOptions.maxGapSeconds*1000) {
|
||||
// ignoring up to 3s gap or a sample error < 2%.Dunno if this is sensible or not.
|
||||
prevPeriod.setRecordStop(nextPeriod.getRecordStop());
|
||||
iterator.remove();
|
||||
nextPeriod = prevPeriod;
|
||||
}
|
||||
}
|
||||
prevPeriod = nextPeriod;
|
||||
}
|
||||
// now remove ones which are too short even after merging.
|
||||
iterator = tempPeriods.listIterator();
|
||||
while (iterator.hasNext()) {
|
||||
RecordingPeriod nextPeriod = iterator.next();
|
||||
long duration = nextPeriod.getDuration();
|
||||
if (duration < exportOptions.minLengthSeconds*1000L) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
// i = 0;
|
||||
// for (RecordingPeriod aP : tempPeriods) {
|
||||
// System.out.printf("Post merge %d : %s to %s\n", i++, PamCalendar.formatDBDateTime(aP.getRecordStart()),
|
||||
// PamCalendar.formatDBDateTime(aP.getRecordStop()));
|
||||
// // cast it to the right type.
|
||||
// AcquisitionControl daqControl = (AcquisitionControl) aModule;
|
||||
// AcquisitionParameters daqParams = daqControl.getAcquisitionParameters();
|
||||
// /**
|
||||
// * The daqParams class has most of what we need about the set up in terms of sample rate,
|
||||
// * number of channels, instrument type, ADC input range (part of calibration), etc.
|
||||
// * It also has a hydrophone list, which maps the input channel numbers to the hydrophon numbers.
|
||||
// * Realistically, this list is always 0,1,2,etc or it goes horribly wrong !
|
||||
// */
|
||||
// // so write functions here to get information from the daqParams.
|
||||
//// System.out.printf("Sample regime: %s input with rate %3.1fHz, %d channels, gain %3.1fdB, ADCp-p %3.1fV\n", daqParams.getDaqSystemType(),
|
||||
//// daqParams.getSampleRate(), daqParams.getNChannels(), daqParams.preamplifier.getGain(), daqParams.voltsPeak2Peak);
|
||||
// /**
|
||||
// * then there is the actual sampling. This is a bit harder to find. I thought it would be in the data map
|
||||
// * but the datamap is a simple count of what's in the databasase which is not quite what we want.
|
||||
// * we're going to have to query the database to get more detailed informatoin I think.
|
||||
// * I'll do that here for now, but we may want to move this when we better organise the code.
|
||||
// * It also seems that there are 'bad' dates in the database when it starts new files, which are the date
|
||||
// * data were analysed at. So we really need to check the start and stop records only.
|
||||
// */
|
||||
// PamDataBlock<DaqStatusDataUnit> daqInfoDataBlock = daqControl.getAcquisitionProcess().getDaqStatusDataBlock();
|
||||
// // just load everything. Probably OK for the acqusition, but will bring down
|
||||
// daqInfoDataBlock.loadViewerData(0, Long.MAX_VALUE, null);
|
||||
// ArrayList<DaqStatusDataUnit> allStatusData = daqInfoDataBlock.getDataCopy();
|
||||
// /**
|
||||
// * Due to seird file overlaps we need to resort this by id if we can.
|
||||
// *
|
||||
// */
|
||||
// Collections.sort(allStatusData, new Comparator<DaqStatusDataUnit>() {
|
||||
//
|
||||
// @Override
|
||||
// public int compare(DaqStatusDataUnit o1, DaqStatusDataUnit o2) {
|
||||
// if (o1.getDatabaseIndex() == 0) {
|
||||
// return (int) (o1.getTimeMilliseconds()-o2.getTimeMilliseconds());
|
||||
// }
|
||||
// return o1.getDatabaseIndex()-o2.getDatabaseIndex();
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// ArrayList<RecordingPeriod> tempPeriods = null;
|
||||
//
|
||||
// if (allStatusData == null || allStatusData.size() == 0) {
|
||||
// System.out.println("Data appear to have no logged recording periods. Try to extract from raw audio ...");
|
||||
// tempPeriods = extractTimesFromFiles(daqControl);
|
||||
// }
|
||||
// System.out.printf("Data have %d distinct files, but only %d distinct recording periods\n", nPeriods, tempPeriods.size());
|
||||
DutyCycleInfo dutyCycleinfo = assessDutyCycle(tempPeriods);
|
||||
// if it's duty cycles, then we only want a single entry.
|
||||
ArrayList<RecordingPeriod> deploymentPeriods;
|
||||
if (dutyCycleinfo.isDutyCycled == false) {
|
||||
deploymentPeriods = tempPeriods;
|
||||
}
|
||||
else {
|
||||
deploymentPeriods = new ArrayList<>();
|
||||
deploymentPeriods.add(new RecordingPeriod(tempPeriods.get(0).getRecordStart(), tempPeriods.get(tempPeriods.size()-1).getRecordStop()));
|
||||
}
|
||||
/*
|
||||
* do another sort of the deploymentPeriods. The start stops were in the order they went into the
|
||||
* database in the hope that pairs were the right way round. Now check all data are/
|
||||
*/
|
||||
Collections.sort(deploymentPeriods, new Comparator<RecordingPeriod>() {
|
||||
@Override
|
||||
public int compare(RecordingPeriod o1, RecordingPeriod o2) {
|
||||
return (int) (o1.getRecordStart()-o2.getRecordStart());
|
||||
}
|
||||
});
|
||||
|
||||
DeploymentOverview deploymentOverview = new DeploymentOverview(dutyCycleinfo, deploymentPeriods);
|
||||
matchPamguard2Tethys(deploymentOverview, projectDeployments);
|
||||
this.deploymentOverview = deploymentOverview;
|
||||
return deploymentOverview;
|
||||
// find the number of times it started and stopped ....
|
||||
// System.out.printf("Input map of sound data indicates data from %s to %s with %d starts and %d stops over %d files\n",
|
||||
// PamCalendar.formatDateTime(dataStart), PamCalendar.formatDateTime(dataEnd), nStart, nStop, nFile+1);
|
||||
// now work out where there are genuine gaps and make up a revised list of recording periods.
|
||||
|
||||
|
||||
}
|
||||
// else {
|
||||
// tempPeriods = extractTimesFromStatus(allStatusData);
|
||||
// }
|
||||
// if (tempPeriods == null || tempPeriods.size() == 0) {
|
||||
// System.out.println("Data appear to have no logged recording periods available either from the database or the raw recordings.");
|
||||
// tempPeriods = extractTimesFromOutputMaps();
|
||||
// }
|
||||
// if (tempPeriods == null || tempPeriods.size() == 0) {
|
||||
// System.out.println("Data appear to have no logged recording periods available either from the database or the raw recordings.");
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// int nPeriods = tempPeriods.size();
|
||||
//// int i = 0;
|
||||
//// for (RecordingPeriod aP : tempPeriods) {
|
||||
//// System.out.printf("Pre merge %d : %s to %s\n", i++, PamCalendar.formatDBDateTime(aP.getRecordStart()),
|
||||
//// PamCalendar.formatDBDateTime(aP.getRecordStop()));
|
||||
//// }
|
||||
// // now go through those and merge into longer periods where there is no gap between files.
|
||||
// ListIterator<RecordingPeriod> iterator = tempPeriods.listIterator();
|
||||
// RecordingPeriod prevPeriod = null;
|
||||
// while (iterator.hasNext()) {
|
||||
// RecordingPeriod nextPeriod = iterator.next();
|
||||
// long nextDur = nextPeriod.getRecordStop()-nextPeriod.getRecordStart();
|
||||
// if (nextDur == 0) {
|
||||
// continue;
|
||||
// }
|
||||
// if (prevPeriod != null) {
|
||||
// long gap = nextPeriod.getRecordStart() - prevPeriod.getRecordStop();
|
||||
// long prevDur = prevPeriod.getRecordStop()-prevPeriod.getRecordStart();
|
||||
// if (gap < exportOptions.maxGapSeconds*1000) {
|
||||
// // ignoring up to 3s gap or a sample error < 2%.Dunno if this is sensible or not.
|
||||
// prevPeriod.setRecordStop(nextPeriod.getRecordStop());
|
||||
// iterator.remove();
|
||||
// nextPeriod = prevPeriod;
|
||||
// }
|
||||
// }
|
||||
// prevPeriod = nextPeriod;
|
||||
// }
|
||||
// // now remove ones which are too short even after merging.
|
||||
// iterator = tempPeriods.listIterator();
|
||||
// while (iterator.hasNext()) {
|
||||
// RecordingPeriod nextPeriod = iterator.next();
|
||||
// long duration = nextPeriod.getDuration();
|
||||
// if (duration < exportOptions.minLengthSeconds*1000L) {
|
||||
// iterator.remove();
|
||||
// }
|
||||
// }
|
||||
//// i = 0;
|
||||
//// for (RecordingPeriod aP : tempPeriods) {
|
||||
//// System.out.printf("Post merge %d : %s to %s\n", i++, PamCalendar.formatDBDateTime(aP.getRecordStart()),
|
||||
//// PamCalendar.formatDBDateTime(aP.getRecordStop()));
|
||||
//// }
|
||||
//// System.out.printf("Data have %d distinct files, but only %d distinct recording periods\n", nPeriods, tempPeriods.size());
|
||||
// DutyCycleInfo dutyCycleinfo = assessDutyCycle(tempPeriods);
|
||||
// // if it's duty cycles, then we only want a single entry.
|
||||
// ArrayList<RecordingPeriod> deploymentPeriods;
|
||||
// if (dutyCycleinfo.isDutyCycled == false) {
|
||||
// deploymentPeriods = tempPeriods;
|
||||
// }
|
||||
// else {
|
||||
// deploymentPeriods = new ArrayList<>();
|
||||
// deploymentPeriods.add(new RecordingPeriod(tempPeriods.get(0).getRecordStart(), tempPeriods.get(tempPeriods.size()-1).getRecordStop()));
|
||||
// }
|
||||
// /*
|
||||
// * do another sort of the deploymentPeriods. The start stops were in the order they went into the
|
||||
// * database in the hope that pairs were the right way round. Now check all data are/
|
||||
// */
|
||||
// Collections.sort(deploymentPeriods, new Comparator<RecordingPeriod>() {
|
||||
// @Override
|
||||
// public int compare(RecordingPeriod o1, RecordingPeriod o2) {
|
||||
// return (int) (o1.getRecordStart()-o2.getRecordStart());
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// DeploymentOverview deploymentOverview = new DeploymentOverview(dutyCycleinfo, deploymentPeriods);
|
||||
// matchPamguard2Tethys(deploymentOverview, projectDeployments);
|
||||
// this.deploymentOverview = deploymentOverview;
|
||||
// return deploymentOverview;
|
||||
// // find the number of times it started and stopped ....
|
||||
//// System.out.printf("Input map of sound data indicates data from %s to %s with %d starts and %d stops over %d files\n",
|
||||
//// PamCalendar.formatDateTime(dataStart), PamCalendar.formatDateTime(dataEnd), nStart, nStop, nFile+1);
|
||||
// // now work out where there are genuine gaps and make up a revised list of recording periods.
|
||||
//
|
||||
//
|
||||
// }
|
||||
|
||||
public void showOptions(Window parent) {
|
||||
if (parent == null) {
|
||||
parent = tethysControl.getGuiFrame();
|
||||
}
|
||||
DeploymentExportOpts newOpts = RecordingGapDialog.showDiloag(parent, exportOptions);
|
||||
DeploymentExportOpts newOpts = RecordingGapDialog.showDiloag(parent, deploymentExportOptions);
|
||||
if (newOpts != null) {
|
||||
exportOptions = newOpts;
|
||||
deploymentOverview = createPamguardOverview();
|
||||
updateProjectDeployments();
|
||||
deploymentExportOptions = newOpts;
|
||||
createPamguardOverview();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void createPamguardOverview() {
|
||||
deploymentOverview = effortFunctions.makeRecordingOverview();
|
||||
updateProjectDeployments();
|
||||
matchPamguard2Tethys(deploymentOverview, projectDeployments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export button pressed on GUI. Run wizard....
|
||||
*/
|
||||
public void exportDeployments() {
|
||||
Deployment deployment = MetaDataContol.getMetaDataControl().getMetaData().getDeployment();
|
||||
DeploymentExportOpts exportOptions = DeploymentWizard.showWizard(getTethysControl().getGuiFrame(), tethysControl, deployment, this.exportOptions);
|
||||
DeploymentExportOpts exportOptions = DeploymentWizard.showWizard(getTethysControl().getGuiFrame(), tethysControl, deployment, this.deploymentExportOptions);
|
||||
if (exportOptions != null) {
|
||||
this.exportOptions = exportOptions;
|
||||
this.deploymentExportOptions = exportOptions;
|
||||
deploymentOverview = getDeploymentOverview();
|
||||
ArrayList<RecordingPeriod> allPeriods = deploymentOverview.getRecordingPeriods();
|
||||
exportDeployments(allPeriods);
|
||||
@ -373,14 +387,14 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
* @param selectedDeployments
|
||||
*/
|
||||
public void exportDeployments(ArrayList<RecordingPeriod> selectedDeployments) {
|
||||
if (exportOptions.separateDeployments) {
|
||||
if (deploymentExportOptions.separateDeployments) {
|
||||
exportSeparateDeployments(selectedDeployments);
|
||||
}
|
||||
else {
|
||||
exportOneDeploymnet(selectedDeployments);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Make one big deployment document with all the recording periods in it.
|
||||
*/
|
||||
@ -390,7 +404,9 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
int freeId = getTethysControl().getDeploymentHandler().getFirstFreeDeploymentId();
|
||||
RecordingPeriod onePeriod = new RecordingPeriod(selectedDeployments.get(0).getRecordStart(),
|
||||
selectedDeployments.get(selectedDeployments.size()-1).getRecordStop());
|
||||
Deployment deployment = createDeploymentDocument(freeId, onePeriod);
|
||||
TethysExportParams exportParams = tethysControl.getTethysExportParams();
|
||||
String id = String.format("%s_%s", exportParams.getDatasetName(), "all");
|
||||
Deployment deployment = createDeploymentDocument(freeId, onePeriod, id);
|
||||
// fill in a few things from here
|
||||
Deployment globalMeta = getTethysControl().getGlobalDeplopymentData();
|
||||
deployment.setCruise(globalMeta.getCruise());
|
||||
@ -428,16 +444,18 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
int freeId = getTethysControl().getDeploymentHandler().getFirstFreeDeploymentId();
|
||||
// fill in a few things from here
|
||||
Deployment globalMeta = getTethysControl().getGlobalDeplopymentData();
|
||||
TethysExportParams exportParams = tethysControl.getTethysExportParams();
|
||||
for (int i = 0; i < selectedDeployments.size(); i++) {
|
||||
RecordingPeriod recordPeriod = selectedDeployments.get(i);
|
||||
PDeployment exDeploymnet = recordPeriod.getMatchedTethysDeployment();
|
||||
Deployment deployment = null;
|
||||
String id = String.format("%s_%d", exportParams.getDatasetName(), i);
|
||||
if (exDeploymnet != null) {
|
||||
deployment = createDeploymentDocument(freeId, recordPeriod);
|
||||
deployment = createDeploymentDocument(freeId, recordPeriod, id);
|
||||
deployment.setId(exDeploymnet.deployment.getId());
|
||||
}
|
||||
if (deployment == null) {
|
||||
deployment = createDeploymentDocument(freeId++, recordPeriod);
|
||||
deployment = createDeploymentDocument(freeId++, recordPeriod, id);
|
||||
}
|
||||
deployment.setCruise(globalMeta.getCruise());
|
||||
deployment.setSite(globalMeta.getSite());
|
||||
@ -458,42 +476,7 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER, Collection.Deployments));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data times from any other datamap, since this will generally match the acquisition anyway
|
||||
* @return
|
||||
*/
|
||||
private ArrayList<RecordingPeriod> extractTimesFromOutputMaps() {
|
||||
OfflineDataMap bestMap = null;
|
||||
PamDataBlock bestBlock = null;
|
||||
long firstStart = Long.MAX_VALUE;
|
||||
long lastEnd = Long.MIN_VALUE;
|
||||
ArrayList<PamDataBlock> dataBlocks = PamController.getInstance().getDetectorDataBlocks();
|
||||
for (PamDataBlock aBlock : dataBlocks) {
|
||||
if (aBlock instanceof PamRawDataBlock) {
|
||||
continue; // don't want acquisition !
|
||||
}
|
||||
OfflineDataMap dataMap = aBlock.getPrimaryDataMap();
|
||||
if (dataMap == null) {
|
||||
continue;
|
||||
}
|
||||
if (dataMap.getFirstDataTime() < firstStart && dataMap.getLastDataTime() > lastEnd) {
|
||||
bestMap = dataMap;
|
||||
bestBlock = aBlock;
|
||||
firstStart = dataMap.getFirstDataTime();
|
||||
lastEnd = dataMap.getLastDataTime();
|
||||
}
|
||||
}
|
||||
if (bestMap == null) {
|
||||
return null;
|
||||
}
|
||||
// get the times out of it.
|
||||
ArrayList<RecordingPeriod> recPeriods = new ArrayList<>();
|
||||
List<OfflineDataMapPoint> mapPoints = bestMap.getMapPoints();
|
||||
for (OfflineDataMapPoint mapPoint : mapPoints) {
|
||||
recPeriods.add(new RecordingPeriod(mapPoint.getStartTime(), mapPoint.getEndTime()));
|
||||
}
|
||||
return recPeriods;
|
||||
}
|
||||
|
||||
|
||||
public DeploymentOverview getDeploymentOverview() {
|
||||
return deploymentOverview;
|
||||
@ -556,108 +539,12 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
return overlap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out whether or not the data are evenly duty cycled by testing the
|
||||
* distributions of on and off times.
|
||||
* @param tempPeriods
|
||||
* @return
|
||||
*/
|
||||
private DutyCycleInfo assessDutyCycle(ArrayList<RecordingPeriod> tempPeriods) {
|
||||
int n = tempPeriods.size();
|
||||
if (n < 2) {
|
||||
return new DutyCycleInfo(false, 0,0,n);
|
||||
}
|
||||
double[] ons = new double[n-1]; // ignore the last one since it may be artificially shortened which is OK
|
||||
double[] gaps = new double[n-1];
|
||||
for (int i = 0; i < n-1; i++) {
|
||||
ons[i] = tempPeriods.get(i).getDuration()/1000.;
|
||||
gaps[i] = (tempPeriods.get(i+1).getRecordStart()-tempPeriods.get(i).getRecordStop())/1000.;
|
||||
}
|
||||
/* now look at how consistent those values are
|
||||
* But some data gets messed by small gaps, so want to
|
||||
* remove outliers and concentrate on say 80% of the data.
|
||||
*/
|
||||
ons = getDistributionCentre(ons, 80);
|
||||
gaps = getDistributionCentre(gaps, 80);
|
||||
Arrays.sort(gaps);
|
||||
|
||||
|
||||
STD std = new STD();
|
||||
double onsMean = std.getMean(ons);
|
||||
double onsSTD = std.getSTD(ons);
|
||||
double gapsMean = std.getMean(gaps);
|
||||
double gapsSTD = std.getSTD(gaps);
|
||||
boolean dutyCycle = onsSTD/onsMean < .05 && gapsSTD/gapsMean < 0.05;
|
||||
DutyCycleInfo cycleInfo = new DutyCycleInfo(dutyCycle, onsMean, gapsMean, tempPeriods.size());
|
||||
return cycleInfo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the central part of a distribution without any outliers so
|
||||
* that we can get a better assessment of duty cycle.
|
||||
* @param data unsorted distribution data.
|
||||
* @param percent percentage to include (half this removed from top and bottom)
|
||||
* @return
|
||||
*/
|
||||
private double[] getDistributionCentre(double[] data, double percent) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
Arrays.sort(data);
|
||||
int nRem = (int) Math.round(data.length * (100-percent)/200);
|
||||
int newLen = data.length-nRem*2;
|
||||
double[] subdata = Arrays.copyOfRange(data, nRem, data.length-2*nRem);
|
||||
if (subdata.length < 2) {
|
||||
return data;
|
||||
}
|
||||
return subdata;
|
||||
}
|
||||
|
||||
private ArrayList<RecordingPeriod> extractTimesFromStatus(ArrayList<DaqStatusDataUnit> allStatusData) {
|
||||
ArrayList<RecordingPeriod> tempPeriods = new ArrayList<>();
|
||||
long dataStart = Long.MAX_VALUE;
|
||||
long dataEnd = Long.MIN_VALUE;
|
||||
Long lastStart = null;
|
||||
int nStart = 0;
|
||||
int nStop = 0;
|
||||
int nFile = 0;
|
||||
for (DaqStatusDataUnit daqStatus : allStatusData) {
|
||||
switch (daqStatus.getStatus()) {
|
||||
case "Start":
|
||||
nStart++;
|
||||
dataStart = Math.min(dataStart, daqStatus.getTimeMilliseconds());
|
||||
lastStart = daqStatus.getTimeMilliseconds();
|
||||
// System.out.println("Start at " + PamCalendar.formatDBDateTime(lastStart));
|
||||
break;
|
||||
case "Stop":
|
||||
nStop++;
|
||||
dataEnd = Math.max(dataEnd, daqStatus.getEndTimeInMilliseconds());
|
||||
long lastEnd = daqStatus.getEndTimeInMilliseconds();
|
||||
if (lastStart != null) {
|
||||
// System.out.printf("Adding period %s to %s\n", PamCalendar.formatDBDateTime(lastStart),
|
||||
// PamCalendar.formatDBDateTime(lastEnd));
|
||||
tempPeriods.add(new RecordingPeriod(lastStart, lastEnd));
|
||||
}
|
||||
else {
|
||||
// System.out.println("Skipping stop at " + PamCalendar.formatDBDateTime(lastEnd));
|
||||
}
|
||||
lastStart = null;
|
||||
break;
|
||||
case "NextFile":
|
||||
nFile++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tempPeriods;
|
||||
}
|
||||
|
||||
private ArrayList<RecordingPeriod> extractTimesFromFiles(AcquisitionControl daqControl) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of Tethys Deployment docs that match the current PAMGuard data.
|
||||
* Get a list of Tethys Deployment docs that match the current PAMGuard data. Watch for repeats
|
||||
* if a single deployment doc covers many perdiods.
|
||||
* @return
|
||||
*/
|
||||
public ArrayList<PDeployment> getMatchedDeployments() {
|
||||
@ -666,8 +553,11 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
return matched;
|
||||
}
|
||||
for (RecordingPeriod period : deploymentOverview.getRecordingPeriods()) {
|
||||
if (period.getMatchedTethysDeployment() != null) {
|
||||
matched.add(period.getMatchedTethysDeployment());
|
||||
PDeployment deployment = period.getMatchedTethysDeployment();
|
||||
if (deployment != null) {
|
||||
if (matched.contains(deployment) == false) {
|
||||
matched.add(period.getMatchedTethysDeployment());
|
||||
}
|
||||
}
|
||||
}
|
||||
return matched;
|
||||
@ -808,7 +698,7 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
return firstFree;
|
||||
}
|
||||
|
||||
public Deployment createDeploymentDocument(int i, RecordingPeriod recordingPeriod) {
|
||||
public Deployment createDeploymentDocument(int i, RecordingPeriod recordingPeriod, String deploymentId) {
|
||||
Deployment deployment = new Deployment();
|
||||
try {
|
||||
nilus.Helper.createRequiredElements(deployment);
|
||||
@ -822,10 +712,11 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
PamguardMetaData pamguardMetaData = MetaDataContol.getMetaDataControl().getMetaData();
|
||||
Deployment templateDeployment = pamguardMetaData.getDeployment();
|
||||
|
||||
// Deployment globalDeplData = tethysControl.getGlobalDeplopymentData();
|
||||
TethysExportParams exportParams = tethysControl.getTethysExportParams();
|
||||
String id = String.format("%s_%d", exportParams.getDatasetName(), i);
|
||||
deployment.setId(id);
|
||||
deployment.setId(deploymentId);
|
||||
deployment.setDeploymentId(i);
|
||||
|
||||
DeploymentRecoveryDetails deploymentDetails = deployment.getDeploymentDetails();
|
||||
@ -836,11 +727,21 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
if (recoveryDetails == null) {
|
||||
recoveryDetails = new DeploymentRecoveryDetails();
|
||||
}
|
||||
deploymentDetails.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStart()));
|
||||
recoveryDetails.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStop()));
|
||||
|
||||
deploymentDetails.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStart()));
|
||||
recoveryDetails.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStop()));
|
||||
// handle situation where deployment and recovery times are not the same as the audio times.
|
||||
if (pamguardMetaData.useAudioForDeploymentTimes == false) {
|
||||
if (templateDeployment.getDeploymentDetails().getAudioTimeStamp() != null) {
|
||||
deploymentDetails.setTimeStamp(templateDeployment.getDeploymentDetails().getAudioTimeStamp());
|
||||
}
|
||||
if (templateDeployment.getRecoveryDetails().getAudioTimeStamp() != null) {
|
||||
recoveryDetails.setTimeStamp(templateDeployment.getRecoveryDetails().getAudioTimeStamp());
|
||||
}
|
||||
}
|
||||
|
||||
deploymentDetails.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStart()));
|
||||
recoveryDetails.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStop()));
|
||||
|
||||
deployment.setDeploymentDetails(deploymentDetails);
|
||||
deployment.setRecoveryDetails(recoveryDetails);
|
||||
@ -849,16 +750,25 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
|
||||
TethysLocationFuncs.getTrackAndPositionData(deployment);
|
||||
|
||||
getTrackDetails(deployment);
|
||||
getTrackDetails(deployment);
|
||||
|
||||
DescriptionType description = deployment.getDescription();
|
||||
if (description == null ) {
|
||||
description = new DescriptionType();
|
||||
deployment.setDescription(description);
|
||||
description.setAbstract("No abstract");
|
||||
description.setMethod("no methods");
|
||||
description.setObjectives("No objectives");
|
||||
}
|
||||
/**
|
||||
* Get some of the meta data from the centralised source.
|
||||
*/
|
||||
MetadataInfo metaData = templateDeployment.getMetadataInfo();
|
||||
metaData.setDate(TethysTimeFuncs.xmlGregCalFromMillis(System.currentTimeMillis()));
|
||||
metaData.setUpdateFrequency("as-needed");
|
||||
deployment.setMetadataInfo(metaData);
|
||||
|
||||
deployment.setDescription(templateDeployment.getDescription());
|
||||
// DescriptionType description = deployment.getDescription();
|
||||
// if (description == null ) {
|
||||
// description = new DescriptionType();
|
||||
// deployment.setDescription(description);
|
||||
// description.setAbstract("No abstract");
|
||||
// description.setMethod("no methods");
|
||||
// description.setObjectives("No objectives");
|
||||
// }
|
||||
// description.set
|
||||
|
||||
addSamplingDetails(deployment, recordingPeriod);
|
||||
@ -900,7 +810,7 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
*/
|
||||
long trackStart = TethysTimeFuncs.millisFromGregorianXML(deployment.getDeploymentDetails().getTimeStamp());
|
||||
long trackEnd = TethysTimeFuncs.millisFromGregorianXML(deployment.getRecoveryDetails().getTimeStamp());
|
||||
long dataWin =(long) (Math.max(1./trackInfo.getGPSDataRate(), exportOptions.trackPointInterval));
|
||||
long dataWin =(long) (Math.max(1./trackInfo.getGPSDataRate(), deploymentExportOptions.trackPointInterval));
|
||||
|
||||
// get the tracks object.
|
||||
Tracks tracks = deployment.getData().getTracks();
|
||||
@ -919,7 +829,7 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
ListIterator<GpsDataUnit> it = gpsDataBlock.getListIterator(0);
|
||||
while (it.hasNext()) {
|
||||
GpsDataUnit gpsDataUnit = it.next();
|
||||
if (gpsDataUnit.getTimeMilliseconds()-lastPointTime < exportOptions.trackPointInterval*1000) {
|
||||
if (gpsDataUnit.getTimeMilliseconds()-lastPointTime < deploymentExportOptions.trackPointInterval*1000) {
|
||||
continue;
|
||||
}
|
||||
GpsData gpsData = gpsDataUnit.getGpsData();
|
||||
@ -1248,8 +1158,8 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
List<ChannelInfo> channelInfos = samplingDetails.getChannel();
|
||||
for (int i = 0; i < nChan; i++) {
|
||||
ChannelInfo channelInfo = new ChannelInfo();
|
||||
channelInfo.setStart(deployment.getDeploymentDetails().getAudioTimeStamp());
|
||||
channelInfo.setEnd(deployment.getRecoveryDetails().getAudioTimeStamp());
|
||||
channelInfo.setStart(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStart()));
|
||||
channelInfo.setEnd(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStop()));
|
||||
|
||||
BigIntegerConverter biCon = new BigIntegerConverter();
|
||||
BigInteger chanNum = BigInteger.valueOf(i);
|
||||
@ -1273,7 +1183,7 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
Sampling sampling = new Sampling();
|
||||
List<Regimen> regimens = sampling.getRegimen();
|
||||
Sampling.Regimen regimen = new Sampling.Regimen();
|
||||
regimen.setTimeStamp(deployment.getDeploymentDetails().getAudioTimeStamp());
|
||||
regimen.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStart()));
|
||||
regimen.setSampleRateKHz(fs/1000.);
|
||||
if (system != null) {
|
||||
regimen.setSampleBits(system.getSampleBits());
|
||||
@ -1288,10 +1198,15 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
nilus.ChannelInfo.DutyCycle.Regimen dsr = new nilus.ChannelInfo.DutyCycle.Regimen();
|
||||
reg.add(dsr);
|
||||
RecordingDurationS ssss = new RecordingDurationS();
|
||||
ssss.setValue(dutyCycleInf.meanOnTimeS);
|
||||
// round to a second ... or .1s if short duty cycle.
|
||||
int dp = 1;
|
||||
if (dutyCycleInf.meanOnTimeS > 59) {
|
||||
dp = 0;
|
||||
}
|
||||
ssss.setValue(AutoTethysProvider.roundDecimalPlaces(dutyCycleInf.meanOnTimeS,dp));
|
||||
dsr.setRecordingDurationS(ssss);
|
||||
RecordingIntervalS ris = new RecordingIntervalS();
|
||||
ris.setValue(dutyCycleInf.meanOnTimeS + dutyCycleInf.meanGapS);
|
||||
ris.setValue(AutoTethysProvider.roundDecimalPlaces(dutyCycleInf.meanOnTimeS + dutyCycleInf.meanGapS,dp));
|
||||
dsr.setRecordingIntervalS(ris);
|
||||
dsr.setTimeStamp(deployment.getDeploymentDetails().getAudioTimeStamp());
|
||||
channelInfo.setDutyCycle(dutyCycle);
|
||||
@ -1329,7 +1244,7 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
|
||||
@Override
|
||||
public Serializable getSettingsReference() {
|
||||
return exportOptions;
|
||||
return deploymentExportOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1339,10 +1254,17 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
|
||||
|
||||
@Override
|
||||
public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
|
||||
exportOptions = (DeploymentExportOpts) pamControlledUnitSettings.getSettings();
|
||||
deploymentExportOptions = (DeploymentExportOpts) pamControlledUnitSettings.getSettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the deploymentExportOptions
|
||||
*/
|
||||
public DeploymentExportOpts getDeploymentExportOptions() {
|
||||
return deploymentExportOptions;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,16 @@
|
||||
package tethys.deployment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import Acquisition.AcquisitionControl;
|
||||
import Acquisition.AcquisitionParameters;
|
||||
import Acquisition.DaqStatusDataUnit;
|
||||
import PamController.PamControlledUnit;
|
||||
import PamController.PamController;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
|
||||
/**
|
||||
* Class to give a general overview of all the effort in PAMGuard which will form the
|
||||
@ -25,7 +35,8 @@ public class DeploymentOverview {
|
||||
this.dutyCycleInfo = dutyCycleInfo;
|
||||
this.recordingPeriods = tempPeriods;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void addRecordingPeriod(long start, long stop) {
|
||||
addRecordingPeriod(new RecordingPeriod(start, stop));
|
||||
}
|
||||
|
407
src/tethys/deployment/EffortFunctions.java
Normal file
407
src/tethys/deployment/EffortFunctions.java
Normal file
@ -0,0 +1,407 @@
|
||||
package tethys.deployment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import Acquisition.AcquisitionControl;
|
||||
import Acquisition.AcquisitionParameters;
|
||||
import Acquisition.DaqStatusDataUnit;
|
||||
import PamController.PamControlledUnit;
|
||||
import PamController.PamController;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
import PamguardMVC.PamRawDataBlock;
|
||||
import SoundRecorder.RecordingInfo;
|
||||
import binaryFileStorage.BinaryStore;
|
||||
import dataMap.OfflineDataMap;
|
||||
import dataMap.OfflineDataMapPoint;
|
||||
import pamMaths.STD;
|
||||
import tethys.TethysControl;
|
||||
import tethys.output.TethysExportParams;
|
||||
import tethys.pamdata.TethysDataProvider;
|
||||
|
||||
/**
|
||||
* functions for working out total effort and periods of recording from a variety of sources, which may be
|
||||
* the recordings database, binary files, etc.
|
||||
* @author dg50
|
||||
*
|
||||
*/
|
||||
public class EffortFunctions {
|
||||
|
||||
private TethysControl tethysControl;
|
||||
|
||||
|
||||
/**
|
||||
* @param tethysControl
|
||||
*/
|
||||
public EffortFunctions(TethysControl tethysControl) {
|
||||
this.tethysControl = tethysControl;
|
||||
}
|
||||
|
||||
private DeploymentOverview createOverview(RecordingList tempPeriods) {
|
||||
|
||||
DutyCycleInfo dutyCycleinfo = assessDutyCycle(tempPeriods);
|
||||
|
||||
// if it's duty cycles, then we only want a single entry.
|
||||
RecordingList deploymentPeriods;
|
||||
if (dutyCycleinfo.isDutyCycled == false) {
|
||||
deploymentPeriods = tempPeriods;
|
||||
}
|
||||
else {
|
||||
deploymentPeriods = new RecordingList();
|
||||
deploymentPeriods.add(new RecordingPeriod(tempPeriods.get(0).getRecordStart(), tempPeriods.get(tempPeriods.size()-1).getRecordStop()));
|
||||
}
|
||||
/*
|
||||
* do another sort of the deploymentPeriods. The start stops were in the order they went into the
|
||||
* database in the hope that pairs were the right way round. Now check all data are/
|
||||
*/
|
||||
Collections.sort(deploymentPeriods, new Comparator<RecordingPeriod>() {
|
||||
@Override
|
||||
public int compare(RecordingPeriod o1, RecordingPeriod o2) {
|
||||
return (int) (o1.getRecordStart()-o2.getRecordStart());
|
||||
}
|
||||
});
|
||||
|
||||
DeploymentOverview deploymentOverview = new DeploymentOverview(dutyCycleinfo, deploymentPeriods);
|
||||
return deploymentOverview;
|
||||
}
|
||||
|
||||
|
||||
public DeploymentOverview makeRecordingOverview() {
|
||||
|
||||
RecordingList recordingPeriods = listSoundAcquisitionDatabase();
|
||||
|
||||
RecordingList binaryPeriods = listBinaryFiles();
|
||||
|
||||
long l1 = listDuration(recordingPeriods);
|
||||
long l2 = listDuration(binaryPeriods);
|
||||
if (listDuration(binaryPeriods) > listDuration(recordingPeriods)) {
|
||||
recordingPeriods = binaryPeriods;
|
||||
}
|
||||
|
||||
DeploymentOverview deploymentOverview = createOverview(recordingPeriods);
|
||||
|
||||
return deploymentOverview;
|
||||
}
|
||||
|
||||
private long listDuration(RecordingList recordingList) {
|
||||
if (recordingList == null) {
|
||||
return -1;
|
||||
}
|
||||
return recordingList.duration();
|
||||
}
|
||||
|
||||
public RecordingList listBinaryFiles() {
|
||||
BinaryStore binaryStore = BinaryStore.findBinaryStoreControl();
|
||||
if (binaryStore == null) {
|
||||
return null;
|
||||
}
|
||||
RecordingList bestList = null;
|
||||
ArrayList<PamDataBlock> allBlocks = PamController.getInstance().getDataBlocks();
|
||||
for (PamDataBlock aBlock : allBlocks) {
|
||||
OfflineDataMap dataMap = aBlock.getOfflineDataMap(binaryStore);
|
||||
if (dataMap == null) {
|
||||
continue;
|
||||
}
|
||||
TethysDataProvider tethysProvider = aBlock.getTethysDataProvider(tethysControl);
|
||||
if (tethysProvider == null) {
|
||||
continue; // do we really need this ?
|
||||
}
|
||||
RecordingList blockList = listMapPoints(dataMap);
|
||||
if (blockList == null) {
|
||||
continue;
|
||||
}
|
||||
if (bestList == null) {
|
||||
bestList = blockList;
|
||||
}
|
||||
else {
|
||||
long l1 = bestList.duration();
|
||||
long l2 = blockList.duration();
|
||||
if (l2>l1) {
|
||||
bestList = blockList;
|
||||
}
|
||||
}
|
||||
}
|
||||
bestList = mergeRecordings(bestList);
|
||||
return bestList;
|
||||
}
|
||||
|
||||
|
||||
public RecordingList listMapPoints(OfflineDataMap dataMap) {
|
||||
List<OfflineDataMapPoint> mapPoints = dataMap.getMapPoints();
|
||||
if (mapPoints == null) {
|
||||
return null;
|
||||
}
|
||||
RecordingList periods = new RecordingList();
|
||||
for (OfflineDataMapPoint mapPoint : mapPoints) {
|
||||
periods.add(new RecordingPeriod(mapPoint.getStartTime(), mapPoint.getEndTime()));
|
||||
}
|
||||
return periods;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public RecordingList listSoundAcquisitionDatabase() {
|
||||
// first find an acquisition module.
|
||||
PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
|
||||
if (!(aModule instanceof AcquisitionControl)) {
|
||||
// will return if it's null. Impossible for it to be the wrong type.
|
||||
// but it's good practice to check anyway before casting.
|
||||
return null;
|
||||
}
|
||||
// cast it to the right type.
|
||||
AcquisitionControl daqControl = (AcquisitionControl) aModule;
|
||||
AcquisitionParameters daqParams = daqControl.getAcquisitionParameters();
|
||||
/**
|
||||
* The daqParams class has most of what we need about the set up in terms of sample rate,
|
||||
* number of channels, instrument type, ADC input range (part of calibration), etc.
|
||||
* It also has a hydrophone list, which maps the input channel numbers to the hydrophon numbers.
|
||||
* Realistically, this list is always 0,1,2,etc or it goes horribly wrong !
|
||||
*/
|
||||
// so write functions here to get information from the daqParams.
|
||||
// System.out.printf("Sample regime: %s input with rate %3.1fHz, %d channels, gain %3.1fdB, ADCp-p %3.1fV\n", daqParams.getDaqSystemType(),
|
||||
// daqParams.getSampleRate(), daqParams.getNChannels(), daqParams.preamplifier.getGain(), daqParams.voltsPeak2Peak);
|
||||
/**
|
||||
* then there is the actual sampling. This is a bit harder to find. I thought it would be in the data map
|
||||
* but the datamap is a simple count of what's in the databasase which is not quite what we want.
|
||||
* we're going to have to query the database to get more detailed informatoin I think.
|
||||
* I'll do that here for now, but we may want to move this when we better organise the code.
|
||||
* It also seems that there are 'bad' dates in the database when it starts new files, which are the date
|
||||
* data were analysed at. So we really need to check the start and stop records only.
|
||||
*/
|
||||
PamDataBlock<DaqStatusDataUnit> daqInfoDataBlock = daqControl.getAcquisitionProcess().getDaqStatusDataBlock();
|
||||
// just load everything. Probably OK for the acqusition, but will bring down
|
||||
daqInfoDataBlock.loadViewerData(0, Long.MAX_VALUE, null);
|
||||
ArrayList<DaqStatusDataUnit> allStatusData = daqInfoDataBlock.getDataCopy();
|
||||
/**
|
||||
* Due to weird file overlaps we need to resort this by id if we can.
|
||||
*
|
||||
*/
|
||||
Collections.sort(allStatusData, new Comparator<DaqStatusDataUnit>() {
|
||||
|
||||
@Override
|
||||
public int compare(DaqStatusDataUnit o1, DaqStatusDataUnit o2) {
|
||||
if (o1.getDatabaseIndex() == 0) {
|
||||
return (int) (o1.getTimeMilliseconds()-o2.getTimeMilliseconds());
|
||||
}
|
||||
return o1.getDatabaseIndex()-o2.getDatabaseIndex();
|
||||
}
|
||||
});
|
||||
|
||||
RecordingList tempPeriods = null;
|
||||
|
||||
if (allStatusData == null || allStatusData.size() == 0) {
|
||||
System.out.println("Data appear to have no logged recording periods. Try to extract from raw audio ...");
|
||||
tempPeriods = extractTimesFromFiles(daqControl);
|
||||
}
|
||||
else {
|
||||
tempPeriods = extractTimesFromStatus(allStatusData);
|
||||
}
|
||||
if (tempPeriods == null || tempPeriods.size() == 0) {
|
||||
System.out.println("Data appear to have no logged recording periods available either from the database or the raw recordings.");
|
||||
tempPeriods = extractTimesFromOutputMaps();
|
||||
}
|
||||
if (tempPeriods == null || tempPeriods.size() == 0) {
|
||||
System.out.println("Data appear to have no logged recording periods available either from the database or the raw recordings.");
|
||||
return null;
|
||||
}
|
||||
|
||||
int nPeriods = tempPeriods.size();
|
||||
// int i = 0;
|
||||
// for (RecordingPeriod aP : tempPeriods) {
|
||||
// System.out.printf("Pre merge %d : %s to %s\n", i++, PamCalendar.formatDBDateTime(aP.getRecordStart()),
|
||||
// PamCalendar.formatDBDateTime(aP.getRecordStop()));
|
||||
// }
|
||||
|
||||
tempPeriods = mergeRecordings(tempPeriods);
|
||||
|
||||
return tempPeriods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge close recordings and discard ones that are too short.
|
||||
* @param tempPeriods all recording periods, may be from consecutive files.
|
||||
* @return merged list.
|
||||
*/
|
||||
private RecordingList mergeRecordings(RecordingList tempPeriods) {
|
||||
// now go through those and merge into longer periods where there is no gap between files.
|
||||
if (tempPeriods == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DeploymentExportOpts exportOptions = tethysControl.getDeploymentHandler().getDeploymentExportOptions();
|
||||
|
||||
ListIterator<RecordingPeriod> iterator = tempPeriods.listIterator();
|
||||
RecordingPeriod prevPeriod = null;
|
||||
while (iterator.hasNext()) {
|
||||
RecordingPeriod nextPeriod = iterator.next();
|
||||
long nextDur = nextPeriod.getRecordStop()-nextPeriod.getRecordStart();
|
||||
if (nextDur == 0) {
|
||||
continue;
|
||||
}
|
||||
if (prevPeriod != null) {
|
||||
long gap = nextPeriod.getRecordStart() - prevPeriod.getRecordStop();
|
||||
long prevDur = prevPeriod.getRecordStop()-prevPeriod.getRecordStart();
|
||||
if (gap < exportOptions.maxRecordingGapSeconds*1000) {
|
||||
// ignoring up to 3s gap or a sample error < 2%.Dunno if this is sensible or not.
|
||||
prevPeriod.setRecordStop(nextPeriod.getRecordStop());
|
||||
iterator.remove();
|
||||
nextPeriod = prevPeriod;
|
||||
}
|
||||
}
|
||||
prevPeriod = nextPeriod;
|
||||
}
|
||||
// now remove ones which are too short even after merging.
|
||||
iterator = tempPeriods.listIterator();
|
||||
while (iterator.hasNext()) {
|
||||
RecordingPeriod nextPeriod = iterator.next();
|
||||
long duration = nextPeriod.getDuration();
|
||||
if (duration < exportOptions.minRecordingLengthSeconds*1000L) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
return tempPeriods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out whether or not the data are evenly duty cycled by testing the
|
||||
* distributions of on and off times.
|
||||
* @param tempPeriods
|
||||
* @return
|
||||
*/
|
||||
private DutyCycleInfo assessDutyCycle(RecordingList tempPeriods) {
|
||||
int n = tempPeriods.size();
|
||||
if (n < 2) {
|
||||
return new DutyCycleInfo(false, 0,0,n);
|
||||
}
|
||||
double[] ons = new double[n-1]; // ignore the last one since it may be artificially shortened which is OK
|
||||
double[] gaps = new double[n-1];
|
||||
for (int i = 0; i < n-1; i++) {
|
||||
ons[i] = tempPeriods.get(i).getDuration()/1000.;
|
||||
gaps[i] = (tempPeriods.get(i+1).getRecordStart()-tempPeriods.get(i).getRecordStop())/1000.;
|
||||
}
|
||||
/* now look at how consistent those values are
|
||||
* But some data gets messed by small gaps, so want to
|
||||
* remove outliers and concentrate on say 80% of the data.
|
||||
*/
|
||||
ons = getDistributionCentre(ons, 80);
|
||||
gaps = getDistributionCentre(gaps, 80);
|
||||
Arrays.sort(gaps);
|
||||
|
||||
|
||||
STD std = new STD();
|
||||
double onsMean = std.getMean(ons);
|
||||
double onsSTD = std.getSTD(ons);
|
||||
double gapsMean = std.getMean(gaps);
|
||||
double gapsSTD = std.getSTD(gaps);
|
||||
boolean dutyCycle = onsSTD/onsMean < .05 && gapsSTD/gapsMean < 0.05;
|
||||
DutyCycleInfo cycleInfo = new DutyCycleInfo(dutyCycle, onsMean, gapsMean, tempPeriods.size());
|
||||
return cycleInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the central part of a distribution without any outliers so
|
||||
* that we can get a better assessment of duty cycle.
|
||||
* @param data unsorted distribution data.
|
||||
* @param percent percentage to include (half this removed from top and bottom)
|
||||
* @return
|
||||
*/
|
||||
private double[] getDistributionCentre(double[] data, double percent) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
Arrays.sort(data);
|
||||
int nRem = (int) Math.round(data.length * (100-percent)/200);
|
||||
int newLen = data.length-nRem*2;
|
||||
double[] subdata = Arrays.copyOfRange(data, nRem, data.length-2*nRem);
|
||||
if (subdata.length < 2) {
|
||||
return data;
|
||||
}
|
||||
return subdata;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get data times from any other datamap, since this will generally match the acquisition anyway
|
||||
* @return
|
||||
*/
|
||||
private RecordingList extractTimesFromOutputMaps() {
|
||||
OfflineDataMap bestMap = null;
|
||||
PamDataBlock bestBlock = null;
|
||||
long firstStart = Long.MAX_VALUE;
|
||||
long lastEnd = Long.MIN_VALUE;
|
||||
ArrayList<PamDataBlock> dataBlocks = PamController.getInstance().getDetectorDataBlocks();
|
||||
for (PamDataBlock aBlock : dataBlocks) {
|
||||
if (aBlock instanceof PamRawDataBlock) {
|
||||
continue; // don't want acquisition !
|
||||
}
|
||||
OfflineDataMap dataMap = aBlock.getPrimaryDataMap();
|
||||
if (dataMap == null) {
|
||||
continue;
|
||||
}
|
||||
if (dataMap.getFirstDataTime() < firstStart && dataMap.getLastDataTime() > lastEnd) {
|
||||
bestMap = dataMap;
|
||||
bestBlock = aBlock;
|
||||
firstStart = dataMap.getFirstDataTime();
|
||||
lastEnd = dataMap.getLastDataTime();
|
||||
}
|
||||
}
|
||||
if (bestMap == null) {
|
||||
return null;
|
||||
}
|
||||
// get the times out of it.
|
||||
RecordingList recPeriods = new RecordingList();
|
||||
List<OfflineDataMapPoint> mapPoints = bestMap.getMapPoints();
|
||||
for (OfflineDataMapPoint mapPoint : mapPoints) {
|
||||
recPeriods.add(new RecordingPeriod(mapPoint.getStartTime(), mapPoint.getEndTime()));
|
||||
}
|
||||
return recPeriods;
|
||||
}
|
||||
|
||||
private RecordingList extractTimesFromStatus(ArrayList<DaqStatusDataUnit> allStatusData) {
|
||||
RecordingList tempPeriods = new RecordingList();
|
||||
long dataStart = Long.MAX_VALUE;
|
||||
long dataEnd = Long.MIN_VALUE;
|
||||
Long lastStart = null;
|
||||
int nStart = 0;
|
||||
int nStop = 0;
|
||||
int nFile = 0;
|
||||
for (DaqStatusDataUnit daqStatus : allStatusData) {
|
||||
switch (daqStatus.getStatus()) {
|
||||
case "Start":
|
||||
nStart++;
|
||||
dataStart = Math.min(dataStart, daqStatus.getTimeMilliseconds());
|
||||
lastStart = daqStatus.getTimeMilliseconds();
|
||||
// System.out.println("Start at " + PamCalendar.formatDBDateTime(lastStart));
|
||||
break;
|
||||
case "Stop":
|
||||
nStop++;
|
||||
dataEnd = Math.max(dataEnd, daqStatus.getEndTimeInMilliseconds());
|
||||
long lastEnd = daqStatus.getEndTimeInMilliseconds();
|
||||
if (lastStart != null) {
|
||||
// System.out.printf("Adding period %s to %s\n", PamCalendar.formatDBDateTime(lastStart),
|
||||
// PamCalendar.formatDBDateTime(lastEnd));
|
||||
tempPeriods.add(new RecordingPeriod(lastStart, lastEnd));
|
||||
}
|
||||
else {
|
||||
// System.out.println("Skipping stop at " + PamCalendar.formatDBDateTime(lastEnd));
|
||||
}
|
||||
lastStart = null;
|
||||
break;
|
||||
case "NextFile":
|
||||
nFile++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tempPeriods;
|
||||
}
|
||||
|
||||
private RecordingList extractTimesFromFiles(AcquisitionControl daqControl) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
52
src/tethys/deployment/RecordingList.java
Normal file
52
src/tethys/deployment/RecordingList.java
Normal file
@ -0,0 +1,52 @@
|
||||
package tethys.deployment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class RecordingList extends ArrayList<RecordingPeriod> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Get the duration of the recording periods from start to end.
|
||||
* @return
|
||||
*/
|
||||
public long duration() {
|
||||
return getEnd()-getStart();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the start of the first in the list.
|
||||
* @return
|
||||
*/
|
||||
public long getStart() {
|
||||
if (size() == 0) {
|
||||
return 0;
|
||||
}
|
||||
return get(0).getRecordStart();
|
||||
}
|
||||
|
||||
/**
|
||||
* get the end of the last in the list.
|
||||
*/
|
||||
public long getEnd() {
|
||||
if (size() == 0) {
|
||||
return 0;
|
||||
}
|
||||
return get(size()-1).getRecordStop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the list in ascending order.
|
||||
*/
|
||||
public void sort() {
|
||||
Collections.sort(this, new Comparator<RecordingPeriod>() {
|
||||
|
||||
@Override
|
||||
public int compare(RecordingPeriod o1, RecordingPeriod o2) {
|
||||
return (int) Math.signum(o1.getRecordStart()-o2.getRecordStart());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -127,6 +127,9 @@ public class ProjectInformationPanel {
|
||||
}
|
||||
|
||||
public boolean getParams(Deployment deployment) {
|
||||
if (deployment == null) {
|
||||
return false;
|
||||
}
|
||||
deployment.setCruise(cruise.getText());
|
||||
deployment.setRegion(region.getText());
|
||||
deployment.setSite(site.getText());
|
||||
|
@ -51,20 +51,20 @@ public class RecordingGapDialog extends PamDialog {
|
||||
|
||||
private void setParams(DeploymentExportOpts exportOpts) {
|
||||
this.exportOpts = exportOpts;
|
||||
maxGap.setText(String.format("%d", exportOpts.maxGapSeconds));
|
||||
minLength.setText(String.format("%d", exportOpts.minLengthSeconds));
|
||||
maxGap.setText(String.format("%d", exportOpts.maxRecordingGapSeconds));
|
||||
minLength.setText(String.format("%d", exportOpts.minRecordingLengthSeconds));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getParams() {
|
||||
try {
|
||||
exportOpts.maxGapSeconds = Integer.valueOf(maxGap.getText());
|
||||
exportOpts.maxRecordingGapSeconds = Integer.valueOf(maxGap.getText());
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return showWarning("Invalid inter recording interval");
|
||||
}
|
||||
try {
|
||||
exportOpts.minLengthSeconds = Integer.valueOf(minLength.getText());
|
||||
exportOpts.minRecordingLengthSeconds = Integer.valueOf(minLength.getText());
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return showWarning("Invalid minimum recording length");
|
||||
|
@ -39,10 +39,12 @@ import tethys.dbxml.TethysException;
|
||||
import tethys.deployment.DeploymentHandler;
|
||||
import tethys.niluswraps.PDeployment;
|
||||
import tethys.niluswraps.PDetections;
|
||||
import tethys.output.DatablockSynchInfo;
|
||||
import tethys.output.StreamExportParams;
|
||||
import tethys.output.TethysExportParams;
|
||||
import tethys.pamdata.TethysDataProvider;
|
||||
import tethys.species.DataBlockSpeciesManager;
|
||||
import tethys.swing.export.DetectionsExportWizard;
|
||||
|
||||
/**
|
||||
* Functions for handling output of Detections documents.
|
||||
@ -401,6 +403,11 @@ public class DetectionsHandler {
|
||||
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_COUNTING);
|
||||
exportObserver.update(prog);
|
||||
granularityHandler.prepare(deployment.getAudioStart());
|
||||
|
||||
if (currentDetections == null) {
|
||||
currentDetections = startDetectionsDocument(deployment, dataBlock, streamExportParams);
|
||||
currentDetections.getEffort().setStart(TethysTimeFuncs.xmlGregCalFromMillis(deployment.getAudioStart()));
|
||||
}
|
||||
// export everything in that deployment.
|
||||
// need to loop through all map points in this interval.
|
||||
List<OfflineDataMapPoint> mapPoints = dataMap.getMapPoints();
|
||||
@ -411,10 +418,6 @@ public class DetectionsHandler {
|
||||
exportObserver.update(prog);
|
||||
}
|
||||
|
||||
if (currentDetections == null) {
|
||||
currentDetections = startDetectionsDocument(deployment, dataBlock, streamExportParams);
|
||||
currentDetections.getEffort().setStart(TethysTimeFuncs.xmlGregCalFromMillis(mapPoint.getStartTime()));
|
||||
}
|
||||
if (mapPoint.getEndTime() < deployment.getAudioStart()) {
|
||||
continue;
|
||||
}
|
||||
@ -629,4 +632,30 @@ public class DetectionsHandler {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Export data from given block, using appropriate species checks and other dialogs.
|
||||
* @param dataBlock
|
||||
*/
|
||||
public void exportDataBlock(PamDataBlock dataBlock) {
|
||||
if (dataBlock == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
DetectionsExportWizard.showDialog(tethysControl.getGuiFrame(), tethysControl, dataBlock);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -169,48 +169,5 @@ public class NilusSettingsWrapper<T extends Object> implements Serializable, Clo
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
// private Class<?> getNilusClass() throws NoSuchMethodException, SecurityException {
|
||||
// Method method = this.getClass().getMethod("getNilusObject", null);
|
||||
// Class<?> retClass = GenericTypeResolver.resolveReturnType(method, this.getClass());
|
||||
//
|
||||
// return retClass;
|
||||
// }
|
||||
|
||||
//
|
||||
// public static void main(String[] args) {
|
||||
//
|
||||
// Deployment deployment = new Deployment();
|
||||
// try {
|
||||
// Helper.createRequiredElements(deployment);
|
||||
// } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// deployment.setCruise("Test cruise");
|
||||
// deployment.setDeploymentId(111);
|
||||
// deployment.setProject("Tethys Development");
|
||||
// DescriptionType desc = deployment.getDescription();
|
||||
// if (desc == null) {
|
||||
// desc = new DescriptionType();
|
||||
// deployment.setDescription(desc);
|
||||
// }
|
||||
// desc.setAbstract("Deployment Abstract");
|
||||
//
|
||||
// NilusSettingsWrapper<Deployment> wrapper = new NilusSettingsWrapper<>();
|
||||
//
|
||||
// wrapper.setNilusObject(deployment);
|
||||
//
|
||||
// System.out.println(wrapper.xmlString);
|
||||
//
|
||||
// Deployment newDeployment = wrapper.getNilusObject(Deployment.class);
|
||||
//
|
||||
// // now warp the new object again and print that.
|
||||
// newDeployment.setDeploymentId(newDeployment.getDeploymentId()*2);
|
||||
// wrapper.setNilusObject(newDeployment);
|
||||
// System.out.println("********************************************");
|
||||
// System.out.println(wrapper.xmlString);
|
||||
//
|
||||
// }
|
||||
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package tethys.niluswraps;
|
||||
import java.io.Serializable;
|
||||
|
||||
import nilus.DescriptionType;
|
||||
import nilus.Helper;
|
||||
|
||||
/**
|
||||
* Because we want to save DescriptionType objects in serialised
|
||||
@ -32,7 +33,17 @@ public class WrappedDescriptionType extends NilusSettingsWrapper<DescriptionType
|
||||
}
|
||||
|
||||
public DescriptionType getDescription() {
|
||||
return getNilusObject(DescriptionType.class);
|
||||
DescriptionType description = getNilusObject(DescriptionType.class);
|
||||
if (description == null) {
|
||||
description = new DescriptionType();
|
||||
try {
|
||||
Helper.createRequiredElements(description);
|
||||
} catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
setNilusObject(description);
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(DescriptionType description) {
|
||||
@ -79,6 +90,10 @@ public class WrappedDescriptionType extends NilusSettingsWrapper<DescriptionType
|
||||
* @param method the method to set
|
||||
*/
|
||||
public void setMethod(String method) {
|
||||
DescriptionType description = getDescription();
|
||||
if (description == null) {
|
||||
return;
|
||||
}
|
||||
getDescription().setMethod(method);
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,14 @@ public class TethysExportParams implements Serializable, Cloneable{
|
||||
|
||||
public static final long serialVersionUID = 1L;
|
||||
|
||||
public static final int DETECTORE_PARAMS_NONE = 0;
|
||||
public static final int DETECTOR_DATASELECTOR = 1;
|
||||
public static final int DETECTORE_PARAMS_MODULE = 2;
|
||||
public static final int DETECTORE_PARAMS_CHAIN = 3;
|
||||
public static final String[] paramsOptNames = {"None", "Data Selector only", "Module only", "Full process chain"};
|
||||
|
||||
public int detectorParameterOutput = DETECTORE_PARAMS_CHAIN;
|
||||
|
||||
/*
|
||||
* Need to add lots of other parameters here, such as the connection details
|
||||
* for the tethys database.
|
||||
@ -37,6 +45,7 @@ public class TethysExportParams implements Serializable, Cloneable{
|
||||
private String datasetName;
|
||||
|
||||
public boolean listDocsInPamguard;
|
||||
|
||||
|
||||
/**
|
||||
* @return the datasetName
|
||||
|
@ -1,283 +0,0 @@
|
||||
package tethys.output;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import Acquisition.AcquisitionControl;
|
||||
import Acquisition.AcquisitionProcess;
|
||||
import Array.ArrayManager;
|
||||
import Array.Hydrophone;
|
||||
import Array.PamArray;
|
||||
import Array.SnapshotGeometry;
|
||||
import PamController.PamController;
|
||||
import PamUtils.PamCalendar;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
import metadata.MetaDataContol;
|
||||
import nilus.Deployment;
|
||||
import tethys.TethysControl;
|
||||
import tethys.dbxml.DBXMLConnect;
|
||||
import tethys.dbxml.TethysException;
|
||||
import tethys.deployment.DeploymentHandler;
|
||||
import tethys.deployment.DeploymentOverview;
|
||||
import tethys.deployment.RecordingPeriod;
|
||||
import tethys.detection.DetectionsHandler;
|
||||
|
||||
/**
|
||||
* No longer used. This was purely a test class used for making the first couple
|
||||
* of test connections and exports to Tethys. Can probably delete.
|
||||
*
|
||||
* Class sitting at the centre of all operations. It will talk to PAMGuard
|
||||
* objects to get schemas and data and talk to the database connection to move
|
||||
* data out (and possibly in). Eventually, a lot of the functionality in here
|
||||
* will be moved to worker threads (SwingWorker?) so that it's easy to keep
|
||||
* dialogs alive, show progress for big export jobs, etc. For now though, it's a
|
||||
* relatively simple set of function which we can use to a) open the database,
|
||||
* b) check everything such as schemas, etc. c) export data and d) clean up.
|
||||
*
|
||||
* @author dg50
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public class TethysExporter {
|
||||
|
||||
private TethysControl tethysControl;
|
||||
private TethysExportParams tethysExportParams;
|
||||
|
||||
private DBXMLConnect dbxmlConnect;
|
||||
|
||||
private TethysExporter(TethysControl tethysControl, TethysExportParams tethysExportParams) {
|
||||
this.tethysControl = tethysControl;
|
||||
this.tethysExportParams = tethysExportParams;
|
||||
dbxmlConnect = new DBXMLConnect(tethysControl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the work. In reality this will need an awful lot of changing, for
|
||||
* instance to provide feedback to an observer class to show progress on the
|
||||
* display.
|
||||
*
|
||||
* @return OK if success.
|
||||
*/
|
||||
public boolean doExport() {
|
||||
|
||||
// boolean dbOK = dbxmlConnect.openDatabase();
|
||||
// if (!dbOK) {
|
||||
/*
|
||||
* should we set up some exceptions to throw ? Can be a lot more informative
|
||||
* than a simple 'false'
|
||||
*/
|
||||
// return false;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Doug populate instrument fields - may need to add a few things. Marie to
|
||||
* define what we mean by instrument. Instrument names probably need to be added
|
||||
* to the PAMGuard Array dialog and can then be extraced from there. We had some
|
||||
* useful discussion about what constitutes an instrumnet in Tinas dataset where
|
||||
* there was a deployment of 10 MARU's, but the files from all of them were
|
||||
* merged into a single 10 channel wav file dataset and processed together for
|
||||
* detection and localisation. Clearly this goes into a single Tethys database,
|
||||
* but do we put 'MARU Array' as the instrument and then include serial numbers
|
||||
* of individual MARU's with the hydrophone data, or what ?
|
||||
*/
|
||||
|
||||
/**
|
||||
* Doug write something here to get most of the 'samplingdetails' schema. This
|
||||
* all comes out of the Sound Acquisition module. Code below shows how to find
|
||||
* this and iterate through various bits of information ... (I've put it in a
|
||||
* separate function. Currently returning void,but could presumably return a
|
||||
* Tethys samplingdetails document?)
|
||||
*/
|
||||
|
||||
/*
|
||||
* A load of notes Katie put in ....654654654
|
||||
*/
|
||||
|
||||
//1. grab DeploymentRecoveryPair that has deployment details and recovery details
|
||||
//a. this is based on start and end times
|
||||
//Douglas calculates out dutycycles to only grab the
|
||||
|
||||
//2. loop through the pairs to populate the extra information
|
||||
//one pair is one deployment
|
||||
//see below for matching
|
||||
|
||||
|
||||
//id => unique
|
||||
//project => project in pamguard
|
||||
//deploymentId == id
|
||||
//deploymentAlias => blank
|
||||
//site => UI addition in pamguard, not done, can be blank
|
||||
//siteAlias => blank
|
||||
//cruise => UI addition, optional
|
||||
//Platform=> UI addition in pamguard
|
||||
//region => UI addition
|
||||
//Instrument/Type => UI, array manager details (hydrophone names area)
|
||||
//Instrument/Id => UI, array manager details
|
||||
//Instrument/Geometry => in pamguard array manager
|
||||
//SamplingDetails/Channel
|
||||
//ChannelNumber => in pamguard, hyrdrophone array
|
||||
//SensorNumber => in pamguard,
|
||||
//Start => same as timestamp deployment detail
|
||||
//End => same as timestamp recovery detail
|
||||
//Sampling/Regimen (change sample rate, pamgauard doesnt handle, only on, get channel info in that loop)
|
||||
//TimeStamp => start time
|
||||
//SampleRate_kHz =>
|
||||
//SampleBits =>
|
||||
//Gain (another func call to get gain info)
|
||||
//DutyCycles => needs to be calculated, not fields in pamguard, have fun Douglas
|
||||
//QualityAssurance => not in pamguard, UI, maybe deployment notes, optional
|
||||
//Data/Audio (static)
|
||||
//URI => folder where audio is saved
|
||||
//Data/Tracks
|
||||
//Track => GPS datatable (granularity filter)
|
||||
//TrackId => not unique between deployments,
|
||||
//TrackEffort
|
||||
//OnPath => scattered throughout pamguard
|
||||
//URI => option, check with Shannon on how they are doing deployments
|
||||
//Sensors/Audio (per hydrophone not quad array) streamer info + individual hydrophone data together
|
||||
//pamguard hydrophone data
|
||||
//number => hydrophoneId
|
||||
//sensorId => sensor serial number
|
||||
//Geometry => array geometry field goes to
|
||||
//Sensors/Depth
|
||||
//optional
|
||||
//Sensors/Sensor
|
||||
//Number => hydrophoneId in pamguard
|
||||
//SensorId => addition to UI
|
||||
//Geometry => array geometry fields
|
||||
//Type => Hydrophone Type
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//get list of deployment recovery details (start, stop times and lat/long)
|
||||
//deployment details and recovery details are same structure
|
||||
//per pair, go through a loop to fill in each deployment
|
||||
// DeploymentHandler deploymentHandler = new DeploymentHandler(tethysControl);
|
||||
DeploymentHandler deploymentHandler = tethysControl.getDeploymentHandler();
|
||||
|
||||
// ArrayList<DeploymentRecoveryPair> deployRecover = deploymentHandler.getDeployments();
|
||||
// if (deployRecover == null) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
ArrayList<Deployment> deploymentDocs = new ArrayList<>();
|
||||
/*
|
||||
* This will become the main loop over deployment documents
|
||||
*/
|
||||
DeploymentOverview deploymentOverview = deploymentHandler.getDeploymentOverview();
|
||||
int i = deploymentHandler.getFirstFreeDeploymentId();
|
||||
for (RecordingPeriod recordingPeriod : deploymentOverview.getRecordingPeriods()) {
|
||||
|
||||
Deployment deployment = deploymentHandler.createDeploymentDocument(i++, recordingPeriod);
|
||||
// System.out.println(deployment.toString());
|
||||
deploymentDocs.add(deployment);
|
||||
try {
|
||||
tethysControl.getDbxmlConnect().postAndLog(deployment);
|
||||
} catch (TethysException e) {
|
||||
tethysControl.showException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* go through the export params and call something for every data block that's
|
||||
* enabled.
|
||||
*/
|
||||
DetectionsHandler detectionsHandler = new DetectionsHandler(tethysControl);
|
||||
ArrayList<PamDataBlock> allDataBlocks = PamController.getInstance().getDataBlocks();
|
||||
// /**
|
||||
// * Outer loop is through deployemnt documents. Will then export detections within each
|
||||
// * deployment detector by detector
|
||||
// */
|
||||
// for (Deployment aDeployment : deploymentDocs) {
|
||||
// for (PamDataBlock aDataBlock : allDataBlocks) {
|
||||
// StreamExportParams streamExportParams = tethysExportParams.getStreamParams(aDataBlock);
|
||||
// if (streamExportParams == null || !streamExportParams.selected) {
|
||||
// continue; // not interested in this one.
|
||||
// }
|
||||
// detectionsHandler.exportDetections(aDataBlock, aDeployment,
|
||||
// new DetectionGranularity(GRANULARITY.TIME, 3600*12), tethysExportParams, streamExportParams);
|
||||
// }
|
||||
// }
|
||||
/*
|
||||
* Then do whatever else is needed to complete the document.
|
||||
*/
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * find Deployment data. This is stored in a separate PAMGuard module, which may
|
||||
// * not be present.
|
||||
// *
|
||||
// * @return
|
||||
// */
|
||||
// public DeploymentData findDeploymentData() {
|
||||
// /**
|
||||
// * What to do if this isn't present or is incomplete ? Should we be showing this
|
||||
// * in the main export dialog at some point ? More a Q for when we make a nicer
|
||||
// * UI later in the project.
|
||||
// */
|
||||
// MetaDataContol metaControl = (MetaDataContol) PamController.getInstance()
|
||||
// .findControlledUnit(MetaDataContol.unitType);
|
||||
// if (metaControl == null) {
|
||||
// return null;
|
||||
// } else {
|
||||
// return metaControl.getDeploymentData();
|
||||
// }
|
||||
// }
|
||||
|
||||
public SnapshotGeometry findArrayGeometrey() {
|
||||
/*
|
||||
* this should never be null, but again, we might want to put some warnings and
|
||||
* exception handlers in here anyway. Really just an example to show how to find
|
||||
* this. We'll need to dig a bit elsewhere to get more detailed hydrophone
|
||||
* information.
|
||||
*/
|
||||
/*
|
||||
* In PAMGuard hydrophones are assigned to streamers, which can have different
|
||||
* methods for estimating their positions from GPS. The geometry is a sum of xyz
|
||||
* in the streamer and xyz in the hydrophone object Within a streamer,
|
||||
* hydrophones are considered rigid relative to each other. The stremer will
|
||||
* floow a choice of modesl (rigid, threading, etc) to estimate it's position
|
||||
* relative to the GPS track. Different errors are used when estimating
|
||||
* localisation errors within and between streamers. The Snapshot geometry sorts
|
||||
* a lot of this out for a point in time and will give back a single object
|
||||
* which is most of what we'll be wanting.
|
||||
*/
|
||||
PamArray currentArray = ArrayManager.getArrayManager().getCurrentArray();
|
||||
SnapshotGeometry currentGeometry = currentArray.getSnapshotGeometry(PamCalendar.getTimeInMillis());
|
||||
/*
|
||||
* The following lines of code show how to get more detailed calibration info
|
||||
* for each hydrophone, but we'll have to think about the easiest way to
|
||||
* repackage this for Tethys. e.g. this function could be modified to return the
|
||||
* correct Tethys object in one go.
|
||||
*/
|
||||
ArrayList<Hydrophone> hydrophones = currentArray.getHydrophoneArray();
|
||||
/*
|
||||
* each object in the list will have more detailed cal information for each
|
||||
* phone. But for the full system calibration we'd need to go to the Acquisition
|
||||
* module.
|
||||
*/
|
||||
AcquisitionControl daqControl = (AcquisitionControl) PamController.getInstance()
|
||||
.findControlledUnit(AcquisitionControl.unitType);
|
||||
if (daqControl != null) {
|
||||
AcquisitionProcess daqProcess = daqControl.getAcquisitionProcess();
|
||||
for (int iPhone = 0; iPhone < hydrophones.size(); iPhone++) {
|
||||
Hydrophone aPhone = hydrophones.get(iPhone);
|
||||
double totalCal = -daqProcess.rawAmplitude2dB(1, iPhone, false);
|
||||
// System.out.printf(
|
||||
// "hydrophone %d has sensitivity %3.1fdB + gain %3.1fdB. Total calibration is %3.1fdB re1U/uPa\n",
|
||||
// iPhone, aPhone.getSensitivity(), aPhone.getPreampGain(), totalCal);
|
||||
}
|
||||
}
|
||||
|
||||
return currentGeometry;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,187 +0,0 @@
|
||||
package tethys.output.swing;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Window;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
import PamController.PamController;
|
||||
import PamView.dialog.PamDialog;
|
||||
import PamView.dialog.PamGridBagContraints;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
import PamguardMVC.dataSelector.DataSelector;
|
||||
import tethys.TethysControl;
|
||||
import tethys.output.StreamExportParams;
|
||||
import tethys.output.TethysExportParams;
|
||||
|
||||
/**
|
||||
* Start of a dialog for controlling the export of Tethys data. For first iteration
|
||||
* this will just be a list of output streams (PamDataBlocks) which have a database
|
||||
* connection. Each will have a checkbox. On OK it will return back a class listing
|
||||
* what to output and the calling function can do as it will. Future versions will
|
||||
* probably want to push the functionality into a SwingWorker to show progress, etc.
|
||||
* but that can come later.
|
||||
*
|
||||
* Normally, I use single instance dialogs for this sort of thing.
|
||||
* @author dg50
|
||||
*
|
||||
*/
|
||||
public class TethysExportDialog extends PamDialog {
|
||||
|
||||
private static TethysExportDialog singleInstance;
|
||||
|
||||
private TethysControl tethysControl;
|
||||
|
||||
private TethysExportParams exportParams;
|
||||
|
||||
private JPanel streamsPanel;
|
||||
|
||||
private ArrayList<DataStreamSet> dataStreamSets = new ArrayList<>();
|
||||
|
||||
private TethysExportDialog(Window parentFrame, TethysControl tethysControl) {
|
||||
super(parentFrame, "Tethys Export", false);
|
||||
this.tethysControl = tethysControl;
|
||||
|
||||
JPanel mainPanel = new JPanel(new BorderLayout());
|
||||
/*
|
||||
* Expect to add at least one more panel at the top of this to have options
|
||||
* for things like connection details to the database. If not another panel,
|
||||
* then they can be arranged on tabs, as a wizard, etc.
|
||||
*/
|
||||
streamsPanel = new JPanel();
|
||||
streamsPanel.setBorder(new TitledBorder("Data Streams"));
|
||||
mainPanel.add(BorderLayout.CENTER, streamsPanel);
|
||||
|
||||
setDialogComponent(mainPanel);
|
||||
setResizable(true);
|
||||
|
||||
}
|
||||
@Deprecated
|
||||
private static TethysExportParams showDialog(Window parentFrame, TethysControl tethysControl) {
|
||||
if (singleInstance == null || singleInstance.getOwner() != parentFrame || singleInstance.tethysControl != tethysControl) {
|
||||
singleInstance = new TethysExportDialog(parentFrame, tethysControl);
|
||||
}
|
||||
singleInstance.makeStreamsPanel();
|
||||
singleInstance.setParams();
|
||||
singleInstance.setVisible(true);
|
||||
return singleInstance.exportParams;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* remake the panel. Gets rebuilt whenever dialog opens in case
|
||||
* the list of available data has changed.
|
||||
*/
|
||||
private void makeStreamsPanel() {
|
||||
streamsPanel.removeAll();
|
||||
streamsPanel.setLayout(new GridBagLayout());
|
||||
GridBagConstraints c = new PamGridBagContraints();
|
||||
dataStreamSets = findDataStreams();
|
||||
streamsPanel.add(new JLabel(" Data Stream ", JLabel.CENTER), c);
|
||||
c.gridx++;
|
||||
streamsPanel.add(new JLabel(" Data Select ", JLabel.CENTER), c);
|
||||
for (DataStreamSet aSet : dataStreamSets) {
|
||||
c.gridx = 0;
|
||||
c.gridy++;
|
||||
streamsPanel.add(aSet.checkBox, c);
|
||||
// try to add a data selector
|
||||
DataSelector dataSelector = aSet.dataBlock.getDataSelector(tethysControl.getDataSelectName(), false);
|
||||
if (dataSelector != null) {
|
||||
c.gridx++;
|
||||
JButton button = dataSelector.getDialogButton(this);
|
||||
if (button != null) {
|
||||
streamsPanel.add(button, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
pack();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set of data blocks that can provide Tethys data.
|
||||
* @return datablocks which can provide Tethys data
|
||||
*/
|
||||
private ArrayList<DataStreamSet> findDataStreams() {
|
||||
ArrayList<DataStreamSet> sets = new ArrayList<>();
|
||||
ArrayList<PamDataBlock> allDataBlocks = PamController.getInstance().getDataBlocks();
|
||||
for (PamDataBlock aDataBlock : allDataBlocks) {
|
||||
if (aDataBlock.getTethysDataProvider(tethysControl) != null) {
|
||||
sets.add(new DataStreamSet(aDataBlock));
|
||||
}
|
||||
}
|
||||
return sets;
|
||||
}
|
||||
|
||||
private void setParams() {
|
||||
this.exportParams = tethysControl.getTethysExportParams();
|
||||
if (exportParams == null) {
|
||||
exportParams = new TethysExportParams();
|
||||
}
|
||||
else {
|
||||
exportParams = exportParams.clone();
|
||||
}
|
||||
setParams(exportParams);
|
||||
}
|
||||
|
||||
private void setParams(TethysExportParams exportParams) {
|
||||
if (exportParams == null || dataStreamSets == null) {
|
||||
return;
|
||||
}
|
||||
for (DataStreamSet streamSet : dataStreamSets) {
|
||||
StreamExportParams streamOpts = exportParams.getStreamParams(streamSet.dataBlock);
|
||||
if (streamOpts == null) {
|
||||
continue;
|
||||
}
|
||||
streamSet.checkBox.setSelected(streamOpts.selected);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getParams() {
|
||||
if (exportParams == null || dataStreamSets == null) {
|
||||
return false;
|
||||
}
|
||||
int nSel = 0;
|
||||
for (DataStreamSet streamSet : dataStreamSets) {
|
||||
StreamExportParams streamOpts = new StreamExportParams(tethysControl, streamSet.dataBlock, streamSet.checkBox.isSelected());
|
||||
exportParams.setStreamParams(streamSet.dataBlock, streamOpts);
|
||||
nSel++;
|
||||
}
|
||||
return nSel > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelButtonPressed() {
|
||||
exportParams = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreDefaultSettings() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
private class DataStreamSet {
|
||||
|
||||
private PamDataBlock dataBlock;
|
||||
|
||||
private JCheckBox checkBox;
|
||||
|
||||
public DataStreamSet(PamDataBlock dataBlock) {
|
||||
super();
|
||||
this.dataBlock = dataBlock;
|
||||
checkBox = new JCheckBox(dataBlock.getDataName());
|
||||
checkBox.setToolTipText(dataBlock.getLongDataName());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -30,6 +30,7 @@ import PamguardMVC.dataSelector.DataSelectParams;
|
||||
import PamguardMVC.dataSelector.DataSelector;
|
||||
import nilus.MarshalXML;
|
||||
import tethys.TethysControl;
|
||||
import tethys.output.TethysExportParams;
|
||||
|
||||
/**
|
||||
* Functions to pack up a PAMGuard parameters object into the correct format
|
||||
@ -64,6 +65,7 @@ public class TethysParameterPacker {
|
||||
* Get a list of elements of parameters for all modules feeding
|
||||
* the given datablock. These are given in reverse order.
|
||||
* @param pamDataBlock output datablock
|
||||
* @param fullChain
|
||||
* @return parameters of all modules feeding that datablock.
|
||||
*/
|
||||
public List<Element> packParameters(PamDataBlock pamDataBlock) {
|
||||
@ -72,11 +74,14 @@ public class TethysParameterPacker {
|
||||
if (pamControlledUnit == null || pamControlledUnit instanceof PamSettings == false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int paramOption = tethysControl.getTethysExportParams().detectorParameterOutput;
|
||||
if (paramOption == TethysExportParams.DETECTORE_PARAMS_NONE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PamSettings pamSettings = (PamSettings) pamControlledUnit;
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// public List<Element> packParameters(Object data) {
|
||||
|
||||
List<Element> elList = new ArrayList<Element>();
|
||||
Object data = pamSettings.getSettingsReference();
|
||||
|
||||
@ -132,9 +137,9 @@ public class TethysParameterPacker {
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (paramOption == TethysExportParams.DETECTOR_DATASELECTOR) {
|
||||
return elList;
|
||||
}
|
||||
|
||||
QName qname = new QName(MarshalXML.schema, "parameters", "ty");
|
||||
JAXBElement<String> jaxel = new JAXBElement<String>(
|
||||
@ -165,6 +170,9 @@ public class TethysParameterPacker {
|
||||
el.appendChild(pgEl);
|
||||
// elList.add(pgEl);
|
||||
}
|
||||
if (paramOption == TethysExportParams.DETECTORE_PARAMS_MODULE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return elList;
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ abstract public class DataBlockSpeciesManager<T extends PamDataUnit> {
|
||||
allCodes.add(defaultDefaultSpecies.getPamguardName());
|
||||
}
|
||||
DataBlockSpeciesCodes codeList = getSpeciesCodes();
|
||||
if (codeList != null) {
|
||||
if (codeList != null && codeList.getSpeciesNames() != null) {
|
||||
allCodes.addAll(codeList.getSpeciesNames());
|
||||
}
|
||||
if (allCodes.size() == 0) {
|
||||
|
@ -8,7 +8,7 @@ package tethys.species;
|
||||
public class ITISTypes {
|
||||
|
||||
public static final int UNKNOWN = 0;
|
||||
public static final int ANTHROPOGENIC = -10;
|
||||
public static final int ANTHROPOGENIC = 1;
|
||||
|
||||
public static final String getName(int code) {
|
||||
switch (code) {
|
||||
|
@ -29,18 +29,30 @@ public class SpeciesSubPanel {
|
||||
private JButton searchButton;
|
||||
|
||||
public SpeciesSubPanel(String aSpecies) {
|
||||
|
||||
callType = new JTextField(15);
|
||||
pamguardName = new JLabel(aSpecies);
|
||||
itisCode = new JTextField(6);
|
||||
searchButton = new JButton("Find");
|
||||
latinName = new JTextField(15);
|
||||
commonName = new JTextField(15);
|
||||
|
||||
mainPanel = new JPanel(new GridBagLayout());
|
||||
mainPanel.setBorder(new BevelBorder(BevelBorder.RAISED));
|
||||
GridBagConstraints c = new PamGridBagContraints();
|
||||
mainPanel.add(new JLabel("Name ", JLabel.RIGHT), c);
|
||||
c.gridx++;
|
||||
mainPanel.add(pamguardName = new JLabel(aSpecies), c);
|
||||
mainPanel.add(pamguardName, c);
|
||||
c.gridx++;
|
||||
mainPanel.add(new JLabel(" ITIS code ", JLabel.RIGHT), c);
|
||||
c.gridx++;
|
||||
mainPanel.add(itisCode = new JTextField(6), c);
|
||||
mainPanel.add(itisCode, c);
|
||||
c.gridx ++;
|
||||
mainPanel.add(searchButton = new JButton("Find"));
|
||||
mainPanel.add(searchButton, c);
|
||||
|
||||
c.gridx ++;
|
||||
c.gridwidth = 1;
|
||||
mainPanel.add(latinName);
|
||||
|
||||
int w1 = 2;
|
||||
int w2 = 3;
|
||||
@ -50,21 +62,26 @@ public class SpeciesSubPanel {
|
||||
mainPanel.add(new JLabel("Call / sound type ", JLabel.RIGHT), c);
|
||||
c.gridx+= c.gridwidth;
|
||||
c.gridwidth = w2;
|
||||
mainPanel.add(callType = new JTextField(15), c);
|
||||
c.gridx = 0;
|
||||
c.gridy++;
|
||||
c.gridwidth = w1;
|
||||
mainPanel.add(new JLabel("Scientific name ", JLabel.RIGHT), c);
|
||||
c.gridx+= c.gridwidth;
|
||||
c.gridwidth = w2;
|
||||
mainPanel.add(latinName = new JTextField(15), c);
|
||||
c.gridx = 0;
|
||||
c.gridy++;
|
||||
c.gridwidth = w1;
|
||||
mainPanel.add(new JLabel("Common name ", JLabel.RIGHT), c);
|
||||
c.gridx+= c.gridwidth;
|
||||
c.gridwidth = w2;
|
||||
mainPanel.add(commonName = new JTextField(15), c);
|
||||
mainPanel.add(callType, c);
|
||||
c.gridx += c.gridwidth;
|
||||
c.gridwidth = 1;
|
||||
mainPanel.add(commonName, c);
|
||||
// c.gridx = 0;
|
||||
// c.gridy++;
|
||||
// c.gridwidth = w1;
|
||||
// mainPanel.add(new JLabel("Scientific name ", JLabel.RIGHT), c);
|
||||
// c.gridx+= c.gridwidth;
|
||||
// c.gridwidth = w2;
|
||||
// mainPanel.add(latinName, c);
|
||||
// c.gridx = 0;
|
||||
// c.gridy++;
|
||||
// c.gridwidth = w1;
|
||||
// mainPanel.add(new JLabel("Common name ", JLabel.RIGHT), c);
|
||||
// c.gridx+= c.gridwidth;
|
||||
// c.gridwidth = w2;
|
||||
// mainPanel.add(commonName = new JTextField(15), c);
|
||||
|
||||
callType.setText(aSpecies); // will get overwritten if the user choses something else.
|
||||
|
||||
pamguardName.setToolTipText("Internal name within PAMGuard module");
|
||||
itisCode.setToolTipText("ITIS species code");
|
||||
@ -72,6 +89,9 @@ public class SpeciesSubPanel {
|
||||
callType.setToolTipText("Descriptive name for call type or measurement");
|
||||
latinName.setToolTipText("Scientific name");
|
||||
commonName.setToolTipText("Common name");
|
||||
commonName.setEditable(false);
|
||||
// commonName.setEnabled(false);
|
||||
latinName.setEditable(false);
|
||||
|
||||
searchButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
@ -119,14 +139,20 @@ public class SpeciesSubPanel {
|
||||
public void setParams(SpeciesMapItem speciesMapItem) {
|
||||
if (speciesMapItem == null) {
|
||||
itisCode.setText(null);
|
||||
callType.setText(null);
|
||||
// callType.setText(null);
|
||||
latinName.setText(null);
|
||||
commonName.setText(null);
|
||||
return;
|
||||
}
|
||||
pamguardName.setText("\"" + speciesMapItem.getPamguardName() + "\"");
|
||||
itisCode.setText(String.format("%d", speciesMapItem.getItisCode()));
|
||||
callType.setText(speciesMapItem.getCallType());
|
||||
String callT = speciesMapItem.getCallType();
|
||||
if (callT != null && callT.length()>0) {
|
||||
callType.setText(speciesMapItem.getCallType());
|
||||
}
|
||||
else {
|
||||
callType.setText(speciesMapItem.getPamguardName());
|
||||
}
|
||||
latinName.setText(speciesMapItem.getLatinName());
|
||||
commonName.setText(speciesMapItem.getCommonName());
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import PamView.PamGui;
|
||||
import PamView.dialog.warn.WarnOnce;
|
||||
import PamView.tables.SwingTableColumnWidths;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
import nilus.DataSourceType;
|
||||
import nilus.DetectionEffortKind;
|
||||
import nilus.Detections;
|
||||
import nilus.GranularityType;
|
||||
@ -42,25 +43,25 @@ import tethys.niluswraps.PDetections;
|
||||
*
|
||||
*/
|
||||
public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTableObserver {
|
||||
|
||||
|
||||
private JPanel mainPanel;
|
||||
|
||||
|
||||
private JLabel dataBlockName;
|
||||
|
||||
private TableModel tableModel;
|
||||
|
||||
|
||||
private JTable table;
|
||||
|
||||
private PamDataBlock dataBlock;
|
||||
|
||||
|
||||
private StreamDetectionsSummary streamDetectionsSummary;
|
||||
|
||||
|
||||
public DatablockDetectionsPanel(TethysControl tethysControl) {
|
||||
super(tethysControl);
|
||||
mainPanel = new JPanel(new BorderLayout());
|
||||
mainPanel.add(BorderLayout.NORTH, dataBlockName = new JLabel("PAMGUard data stream", JLabel.LEFT));
|
||||
mainPanel.setBorder(new TitledBorder("Data stream Tethys Detections documents"));
|
||||
|
||||
|
||||
tableModel = new TableModel();
|
||||
table = new JTable(tableModel) {
|
||||
@Override
|
||||
@ -68,46 +69,46 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa
|
||||
return getToolTip(event);
|
||||
}
|
||||
|
||||
protected JTableHeader createDefaultTableHeader() {
|
||||
return new JTableHeader(columnModel) {
|
||||
public String getToolTipText(MouseEvent e) {
|
||||
return getToolTip(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected JTableHeader createDefaultTableHeader() {
|
||||
return new JTableHeader(columnModel) {
|
||||
public String getToolTipText(MouseEvent e) {
|
||||
return getToolTip(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
JScrollPane scrollPane = new JScrollPane(table);
|
||||
mainPanel.add(BorderLayout.CENTER, scrollPane);
|
||||
|
||||
|
||||
new SwingTableColumnWidths(tethysControl.getUnitName() + getClass().getName(), table);
|
||||
|
||||
|
||||
table.addMouseListener(new MouseActions());
|
||||
}
|
||||
|
||||
protected String getToolTip(MouseEvent event) {
|
||||
java.awt.Point p = event.getPoint();
|
||||
int rowIndex = table.rowAtPoint(p);
|
||||
// if (rowIndex < 0) {
|
||||
// return null;
|
||||
// }
|
||||
int colIndex = table.columnAtPoint(p);
|
||||
switch (colIndex) {
|
||||
case 0:
|
||||
return "Tethys Detections document name";
|
||||
case 1:
|
||||
return "Name of PAMGuard data stream";
|
||||
case 2:
|
||||
return "Effort period";
|
||||
case 3:
|
||||
return "Output granularity";
|
||||
case 4:
|
||||
return "Number of detection elements in document";
|
||||
case 5:
|
||||
return "Document abstract";
|
||||
|
||||
}
|
||||
return "No tip";
|
||||
java.awt.Point p = event.getPoint();
|
||||
int rowIndex = table.rowAtPoint(p);
|
||||
// if (rowIndex < 0) {
|
||||
// return null;
|
||||
// }
|
||||
int colIndex = table.columnAtPoint(p);
|
||||
switch (colIndex) {
|
||||
case 0:
|
||||
return "Tethys Detections document name";
|
||||
case 1:
|
||||
return "Name of PAMGuard data stream";
|
||||
case 2:
|
||||
return "Effort period";
|
||||
case 3:
|
||||
return "Output granularity";
|
||||
case 4:
|
||||
return "Number of detection elements in document";
|
||||
case 5:
|
||||
return "Document abstract";
|
||||
|
||||
}
|
||||
return "No tip";
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -122,7 +123,7 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa
|
||||
streamDetectionsSummary = getTethysControl().getDetectionsHandler().getStreamDetections(dataBlock);
|
||||
tableModel.fireTableDataChanged();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateState(TethysState tethysState) {
|
||||
if (dataBlock != null) {
|
||||
@ -146,55 +147,92 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void showPopupMenu(MouseEvent e) {
|
||||
int row = table.getSelectedRow();
|
||||
if (row < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int[] rows = table.getSelectedRows();
|
||||
|
||||
PDetections pDets = detectionsForRow(row);
|
||||
if (pDets == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
JPopupMenu popMenu = new JPopupMenu();
|
||||
|
||||
JMenuItem menuItem = new JMenuItem("Delete document " + pDets.detections.getId());
|
||||
menuItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
deleteDocument(pDets);
|
||||
}
|
||||
});
|
||||
popMenu.add(menuItem);
|
||||
|
||||
menuItem = new JMenuItem("Display document " + pDets.detections.getId());
|
||||
menuItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
displayDocument(pDets);
|
||||
}
|
||||
});
|
||||
popMenu.add(menuItem);
|
||||
|
||||
menuItem = new JMenuItem("Export document " + pDets.detections.getId());
|
||||
menuItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
exportDocument(pDets);
|
||||
}
|
||||
});
|
||||
popMenu.add(menuItem);
|
||||
|
||||
|
||||
|
||||
|
||||
if (rows.length == 1) {
|
||||
JMenuItem menuItem = new JMenuItem("Delete document " + pDets.detections.getId());
|
||||
menuItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
deleteDocument(pDets);
|
||||
}
|
||||
});
|
||||
popMenu.add(menuItem);
|
||||
|
||||
menuItem = new JMenuItem("Display document " + pDets.detections.getId());
|
||||
menuItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
displayDocument(pDets);
|
||||
}
|
||||
});
|
||||
popMenu.add(menuItem);
|
||||
|
||||
menuItem = new JMenuItem("Export document " + pDets.detections.getId());
|
||||
menuItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
exportDocument(pDets);
|
||||
}
|
||||
});
|
||||
popMenu.add(menuItem);
|
||||
}
|
||||
else if (rows.length > 0){
|
||||
JMenuItem menuItem = new JMenuItem("Delete multiple Detections documents");
|
||||
menuItem.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
deleteDocuments(rows);
|
||||
}
|
||||
|
||||
});
|
||||
popMenu.add(menuItem);
|
||||
}
|
||||
|
||||
|
||||
popMenu.show(e.getComponent(), e.getX(), e.getY());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void deleteDocuments(int[] rows) {
|
||||
String msg = String.format("Are you sure you want to delete %d Detections documents ?", rows.length);
|
||||
|
||||
int ans = WarnOnce.showWarning(PamGui.findComponentWindow(mainPanel), "Delete Document", msg, WarnOnce.OK_CANCEL_OPTION);
|
||||
if (ans != WarnOnce.OK_OPTION) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < rows.length; i++) {
|
||||
int row = rows[i];
|
||||
PDetections pDets = detectionsForRow(row);
|
||||
if (pDets == null) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
getTethysControl().getDbxmlConnect().deleteDocument(pDets.detections);
|
||||
} catch (TethysException e) {
|
||||
getTethysControl().showException(e);
|
||||
}
|
||||
}
|
||||
getTethysControl().exportedDetections(dataBlock);
|
||||
selectDataBlock(dataBlock); // force table update.
|
||||
}
|
||||
|
||||
protected void deleteDocument(PDetections pDets) {
|
||||
String msg = String.format("Are you sure you want to delete the Detections document %s ?", pDets.detections.getId());
|
||||
int ans = WarnOnce.showWarning(PamGui.findComponentWindow(mainPanel), "Delete Document", msg, WarnOnce.OK_CANCEL_OPTION);
|
||||
@ -212,12 +250,12 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa
|
||||
|
||||
private void displayDocument(PDetections pDets) {
|
||||
getTethysControl().displayDocument(Collection.Detections.collectionName(), pDets.detections.getId());
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void exportDocument(PDetections pDets) {
|
||||
getTethysControl().exportDocument(Collection.Detections.toString(), pDets.detections.getId());
|
||||
|
||||
|
||||
}
|
||||
|
||||
private PDetections detectionsForRow(int iRow) {
|
||||
@ -231,8 +269,8 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa
|
||||
}
|
||||
|
||||
private class TableModel extends AbstractTableModel {
|
||||
|
||||
private String[] colNames = {"Document", "Detector", "Effort", "Granularity", "Count", "Abstract"};
|
||||
|
||||
private String[] colNames = {"Document", "Detector", "Deployment", "Effort", "Granularity", "Count", "Abstract"};
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
@ -275,10 +313,18 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa
|
||||
}
|
||||
return pDets.dataBlock.getDataName();
|
||||
case 2:
|
||||
DataSourceType dataSource = dets.getDataSource();
|
||||
if (dataSource == null) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return dataSource.getDeploymentId();
|
||||
}
|
||||
case 3:
|
||||
XMLGregorianCalendar start = dets.getEffort().getStart();
|
||||
XMLGregorianCalendar stop = dets.getEffort().getEnd();
|
||||
return start + " to " + stop;
|
||||
case 3:
|
||||
case 4:
|
||||
List<DetectionEffortKind> kinds = dets.getEffort().getKind();
|
||||
if (kinds == null) {
|
||||
return null;
|
||||
@ -287,19 +333,19 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa
|
||||
if (kind.getGranularity() != null) {
|
||||
GranularityType granularity = kind.getGranularity();
|
||||
return PDeployment.formatGranularity(granularity);
|
||||
// if (granularity != null) {
|
||||
// return granularity.getValue();
|
||||
// }
|
||||
// if (granularity != null) {
|
||||
// return granularity.getValue();
|
||||
// }
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
return pDets.count;
|
||||
case 5:
|
||||
return pDets.count;
|
||||
case 6:
|
||||
return dets.getDescription().getAbstract();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
@ -22,13 +23,16 @@ import javax.swing.table.AbstractTableModel;
|
||||
|
||||
|
||||
import PamUtils.PamCalendar;
|
||||
import PamView.dialog.warn.WarnOnce;
|
||||
import PamView.panel.PamPanel;
|
||||
import PamView.panel.WestAlignedPanel;
|
||||
import PamView.tables.SwingTableColumnWidths;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
import dataMap.OfflineDataMap;
|
||||
import tethys.TethysControl;
|
||||
import tethys.TethysState;
|
||||
import tethys.TethysStateObserver;
|
||||
import tethys.niluswraps.PDeployment;
|
||||
import tethys.output.DatablockSynchInfo;
|
||||
import tethys.species.DataBlockSpeciesManager;
|
||||
|
||||
@ -43,6 +47,8 @@ public class DatablockSynchPanel extends TethysGUIPanel {
|
||||
private ArrayList<DatablockSynchInfo> dataBlockSynchInfo;
|
||||
|
||||
private ArrayList<StreamTableObserver> tableObservers = new ArrayList<>();
|
||||
|
||||
private JButton exportButton;
|
||||
|
||||
public DatablockSynchPanel(TethysControl tethysControl) {
|
||||
super(tethysControl);
|
||||
@ -53,8 +59,22 @@ public class DatablockSynchPanel extends TethysGUIPanel {
|
||||
new SwingTableColumnWidths(tethysControl.getUnitName()+"SynchTable", synchTable);
|
||||
JScrollPane scrollPane = new JScrollPane(synchTable);
|
||||
mainPanel.add(BorderLayout.CENTER, scrollPane);
|
||||
PamPanel ctrlPanel = new PamPanel(new BorderLayout());
|
||||
exportButton = new JButton("Export ...");
|
||||
ctrlPanel.add(BorderLayout.WEST, exportButton);
|
||||
mainPanel.add(BorderLayout.NORTH, ctrlPanel);
|
||||
|
||||
|
||||
synchTable.addMouseListener(new MouseActions());
|
||||
synchTable.addKeyListener(new KeyActions());
|
||||
|
||||
exportButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
exportData();
|
||||
}
|
||||
});
|
||||
enableExportButton();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -106,9 +126,30 @@ public class DatablockSynchPanel extends TethysGUIPanel {
|
||||
DatablockSynchInfo synchInfo = dataBlockSynchInfo.get(row);
|
||||
// datablockDetectionsPanel.setDataBlock(synchInfo.getDataBlock());
|
||||
notifyObservers(synchInfo.getDataBlock());
|
||||
enableExportButton();
|
||||
return row;
|
||||
}
|
||||
|
||||
protected void exportData() {
|
||||
int[] rows = synchTable.getSelectedRows();
|
||||
if (rows == null || rows.length != 1) {
|
||||
WarnOnce.showWarning("Data selection", "you must select a single data block for export", WarnOnce.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
PamDataBlock dataBlock = dataBlockSynchInfo.get(rows[0]).getDataBlock();
|
||||
getTethysControl().getDetectionsHandler().exportDataBlock(dataBlock);
|
||||
}
|
||||
|
||||
private void enableExportButton() {
|
||||
int[] rows = synchTable.getSelectedRows();
|
||||
boolean en = rows != null && rows.length == 1;
|
||||
ArrayList<PDeployment> deployments = getTethysControl().getDeploymentHandler().getMatchedDeployments();
|
||||
if (deployments == null || deployments.size() == 0) {
|
||||
en = false;
|
||||
}
|
||||
exportButton.setEnabled(en);
|
||||
}
|
||||
|
||||
public void showPopup(MouseEvent e, int row) {
|
||||
DatablockSynchInfo synchInfo = dataBlockSynchInfo.get(row);
|
||||
if (synchInfo == null) {
|
||||
@ -133,6 +174,15 @@ public class DatablockSynchPanel extends TethysGUIPanel {
|
||||
|
||||
@Override
|
||||
public void updateState(TethysState tethysState) {
|
||||
switch (tethysState.stateType) {
|
||||
case DELETEDATA:
|
||||
case EXPORTRDATA:
|
||||
case NEWPROJECTSELECTION:
|
||||
// dataBlockSynchInfo = null;
|
||||
// getSychInfos();
|
||||
// getTethysControl().coun
|
||||
}
|
||||
|
||||
synchTableModel.fireTableDataChanged();
|
||||
selectRow();
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import tethys.TethysControl;
|
||||
import tethys.species.DataBlockSpeciesManager;
|
||||
import tethys.swing.export.DetectionsExportWizard;
|
||||
|
||||
@Deprecated
|
||||
public class DetectionsExportPanel extends TethysGUIPanel implements StreamTableObserver {
|
||||
|
||||
private JPanel mainPanel;
|
||||
@ -28,7 +29,7 @@ public class DetectionsExportPanel extends TethysGUIPanel implements StreamTable
|
||||
|
||||
private PamDataBlock selectedDataBlock;
|
||||
|
||||
public DetectionsExportPanel(TethysControl tethysControl) {
|
||||
private DetectionsExportPanel(TethysControl tethysControl) {
|
||||
super(tethysControl);
|
||||
mainPanel = new PamAlignmentPanel(BorderLayout.NORTH);
|
||||
mainPanel.setLayout(new GridBagLayout());
|
||||
|
@ -222,20 +222,49 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
if (checkDetections(depl.deployment) == false) {
|
||||
continue;
|
||||
}
|
||||
boolean gone = getTethysControl().getDbxmlConnect().deleteDocument(depl.deployment);
|
||||
} catch (TethysException e) {
|
||||
getTethysControl().showException(e);
|
||||
}
|
||||
}
|
||||
getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER, Collection.Deployments));
|
||||
getTethysControl().sendStateUpdate(new TethysState(StateType.DELETEDATA, Collection.Deployments));
|
||||
}
|
||||
|
||||
protected void exportDeployment(PDeployment pDeployment) {
|
||||
getTethysControl().exportDocument(Collection.Deployments.collectionName(), pDeployment.deployment.getId());
|
||||
}
|
||||
|
||||
protected void displayDeployment(PDeployment pDeployment) {
|
||||
getTethysControl().displayDocument(Collection.Deployments.collectionName(), pDeployment.deployment.getId());
|
||||
/**
|
||||
* Check for detections associated with this deployment. they must be deleted first.
|
||||
* @param deployment
|
||||
* @return true if there are no Detections or if they are sucessfully removed as well.
|
||||
*/
|
||||
private boolean checkDetections(Deployment deployment) {
|
||||
// get any deployment documents that associate with this deployment.
|
||||
ArrayList<String> detectionDocs = getTethysControl().getDbxmlQueries().getDetectionsDocuments(deployment.getId());
|
||||
if (detectionDocs == null || detectionDocs.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
String msg = String.format("<html>One or more Detections documents are associated with Deployment %s<br>", deployment.getId());
|
||||
for (String str : detectionDocs) {
|
||||
msg += String.format("<br>%s", str);
|
||||
}
|
||||
msg += String.format("<br><br>You must delete these prior to deleting the Deploymen. Go ahead and delete ?");
|
||||
int ans = WarnOnce.showWarning(getTethysControl().getGuiFrame(), "Existing Detections documents !" , msg, WarnOnce.OK_CANCEL_OPTION);
|
||||
if (ans == WarnOnce.CANCEL_OPTION) {
|
||||
return false;
|
||||
}
|
||||
// OK, so delete all the Detections too !!!
|
||||
boolean errors = false;
|
||||
for (String str : detectionDocs) {
|
||||
try {
|
||||
boolean gone = getTethysControl().getDbxmlConnect().removeDocument(Collection.Detections, str);
|
||||
} catch (TethysException e) {
|
||||
getTethysControl().showException(e);
|
||||
errors = true;
|
||||
}
|
||||
}
|
||||
|
||||
return !errors;
|
||||
}
|
||||
|
||||
protected void deleteDeployment(PDeployment pDeployment) {
|
||||
@ -248,12 +277,23 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel {
|
||||
if (ans == WarnOnce.CANCEL_OPTION) {
|
||||
return;
|
||||
}
|
||||
if (checkDetections(dep) == false) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
boolean gone = getTethysControl().getDbxmlConnect().deleteDocument(dep);
|
||||
} catch (TethysException e) {
|
||||
getTethysControl().showException(e);
|
||||
}
|
||||
getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER, Collection.Deployments));
|
||||
getTethysControl().sendStateUpdate(new TethysState(StateType.DELETEDATA, Collection.Deployments));
|
||||
}
|
||||
|
||||
protected void exportDeployment(PDeployment pDeployment) {
|
||||
getTethysControl().exportDocument(Collection.Deployments.collectionName(), pDeployment.deployment.getId());
|
||||
}
|
||||
|
||||
protected void displayDeployment(PDeployment pDeployment) {
|
||||
getTethysControl().displayDocument(Collection.Deployments.collectionName(), pDeployment.deployment.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -320,7 +360,7 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel {
|
||||
|
||||
private class TableModel extends AbstractTableModel {
|
||||
|
||||
private String[] columnNames = {"Id", "Select", "Start", "Stop", "Gap", "Duration", "Cycle", "Tethys Deployment"};
|
||||
private String[] columnNames = {"Id", "Select", "Start", "Stop", "Gap", "Duration", "Cycle", "Tethys Deployment", "Deployment Effort"};
|
||||
|
||||
private static final int SELECTCOLUMN = 1;
|
||||
|
||||
@ -369,6 +409,7 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel {
|
||||
}
|
||||
|
||||
private Object getValueAt(RecordingPeriod period, int rowIndex, int columnIndex) {
|
||||
PDeployment deployment = period.getMatchedTethysDeployment();
|
||||
switch (columnIndex) {
|
||||
case 0:
|
||||
return rowIndex;
|
||||
@ -383,8 +424,18 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel {
|
||||
// long t2 = TethysTimeFuncs.millisFromGregorianXML(deplInfo.recoveryDetails.getAudioTimeStamp());
|
||||
return PamCalendar.formatDuration(period.getRecordStop()-period.getRecordStart());
|
||||
case 7:
|
||||
PDeployment deployment = period.getMatchedTethysDeployment();
|
||||
return makeDeplString(period, deployment);
|
||||
if (deployment == null) {
|
||||
return null;
|
||||
}
|
||||
return deployment.deployment.getId();
|
||||
// return makeDeplString(period, deployment);
|
||||
case 8:
|
||||
if (deployment == null) {
|
||||
return null;
|
||||
}
|
||||
return String.format("%s to %s", PamCalendar.formatDBDateTime(deployment.getAudioStart()),
|
||||
PamCalendar.formatDBDateTime(deployment.getAudioEnd()));
|
||||
|
||||
case SELECTCOLUMN:
|
||||
// return selectBoxes[rowIndex];
|
||||
return period.isSelected();
|
||||
|
@ -25,7 +25,7 @@ public class TethysMainPanel extends TethysGUIPanel {
|
||||
|
||||
private DatablockDetectionsPanel datablockDetectionsPanel;
|
||||
|
||||
private DetectionsExportPanel detectionsExportPanel;
|
||||
// private DetectionsExportPanel detectionsExportPanel;
|
||||
|
||||
private CalibrationsMainPanel calibrationPanel;
|
||||
|
||||
@ -37,8 +37,8 @@ public class TethysMainPanel extends TethysGUIPanel {
|
||||
datablockDetectionsPanel = new DatablockDetectionsPanel(tethysControl);
|
||||
datablockSynchPanel = new DatablockSynchPanel(tethysControl);
|
||||
deploymentsPanel = new DeploymentsPanel(tethysControl);
|
||||
detectionsExportPanel = new DetectionsExportPanel(tethysControl);
|
||||
datablockSynchPanel.addTableObserver(detectionsExportPanel);
|
||||
// detectionsExportPanel = new DetectionsExportPanel(tethysControl);
|
||||
// datablockSynchPanel.addTableObserver(detectionsExportPanel);
|
||||
datablockSynchPanel.addTableObserver(datablockDetectionsPanel);
|
||||
calibrationPanel = new CalibrationsMainPanel(tethysControl, tethysControl.getCalibrationHandler());
|
||||
|
||||
@ -62,7 +62,7 @@ public class TethysMainPanel extends TethysGUIPanel {
|
||||
southwestSplit.add(datablockSynchPanel.getComponent());
|
||||
southwestSplit.add(southEastPanel);
|
||||
southEastPanel.add(datablockDetectionsPanel.getComponent(), BorderLayout.CENTER);
|
||||
southEastPanel.add(detectionsExportPanel.getComponent(), BorderLayout.WEST);
|
||||
// southEastPanel.add(detectionsExportPanel.getComponent(), BorderLayout.WEST);
|
||||
splitPane.add(southwestSplit);
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
// these only work if called after display is visible
|
||||
|
@ -27,6 +27,7 @@ public class XMLStringView extends PamDialog {
|
||||
textArea.setCaretPosition(0);
|
||||
|
||||
getCancelButton().setVisible(false);
|
||||
setModal(false);
|
||||
}
|
||||
|
||||
public static void showDialog(Window parent, String collection, String documentId, String xmlString) {
|
||||
|
128
src/tethys/swing/export/DeploymentPeriodPanel.java
Normal file
128
src/tethys/swing/export/DeploymentPeriodPanel.java
Normal file
@ -0,0 +1,128 @@
|
||||
package tethys.swing.export;
|
||||
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import PamUtils.PamCalendar;
|
||||
import PamView.dialog.PamDialog;
|
||||
import PamView.dialog.PamGridBagContraints;
|
||||
import metadata.PamguardMetaData;
|
||||
import nilus.Deployment;
|
||||
import nilus.DeploymentRecoveryDetails;
|
||||
import tethys.TethysTimeFuncs;
|
||||
|
||||
public class DeploymentPeriodPanel {
|
||||
|
||||
private JPanel mainPanel;
|
||||
private JTextField deploymentStart, deploymentEnd;
|
||||
private JRadioButton useThese, useAudio;
|
||||
private Window parentFrame;
|
||||
|
||||
public DeploymentPeriodPanel(Window parentFrame) {
|
||||
super();
|
||||
this.parentFrame = parentFrame;
|
||||
mainPanel = new JPanel(new GridBagLayout());
|
||||
ButtonGroup bg = new ButtonGroup();
|
||||
useThese = new JRadioButton("Use fixed deployment and recovery times below");
|
||||
useAudio = new JRadioButton("Use start and end times of collected audio data");
|
||||
bg.add(useThese);
|
||||
bg.add(useAudio);
|
||||
useThese.setToolTipText("This is useful if recording started before a device was first deployed as is often the case for moored systems");
|
||||
deploymentStart = new JTextField(15);
|
||||
deploymentEnd = new JTextField(15);
|
||||
|
||||
GridBagConstraints c = new PamGridBagContraints();
|
||||
c.gridwidth = 2;
|
||||
mainPanel.add(useAudio, c);
|
||||
c.gridy++;
|
||||
mainPanel.add(useThese, c);
|
||||
c.gridy++;
|
||||
c.gridwidth = 1;
|
||||
mainPanel.add(new JLabel("Deployment start ", JLabel.RIGHT), c);
|
||||
c.gridx++;
|
||||
mainPanel.add(deploymentStart, c);
|
||||
c.gridy++;
|
||||
c.gridx = 0;
|
||||
mainPanel.add(new JLabel("Deployment end ", JLabel.RIGHT), c);
|
||||
c.gridx++;
|
||||
mainPanel.add(deploymentEnd, c);
|
||||
|
||||
useThese.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
enableControls();
|
||||
}
|
||||
});
|
||||
useAudio.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
enableControls();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void enableControls() {
|
||||
deploymentStart.setEditable(useThese.isSelected());
|
||||
deploymentEnd.setEditable(useThese.isSelected());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mainPanel
|
||||
*/
|
||||
public JPanel getMainPanel() {
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
public void setParams(PamguardMetaData metaData) {
|
||||
useThese.setSelected(metaData.useAudioForDeploymentTimes == false);
|
||||
useAudio.setSelected(metaData.useAudioForDeploymentTimes);
|
||||
|
||||
enableControls();
|
||||
|
||||
Deployment deployment = metaData.getDeployment();
|
||||
if (deployment == null) {
|
||||
return;
|
||||
}
|
||||
DeploymentRecoveryDetails drl = deployment.getDeploymentDetails();
|
||||
Long millis = TethysTimeFuncs.millisFromGregorianXML(drl.getTimeStamp());
|
||||
if (millis != null) {
|
||||
deploymentStart.setText(PamCalendar.formatDBDateTime(millis));
|
||||
}
|
||||
drl = deployment.getRecoveryDetails();
|
||||
millis = TethysTimeFuncs.millisFromGregorianXML(drl.getTimeStamp());
|
||||
if (millis != null) {
|
||||
deploymentEnd.setText(PamCalendar.formatDBDateTime(millis));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getParams(PamguardMetaData metaData) {
|
||||
Deployment deployment = metaData.getDeployment();
|
||||
metaData.useAudioForDeploymentTimes = useAudio.isSelected();
|
||||
if (metaData.useAudioForDeploymentTimes) {
|
||||
return true;
|
||||
}
|
||||
Long millis = PamCalendar.millisFromDateString(deploymentStart.getText(), true);
|
||||
if (millis == null) {
|
||||
return PamDialog.showWarning(parentFrame, "Bad data string", "unable to read date strin for deployment start");
|
||||
}
|
||||
deployment.getDeploymentDetails().setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(millis));
|
||||
|
||||
millis = PamCalendar.millisFromDateString(deploymentEnd.getText(), true);
|
||||
if (millis == null) {
|
||||
return PamDialog.showWarning(parentFrame, "Bad data string", "unable to read date strin for deployment end");
|
||||
}
|
||||
deployment.getRecoveryDetails().setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(millis));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -24,6 +24,7 @@ import tethys.pamdata.TethysDataProvider;
|
||||
|
||||
public class DetectionsExportWizard extends PamWizard {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private PamDataBlock dataBlock;
|
||||
private CardLayout cardLayout;
|
||||
private GranularityCard granularityCard;
|
||||
@ -33,6 +34,7 @@ public class DetectionsExportWizard extends PamWizard {
|
||||
private AlgorithmCard algorithmCard;
|
||||
private ExportWorkerCard exportWorkerCard;
|
||||
private TethysDataProvider tethysDataProvider;
|
||||
private ParameterCard parameterCard;
|
||||
|
||||
private DetectionsExportWizard(Window parentFrame, TethysControl tethysControl, PamDataBlock dataBlock) {
|
||||
super(parentFrame, "Detections Export");
|
||||
@ -48,6 +50,7 @@ public class DetectionsExportWizard extends PamWizard {
|
||||
addCard(algorithmCard = new AlgorithmCard(this, tethysControl, dataBlock));
|
||||
addCard(granularityCard = new GranularityCard(this, tethysControl, dataBlock));
|
||||
addCard(descriptionCard = new DescriptionCard(this, tethysControl));
|
||||
addCard(parameterCard = new ParameterCard(tethysControl, this, dataBlock));
|
||||
addCard(exportWorkerCard = new ExportWorkerCard(this, tethysControl, dataBlock));
|
||||
|
||||
moveFirst();
|
||||
@ -73,15 +76,47 @@ public class DetectionsExportWizard extends PamWizard {
|
||||
|
||||
@Override
|
||||
public void setCardParams(PamWizardCard wizardCard) {
|
||||
wizardCard.setParams(streamExportParams);
|
||||
// return wizardCard.getParams(streamExportParams);
|
||||
if (wizardCard == granularityCard) {
|
||||
granularityCard.setParams(streamExportParams);
|
||||
}
|
||||
if (wizardCard == descriptionCard) {
|
||||
descriptionCard.setParams(streamExportParams.getNilusDetectionDescription());
|
||||
}
|
||||
if (wizardCard == algorithmCard) {
|
||||
algorithmCard.setParams(streamExportParams);
|
||||
}
|
||||
if (wizardCard == exportWorkerCard) {
|
||||
exportWorkerCard.setParams(streamExportParams);
|
||||
}
|
||||
try {
|
||||
wizardCard.setParams(streamExportParams);
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getCardParams(PamWizardCard wizardCard) {
|
||||
// return wizardCard.getParams(streamExportParams);
|
||||
if (wizardCard == granularityCard) {
|
||||
return granularityCard.getParams(streamExportParams);
|
||||
}
|
||||
if (wizardCard == descriptionCard) {
|
||||
return descriptionCard.getParams(streamExportParams.getNilusDetectionDescription());
|
||||
}
|
||||
if (wizardCard == algorithmCard) {
|
||||
return algorithmCard.getParams(streamExportParams);
|
||||
}
|
||||
if (wizardCard == exportWorkerCard) {
|
||||
return exportWorkerCard.getParams(streamExportParams);
|
||||
}
|
||||
return wizardCard.getParams(streamExportParams);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void cancelButtonPressed() {
|
||||
// TODO Auto-generated method stub
|
||||
|
@ -133,7 +133,10 @@ public class ExportWorkerCard extends ExportWizardCard implements DetectionExpor
|
||||
itemCount.setText("0");
|
||||
projectedCount.setText(String.format("%d", progress.exportCount));
|
||||
skipCount.setText(String.format("%d", progress.skipCount));
|
||||
long perc = (progress.exportCount+progress.skipCount) * 100 / progress.totalUnits;
|
||||
long perc = 100;
|
||||
if (progress.totalUnits>0) {
|
||||
perc = (progress.exportCount+progress.skipCount) * 100 / progress.totalUnits;
|
||||
}
|
||||
progressBar.setValue((int) perc);
|
||||
}
|
||||
else if (progress.totalUnits > 0) {
|
||||
|
67
src/tethys/swing/export/ParameterCard.java
Normal file
67
src/tethys/swing/export/ParameterCard.java
Normal file
@ -0,0 +1,67 @@
|
||||
package tethys.swing.export;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
import PamView.dialog.PamGridBagContraints;
|
||||
import PamView.panel.WestAlignedPanel;
|
||||
import PamView.wizard.PamWizard;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
import tethys.TethysControl;
|
||||
import tethys.deployment.DeploymentHandler;
|
||||
import tethys.detection.DetectionsHandler;
|
||||
import tethys.output.StreamExportParams;
|
||||
import tethys.output.TethysExportParams;
|
||||
|
||||
public class ParameterCard extends ExportWizardCard {
|
||||
|
||||
private DetectionsHandler detectionsHandler;
|
||||
|
||||
private JRadioButton[] optButtons;
|
||||
|
||||
public ParameterCard(TethysControl tethysControl, PamWizard pamWizard, PamDataBlock dataBlock) {
|
||||
super(tethysControl, pamWizard, "Algorithm Parameters", dataBlock);
|
||||
detectionsHandler = tethysControl.getDetectionsHandler();
|
||||
String[] optionStrings = TethysExportParams.paramsOptNames;
|
||||
optButtons = new JRadioButton[optionStrings.length];
|
||||
JPanel buttonPanel = new JPanel(new GridBagLayout());
|
||||
GridBagConstraints c = new PamGridBagContraints();
|
||||
ButtonGroup bg = new ButtonGroup();
|
||||
for (int i = 0; i < optButtons.length; i++) {
|
||||
optButtons[i] = new JRadioButton(optionStrings[i]);
|
||||
bg.add(optButtons[i]);
|
||||
buttonPanel.add(optButtons[i], c);
|
||||
c.gridy++;
|
||||
}
|
||||
this.setLayout(new BorderLayout());
|
||||
this.add(BorderLayout.NORTH, new WestAlignedPanel(buttonPanel));
|
||||
this.setBorder(new TitledBorder("Algorithm parameters export"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getParams(StreamExportParams cardParams) {
|
||||
TethysExportParams exportParams = getTethysControl().getTethysExportParams();
|
||||
for (int i = 0; i < optButtons.length; i++) {
|
||||
if (optButtons[i].isSelected()) {
|
||||
exportParams.detectorParameterOutput = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return getPamWizard().showWarning("Select a parameters export option");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParams(StreamExportParams cardParams) {
|
||||
TethysExportParams exportParams = getTethysControl().getTethysExportParams();
|
||||
for (int i = 0; i < optButtons.length; i++) {
|
||||
optButtons[i].setSelected(i == exportParams.detectorParameterOutput);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user