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:
Douglas Gillespie 2023-12-15 17:49:39 +00:00
parent 3059e087ac
commit 2e29e9cd95
32 changed files with 1371 additions and 1000 deletions

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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));

View File

@ -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;
}

View File

@ -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");

View File

@ -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() {

View File

@ -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;
}
}

View File

@ -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));
}

View 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;
}
}

View 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());
}
});
}
}

View File

@ -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());

View File

@ -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");

View File

@ -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);
}
}

View File

@ -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);
//
// }
}

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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());
}
}
}

View File

@ -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;
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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());
}

View File

@ -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;
}
}
}

View File

@ -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();
}

View File

@ -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());

View File

@ -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();

View File

@ -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

View File

@ -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) {

View 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;
}
}

View File

@ -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

View File

@ -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) {

View 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);
}
}
}