Export wizard for detections
This commit is contained in:
Douglas Gillespie 2023-03-31 19:07:02 +01:00
parent 4be259b76b
commit 573785d98f
21 changed files with 1352 additions and 295 deletions

View File

@ -23,6 +23,7 @@ package PamController;
import java.awt.Component; import java.awt.Component;
import java.awt.Frame; import java.awt.Frame;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JMenu; import javax.swing.JMenu;
@ -39,7 +40,9 @@ import org.w3c.dom.Element;
import PamController.status.ModuleStatus; import PamController.status.ModuleStatus;
import PamController.status.ModuleStatusManager; import PamController.status.ModuleStatusManager;
import PamController.status.ProcessCheck; import PamController.status.ProcessCheck;
import PamModel.PamModel;
import PamModel.PamModuleInfo; import PamModel.PamModuleInfo;
import PamModel.PamPluginInterface;
import PamView.ClipboardCopier; import PamView.ClipboardCopier;
import PamView.PamGui; import PamView.PamGui;
import PamView.PamSidePanel; import PamView.PamSidePanel;
@ -863,5 +866,22 @@ public abstract class PamControlledUnit implements SettingsNameProvider {
public int getInstanceIndex() { public int getInstanceIndex() {
return instanceIndex; return instanceIndex;
} }
/**
* Get detail if this is a plugin.
* @return plugin detail, or null if it's not a plugin.
*/
public PamPluginInterface getPlugin() {
List<PamPluginInterface> pluginList = ((PamModel) PamController.getInstance().getModelInterface()).getPluginList();
if (pluginList == null) {
return null;
}
for (PamPluginInterface plugin : pluginList) {
if (plugin.getClassName().equals(this.getClass().getName())) {
return plugin;
}
}
return null;
}
} }

View File

@ -361,6 +361,28 @@ abstract public class OfflineDataMap<TmapPoint extends OfflineDataMapPoint> {
} }
} }
/**
* Get the start time of the first datamap point or Long.minval
* @return
*/
public long getMapStartTime() {
if (mapPoints == null || mapPoints.size() == 0) {
return Long.MIN_VALUE;
}
return mapPoints.get(0).getStartTime();
}
/**
* Get the start time of the first datamap point or Long.minval
* @return
*/
public long getMapEndTime() {
if (mapPoints == null || mapPoints.size() == 0) {
return Long.MIN_VALUE;
}
return mapPoints.get(mapPoints.size()-1).getEndTime();
}
/** /**
* @return the lowestPoint * @return the lowestPoint
*/ */

View File

@ -71,6 +71,7 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
private ArrayList<DatablockSynchInfo> dataBlockSynchInfos; private ArrayList<DatablockSynchInfo> dataBlockSynchInfos;
private DeploymentHandler deploymentHandler; private DeploymentHandler deploymentHandler;
private DetectionsHandler detectionsHandler;
public TethysControl(String unitName) { public TethysControl(String unitName) {
super(unitType, unitName); super(unitType, unitName);
@ -78,6 +79,7 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
dbxmlConnect = new DBXMLConnect(this); dbxmlConnect = new DBXMLConnect(this);
dbxmlQueries = new DBXMLQueries(this, dbxmlConnect); dbxmlQueries = new DBXMLQueries(this, dbxmlConnect);
deploymentHandler = new DeploymentHandler(this); deploymentHandler = new DeploymentHandler(this);
detectionsHandler = new DetectionsHandler(this);
serverCheckTimer = new Timer(10000, new ActionListener() { serverCheckTimer = new Timer(10000, new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
@ -111,14 +113,14 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
@Override @Override
public JMenuItem createFileMenu(JFrame parentFrame) { public JMenuItem createFileMenu(JFrame parentFrame) {
JMenu tethysMenu = new JMenu("Tethys"); JMenu tethysMenu = new JMenu("Tethys");
JMenuItem tethysExport = new JMenuItem("Export ..."); // JMenuItem tethysExport = new JMenuItem("Export ...");
tethysMenu.add(tethysExport); // tethysMenu.add(tethysExport);
tethysExport.addActionListener(new ActionListener() { // tethysExport.addActionListener(new ActionListener() {
@Override // @Override
public void actionPerformed(ActionEvent e) { // public void actionPerformed(ActionEvent e) {
tethysExport(parentFrame); // tethysExport(parentFrame);
} // }
}); // });
JMenuItem openClient = new JMenuItem("Open client in browser"); JMenuItem openClient = new JMenuItem("Open client in browser");
openClient.addActionListener(new ActionListener() { openClient.addActionListener(new ActionListener() {
@Override @Override
@ -430,4 +432,8 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
return deploymentHandler; return deploymentHandler;
} }
public DetectionsHandler getDetectionsHandler() {
return detectionsHandler;
}
} }

View File

@ -25,7 +25,7 @@ public class TethysMenuActions {
} }
public void deploymentMouseActions(MouseEvent e, PDeployment pDeployment) { public void deploymentMouseActions(MouseEvent e, PDeployment pDeployment) {
ArrayList<String> detDocNames = tethysControl.getDbxmlQueries().getDetectionsDocsIds(pDeployment.deployment.getId()); ArrayList<String> detDocNames = tethysControl.getDbxmlQueries().getDetectionsDocuments(pDeployment.deployment.getId());
// System.out.println("Detections for deployment " + pDeployment.deployment.getId()); // System.out.println("Detections for deployment " + pDeployment.deployment.getId());
// for (String detName : detDocNames) { // for (String detName : detDocNames) {
// System.out.println(detName); // System.out.println(detName);

View File

@ -1,5 +1,7 @@
package tethys; package tethys;
import tethys.detection.DetectionExportProgress;
/** /**
* Basis for a message system which will get passed around whenever something happens in * Basis for a message system which will get passed around whenever something happens in
* Tethys, whether it be a new connection, progress during data output, etc. * Tethys, whether it be a new connection, progress during data output, etc.
@ -12,13 +14,24 @@ public class TethysState {
TRANSFERDATA, // data have been transferred from PAMGuard to Tethys TRANSFERDATA, // data have been transferred from PAMGuard to Tethys
NEWPROJECTSELECTION, // a new Tethys project has been selected in the GUI NEWPROJECTSELECTION, // a new Tethys project has been selected in the GUI
NEWPAMGUARDSELECTION, // new PAMGuard data are available (called once on first load) NEWPAMGUARDSELECTION, // new PAMGuard data are available (called once on first load)
UPDATEMETADATA // META Data being prepared for output have changed (so may be able to enable output!) UPDATEMETADATA, // META Data being prepared for output have changed (so may be able to enable output!)
EXPORTING // currently exporting data. may be a while ...
}; };
public StateType stateType; public StateType stateType;
private Object stateObject;
public TethysState(StateType stateType) { public TethysState(StateType stateType) {
super(); super();
this.stateType = stateType; this.stateType = stateType;
} }
public TethysState(StateType stateType, Object stateObject) {
this.stateType = stateType;
this.stateObject = stateObject;
}
public Object getStateObject() {
return stateObject;
}
} }

View File

@ -1,5 +1,16 @@
package tethys.dbxml; package tethys.dbxml;
import java.io.IOException;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class DBQueryResult { public class DBQueryResult {
public long queryTimeMillis; public long queryTimeMillis;
@ -23,4 +34,29 @@ public class DBQueryResult {
this.queryException = queryException; this.queryException = queryException;
} }
/**
* Get the result as an XML document.
* @return XML document
* @throws ParserConfigurationException
* @throws SAXException
* @throws IOException
*/
public Document getDocument() throws ParserConfigurationException, SAXException, IOException {
if (queryResult == null) {
return null;
}
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//API to obtain DOM Document instance
DocumentBuilder builder = null;
//Create DocumentBuilder with default configuration
builder = factory.newDocumentBuilder();
//Parse the content to Document object
Document doc = builder.parse(new InputSource(new StringReader(queryResult)));
return doc;
}
} }

View File

@ -125,6 +125,7 @@ public class DBXMLConnect {
catch (Exception e) { catch (Exception e) {
System.out.printf("Error deleting %s %s: %s\n", collection, docId, e.getMessage()); System.out.printf("Error deleting %s %s: %s\n", collection, docId, e.getMessage());
} }
forceFlush();
return result == null; return result == null;
} }
@ -164,10 +165,28 @@ public class DBXMLConnect {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
// System.out.println(fileError);
return fileError; return fileError;
} }
/*
* force a fluch by sending a dummy document to th eimporter which will rail, but ...
*/
private void forceFlush() {
TethysExportParams params = new TethysExportParams();
String fileError = null;
try {
fileError = Importer.ImportFiles(params.getFullServerName(), "NoCollection",
new String[] { "ThereIsNoFileE" }, "", "", false);
}
catch (Exception e) {
}
// System.out.println(fileError);
}
/** /**
* Get a temp folder to hold xml output. This will be the standard * Get a temp folder to hold xml output. This will be the standard
* temp folder + /PAMGuardTethys. Files will be left here until PAMGUard * temp folder + /PAMGuardTethys. Files will be left here until PAMGUard
@ -266,7 +285,7 @@ public class DBXMLConnect {
* @return * @return
*/ */
public boolean deleteDeployment(String deploymentId) { public boolean deleteDeployment(String deploymentId) {
ArrayList<String> detDocNames = tethysControl.getDbxmlQueries().getDetectionsDocsIds(deploymentId); ArrayList<String> detDocNames = tethysControl.getDbxmlQueries().getDetectionsDocuments(deploymentId);
JerseyClient jerseyClient = getJerseyClient(); JerseyClient jerseyClient = getJerseyClient();
Queries queries = null; Queries queries = null;
String result; String result;
@ -324,6 +343,7 @@ public class DBXMLConnect {
} }
return new ServerStatus(ok, null); return new ServerStatus(ok, null);
} }
// add whatever calls are necessary ... // add whatever calls are necessary ...

View File

@ -1,5 +1,6 @@
package tethys.dbxml; package tethys.dbxml;
import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -7,12 +8,14 @@ import java.util.Collections;
import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import PamController.settings.output.xml.PamguardXMLWriter; import PamController.settings.output.xml.PamguardXMLWriter;
import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataBlock;
@ -21,6 +24,8 @@ import dbxml.Queries;
import nilus.Deployment; import nilus.Deployment;
import nilus.Deployment.Instrument; import nilus.Deployment.Instrument;
import nilus.DeploymentRecoveryDetails; import nilus.DeploymentRecoveryDetails;
import nilus.DescriptionType;
import nilus.Detections;
import nilus.Helper; import nilus.Helper;
import tethys.TethysControl; import tethys.TethysControl;
import tethys.TethysTimeFuncs; import tethys.TethysTimeFuncs;
@ -137,7 +142,9 @@ public class DBXMLQueries {
} }
/** /**
* Get some basic (not all) data for deployments associated with a project. * Get some basic (not all) data for deployments associated with a project. Note that
* this may include deployments which are NOT part of the current dataset. That requires
* a search on Instrument as well.
* @param projectName * @param projectName
* @return * @return
*/ */
@ -212,12 +219,18 @@ public class DBXMLQueries {
return deployments; return deployments;
} }
public int countData(PamDataBlock dataBlock, String deploymentId) { /**
* Get a list of Detections documents which associate with a datablock and a deploymentId.
* @param dataBlock
* @param deploymentId
* @return
*/
public ArrayList<String> getDetectionsDocuments(PamDataBlock dataBlock, String deploymentId) {
/** /**
* first query for Detections documents associated with this deployment and datablock. * first query for Detections documents associated with this deployment and datablock.
*/ */
String queryNoDepl = "{\"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\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Description/Method\",\"LongDataName\"],\"optype\":\"binary\"}],\"enclose\":1}"; String queryNoDepl = "{\"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\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Algorithm/Software\",\"LongDataName\"],\"optype\":\"binary\"}],\"enclose\":1}";
String queryWithDepl = "{\"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\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Description/Method\",\"LongDataName\"],\"optype\":\"binary\"},{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"TheDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}"; String queryWithDepl = "{\"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\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Algorithm/Software\",\"LongDataName\"],\"optype\":\"binary\"},{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"TheDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}";
String query; String query;
if (deploymentId == null) { if (deploymentId == null) {
query = queryNoDepl; query = queryNoDepl;
@ -228,18 +241,92 @@ public class DBXMLQueries {
query = query.replace("LongDataName", dataBlock.getLongDataName()); query = query.replace("LongDataName", dataBlock.getLongDataName());
DBQueryResult queryResult = executeQuery(query); DBQueryResult queryResult = executeQuery(query);
if (queryResult ==null) { if (queryResult ==null) {
return 0; return null;
} }
Document doc = convertStringToXMLDocument(queryResult.queryResult); Document doc;
if (doc == null) { try {
return 0; doc = queryResult.getDocument();
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
return null;
} }
ArrayList<String> detectionsNames = new ArrayList();
int count = 0; int count = 0;
NodeList returns = doc.getElementsByTagName("Return"); NodeList returns = doc.getElementsByTagName("Return");
for (int i = 0; i < returns.getLength(); i++) { for (int i = 0; i < returns.getLength(); i++) {
Node aNode = returns.item(i); Node aNode = returns.item(i);
String docName = aNode.getTextContent(); String docName = aNode.getTextContent();
detectionsNames.add(docName);
}
return detectionsNames;
}
/**
* Get the names of all detection documents for a given deployment for all data streams.
* @param deploymentId
* @return
*/
public ArrayList<String> getDetectionsDocuments(String deploymentId) {
String queryBase = "{\"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\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"SomeDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}";
String queryStr = queryBase.replace("SomeDeploymentId", deploymentId);
DBQueryResult queryResult = executeQuery(queryStr);
if (queryResult == null || queryResult.queryException != null) {
return null;
}
// PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
Document doc = convertStringToXMLDocument(queryResult.queryResult);
if (doc == null) {
return null;
}
ArrayList<String> detectionDocs = new ArrayList<>();
NodeList returns = doc.getElementsByTagName("Return");
for (int i = 0; i < returns.getLength(); i++) {
Node aNode = returns.item(i);
detectionDocs.add(aNode.getTextContent());
}
return detectionDocs;
}
public int countData(PamDataBlock dataBlock, String deploymentId) {
// /**
// * first query for Detections documents associated with this deployment and datablock.
// */
// String queryNoDepl = "{\"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\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Algorithm/Software\",\"LongDataName\"],\"optype\":\"binary\"}],\"enclose\":1}";
// String queryWithDepl = "{\"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\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Algorithm/Software\",\"LongDataName\"],\"optype\":\"binary\"},{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"TheDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}";
// String query;
// if (deploymentId == null) {
// query = queryNoDepl;
// }
// else {
// query = queryWithDepl.replace("TheDeploymentId", deploymentId);
// }
// query = query.replace("LongDataName", dataBlock.getLongDataName());
// DBQueryResult queryResult = executeQuery(query);
// if (queryResult ==null) {
// return 0;
// }
// Document doc;
// try {
// doc = queryResult.getDocument();
// } catch (ParserConfigurationException | SAXException | IOException e) {
// e.printStackTrace();
// return 0;
// }
//
// int count = 0;
// NodeList returns = doc.getElementsByTagName("Return");
ArrayList<String> documentNames = getDetectionsDocuments(dataBlock, deploymentId);
if (documentNames == null) {
return 0;
}
int count = 0;
for (int i = 0; i < documentNames.size(); i++) {
// Node aNode = returns.item(i);
String docName = documentNames.get(i);
// System.out.println(aNode.getTextContent()); // System.out.println(aNode.getTextContent());
int count2 = countDetections2(docName); int count2 = countDetections2(docName);
count += count2; //countDetecionsData(docName); count += count2; //countDetecionsData(docName);
@ -248,7 +335,12 @@ public class DBXMLQueries {
return count; return count;
} }
private int countDetections2(String docName) { /**
* Count on effort detections in a Detections document
* @param docName
* @return
*/
public int countDetections2(String docName) {
TethysExportParams params = tethysControl.getTethysExportParams(); TethysExportParams params = tethysControl.getTethysExportParams();
String queryBase = "count(collection(\"Detections\")/Detections[Id=\"ReplaceDocumentId\"]/OnEffort/Detection)"; String queryBase = "count(collection(\"Detections\")/Detections[Id=\"ReplaceDocumentId\"]/OnEffort/Detection)";
String query = queryBase.replace("ReplaceDocumentId", docName); String query = queryBase.replace("ReplaceDocumentId", docName);
@ -275,115 +367,67 @@ public class DBXMLQueries {
return count; return count;
} }
/** // /**
* Count the data in a detections document. // * Get a count of the detections in a detections document.
* @param detectionDocId // * Only looking in onEffort so far.
* @return count of on effort detections in document. // * @param deploymentId
*/ // * @param detectionDocId
private int countDetecionsData(String detectionDocId) { // * @param dataBlock
String queryBase = "{\"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/OnEffort/Detection/Start\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Id\",\"DetectionsDocName\"],\"optype\":\"binary\"}],\"enclose\":1}"; // * @return
String query = queryBase.replace("DetectionsDocName", detectionDocId); // */
DBQueryResult queryResult = executeQuery(query); // public int getDetectionsDetectionCount(String deploymentId, String detectionDocId, PamDataBlock dataBlock) {
Document doc = convertStringToXMLDocument(queryResult.queryResult); // String queryBase = "{\"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/OnEffort/Detection/Start\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Id\",\"SomeDetectionsId\"],\"optype\":\"binary\"},{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"SomeDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}";
if (doc == null) { // String queryStr = queryBase.replace("SomeDetectionsId", detectionDocId);
return 0; // queryStr = queryStr.replace("SomeDeploymentId", deploymentId);
} // DBQueryResult queryResult = executeQuery(queryStr);
// if (queryResult == null || queryResult.queryException != null) {
NodeList returns = doc.getElementsByTagName("Start"); // return 0;
return returns.getLength(); // }
} //// System.out.println("Detections query time ms = " + queryResult.queryTimeMillis);
//
/**
* Get the names of all detection documents for a given deployment
* @param deploymentId
* @return
*/
public ArrayList<String> getDetectionsDocsIds(String deploymentId) {
String queryBase = "{\"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\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"SomeDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}";
String queryStr = queryBase.replace("SomeDeploymentId", deploymentId);
DBQueryResult queryResult = executeQuery(queryStr);
if (queryResult == null || queryResult.queryException != null) {
return null;
}
// PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter(); // PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
//
// Document doc = convertStringToXMLDocument(queryResult.queryResult);
// if (doc == null) {
// return 0;
// }
//
//// System.out.println(pamXMLWriter.getAsString(doc));
//
//// ArrayList<String> detectionDocs = new ArrayList<>();
//
// NodeList returns = doc.getElementsByTagName("Start");
// int n = returns.getLength();
// return n;
// }
Document doc = convertStringToXMLDocument(queryResult.queryResult); // /**
if (doc == null) { // * This is the quickest way of counting data in a project, but it will load the start
return null; // * times for every detection in a project at once, so might use a lot of memory. Also
} // * it wll probably get data for all deployments in a project, which may not be what we want.
// * @param projectName
ArrayList<String> detectionDocs = new ArrayList<>(); // * @param dataPrefixes
// * @return
NodeList returns = doc.getElementsByTagName("Return"); // */
for (int i = 0; i < returns.getLength(); i++) { // public int[] countDataForProject(String projectName, String[] dataPrefixes) {
Node aNode = returns.item(i); // int[] n = new int[dataPrefixes.length];
detectionDocs.add(aNode.getTextContent()); // ArrayList<PDeployment> matchedDeployments = tethysControl.getDeploymentHandler().getMatchedDeployments();
} //// ArrayList<nilus.Deployment> deployments = getProjectDeployments(projectName);
return detectionDocs; // if (matchedDeployments == null) {
} // return null;
// }
/** // for (PDeployment aDeployment : matchedDeployments) {
* Get a count of the detections in a detections document. //// ArrayList<String> detectionsIds = getDetectionsDocsIds(aDeployment.getId());
* Only looking in onEffort so far. //// for (String detId : detectionsIds) {
* @param deploymentId //// n += getDetectionsDetectionCount(aDeployment.getId(), detId, dataBlock);
* @param detectionDocId //// }
* @param dataBlock // int[] newN = countDataForDeployment(projectName, aDeployment.deployment.getId(), dataPrefixes);
* @return // for (int i = 0; i < n.length; i++) {
*/ // n[i] += newN[i];
public int getDetectionsDetectionCount(String deploymentId, String detectionDocId, PamDataBlock dataBlock) {
String queryBase = "{\"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/OnEffort/Detection/Start\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Id\",\"SomeDetectionsId\"],\"optype\":\"binary\"},{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"SomeDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}";
String queryStr = queryBase.replace("SomeDetectionsId", detectionDocId);
queryStr = queryStr.replace("SomeDeploymentId", deploymentId);
DBQueryResult queryResult = executeQuery(queryStr);
if (queryResult == null || queryResult.queryException != null) {
return 0;
}
// System.out.println("Detections query time ms = " + queryResult.queryTimeMillis);
PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
Document doc = convertStringToXMLDocument(queryResult.queryResult);
if (doc == null) {
return 0;
}
// System.out.println(pamXMLWriter.getAsString(doc));
// ArrayList<String> detectionDocs = new ArrayList<>();
NodeList returns = doc.getElementsByTagName("Start");
int n = returns.getLength();
return n;
}
/**
* This is the quickest way of counting data in a project, but it will load the start
* times for every detection in a project at once, so might use a lot of memory. Also
* it wll probably get data for all deployments in a project, which may not be what we want.
* @param projectName
* @param dataPrefixes
* @return
*/
public int[] countDataForProject(String projectName, String[] dataPrefixes) {
int[] n = new int[dataPrefixes.length];
ArrayList<PDeployment> matchedDeployments = tethysControl.getDeploymentHandler().getMatchedDeployments();
// ArrayList<nilus.Deployment> deployments = getProjectDeployments(projectName);
if (matchedDeployments == null) {
return null;
}
for (PDeployment aDeployment : matchedDeployments) {
// ArrayList<String> detectionsIds = getDetectionsDocsIds(aDeployment.getId());
// for (String detId : detectionsIds) {
// n += getDetectionsDetectionCount(aDeployment.getId(), detId, dataBlock);
// } // }
int[] newN = countDataForDeployment(projectName, aDeployment.deployment.getId(), dataPrefixes); // }
for (int i = 0; i < n.length; i++) { // return n;
n[i] += newN[i]; // }
}
}
return n;
}
/** /**
* Count data within a deployment document which is associated with a set of datablocks * Count data within a deployment document which is associated with a set of datablocks
@ -486,4 +530,55 @@ public class DBXMLQueries {
return null; return null;
} }
/**
* Get the basic information about a Detections document. This is basically everything apart from
* the actual detections themselves.
* @param aDoc
* @return
*/
public Detections getDetectionsDocInfo(String detectionsDocName) {
String queryBase = "{\"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 query = queryBase.replace("DetectionsDocName", detectionsDocName);
DBQueryResult queryResult = executeQuery(query);
Document doc;
try {
doc = queryResult.getDocument();
} catch (ParserConfigurationException | SAXException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
// System.out.println(queryResult.queryResult);
Detections detections = new Detections();
try {
Helper.createRequiredElements(detections);
} catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
NodeList returns = doc.getElementsByTagName("Result");
// System.out.println("N projects = " + returns.getLength());
int n = returns.getLength();
if (n == 0) {
return null;
}
Element result = (Element) returns.item(0);
DescriptionType description = detections.getDescription();
if (description == null) {
description = new DescriptionType();
detections.setDescription(description);
}
detections.setId(getElementData(result, "Id"));
description.setAbstract(getElementData(result, "Description.Abstract"));
description.setMethod(getElementData(result, "Description.Method"));
description.setObjectives(getElementData(result, "Description.Objectives"));
// TODO Auto-generated method stub
return detections;
}
} }

View File

@ -0,0 +1,11 @@
package tethys.detection;
public interface DetectionExportObserver {
/**
* Update message and state of export
* @param progress
*/
public void update(DetectionExportProgress progress);
}

View File

@ -0,0 +1,31 @@
package tethys.detection;
import nilus.Detections;
import tethys.niluswraps.PDeployment;
public class DetectionExportProgress {
public static final int STATE_GATHERING = 1;
public static final int STATE_CANCELED = 2;
public static final int STATE_COMPLETE = 3;
public static final int STATE_WRITING = 4;
public PDeployment currentDeployment;
public Detections currentDetections;
public long lastUnitTime;
public long totalUnits;
public int exportCount;
public int skipCount;
public int state;
public DetectionExportProgress(PDeployment currentDeployment, Detections currentDetections, long lastUnitTime,
long totalUnits, int exportCount, int skipCount, int state) {
super();
this.currentDeployment = currentDeployment;
this.currentDetections = currentDetections;
this.lastUnitTime = lastUnitTime;
this.totalUnits = totalUnits;
this.exportCount = exportCount;
this.skipCount = skipCount;
this.state = state;
}
}

View File

@ -4,13 +4,21 @@ import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.SwingWorker;
import PamController.PamControlledUnit;
import PamController.PamguardVersionInfo;
import PamModel.PamPluginInterface;
import PamUtils.PamCalendar; import PamUtils.PamCalendar;
import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit; import PamguardMVC.PamDataUnit;
import PamguardMVC.PamProcess;
import PamguardMVC.dataSelector.DataSelector; import PamguardMVC.dataSelector.DataSelector;
import dataMap.OfflineDataMap; import dataMap.OfflineDataMap;
import dataMap.OfflineDataMapPoint; import dataMap.OfflineDataMapPoint;
import metadata.deployment.DeploymentData; import metadata.deployment.DeploymentData;
import nilus.AlgorithmType;
import nilus.AlgorithmType.SupportSoftware;
import nilus.DataSourceType; import nilus.DataSourceType;
import nilus.Deployment; import nilus.Deployment;
import nilus.Detection; import nilus.Detection;
@ -18,172 +26,225 @@ import nilus.DetectionEffort;
import nilus.DetectionEffortKind; import nilus.DetectionEffortKind;
import nilus.DetectionGroup; import nilus.DetectionGroup;
import nilus.Detections; import nilus.Detections;
import nilus.Helper;
import tethys.TethysControl; import tethys.TethysControl;
import tethys.TethysState;
import tethys.TethysState.StateType;
import tethys.deployment.DeploymentHandler;
import tethys.TethysStateObserver;
import tethys.TethysTimeFuncs; import tethys.TethysTimeFuncs;
import tethys.dbxml.DBXMLConnect;
import tethys.detection.DetectionGranularity.GRANULARITY; import tethys.detection.DetectionGranularity.GRANULARITY;
import tethys.niluswraps.PDeployment;
import tethys.niluswraps.PDetections;
import tethys.output.StreamExportParams; import tethys.output.StreamExportParams;
import tethys.output.TethysExportParams; import tethys.output.TethysExportParams;
import tethys.pamdata.TethysDataPoint;
import tethys.pamdata.TethysDataProvider; import tethys.pamdata.TethysDataProvider;
import tethys.swing.export.ExportWorkerCard;
public class DetectionsHandler { public class DetectionsHandler {
private TethysControl tethysControl; private TethysControl tethysControl;
public int uniqueDetectionsId; public int uniqueDetectionsId=1;
public int uniqueDetectionId; public int uniqueDetectionId;
private volatile boolean activeExport;
private ExportWorker exportWorker;
public DetectionsHandler(TethysControl tethysControl) { public DetectionsHandler(TethysControl tethysControl) {
super(); super();
this.tethysControl = tethysControl; this.tethysControl = tethysControl;
} }
/**
* Get a list of Detections documents associated with a particular data stream for
* this data set (not the entire project).
* @param dataBlock
*/
public StreamDetectionsSummary getStreamDetections(PamDataBlock dataBlock) {
ArrayList<PDeployment> deployments = tethysControl.getDeploymentHandler().getMatchedDeployments();
return getStreamDetections(dataBlock, deployments);
}
/** /**
* Here is where we export data for a specific data stream to Tethys. * Get a list of Detections documents associated with a particular data block for the list of deployments
* * documents. Group them by abstract or something
* @param aDataBlock
* @param aDeployment
* @param tethysExportParams
* @param streamExportParams
*/
public boolean exportDetections(PamDataBlock aDataBlock, Deployment deployment, DetectionGranularity granularity, TethysExportParams tethysExportParams,
StreamExportParams streamExportParams) {
if (granularity == null || granularity.granularity == null) {
granularity = new DetectionGranularity(GRANULARITY.TIME, 3600);
}
switch (granularity.granularity) {
case BINARYFILE:
return exportByBinaryFile(aDataBlock, deployment, tethysExportParams, streamExportParams);
case NONE:
return exportEverything(aDataBlock, deployment, tethysExportParams, streamExportParams);
case TIME:
return exportByTimeChunk(aDataBlock, deployment, granularity.granularityIntervalSeconds, tethysExportParams, streamExportParams);
default:
break;
}
return false;
}
private boolean exportByBinaryFile(PamDataBlock dataBlock, Deployment deployment,
TethysExportParams tethysExportParams, StreamExportParams streamExportParams) {
long deploymentStart = TethysTimeFuncs.millisFromGregorianXML(deployment.getDeploymentDetails().getAudioTimeStamp());
long deploymentStop = TethysTimeFuncs.millisFromGregorianXML(deployment.getRecoveryDetails().getAudioTimeStamp());
/*
* there should be a pretty good correspondence between the start of a binary file and the deploymentStart
* since they all derived from the same start clock.
*/
OfflineDataMap dataMap = dataBlock.getPrimaryDataMap();
if (dataMap == null) {
return false;
}
List<OfflineDataMapPoint> mapPoints = dataMap.getMapPoints();
boolean ok = true;
for (OfflineDataMapPoint mapPoint : mapPoints) {
if (mapPoint.getEndTime() < deploymentStart) {
continue;
}
if (mapPoint.getStartTime() >= deploymentStop) {
continue;
}
ok &= loadAndExport(dataBlock, deployment, Math.max(deploymentStart, mapPoint.getStartTime()),
Math.min(deploymentStop, mapPoint.getEndTime()), tethysExportParams, streamExportParams);
}
return ok;
}
private boolean exportEverything(PamDataBlock dataBlock, Deployment deployment,
TethysExportParams tethysExportParams, StreamExportParams streamExportParams) {
long deploymentStart = TethysTimeFuncs.millisFromGregorianXML(deployment.getDeploymentDetails().getAudioTimeStamp());
long deploymentStop = TethysTimeFuncs.millisFromGregorianXML(deployment.getRecoveryDetails().getAudioTimeStamp());
return loadAndExport(dataBlock, deployment, deploymentStart, deploymentStop, tethysExportParams, streamExportParams);
}
private boolean exportByTimeChunk(PamDataBlock dataBlock, Deployment deployment, long granularityIntervalSeconds,
TethysExportParams tethysExportParams, StreamExportParams streamExportParams) {
long deploymentStart = TethysTimeFuncs.millisFromGregorianXML(deployment.getDeploymentDetails().getAudioTimeStamp());
long deploymentStop = TethysTimeFuncs.millisFromGregorianXML(deployment.getRecoveryDetails().getAudioTimeStamp());
long chunkMillis = granularityIntervalSeconds*1000;
long exportStart = deploymentStart / chunkMillis;
exportStart *= chunkMillis;
boolean ok = true;
while (exportStart < deploymentStop) {
ok &= loadAndExport(dataBlock, deployment, Math.max(deploymentStart, exportStart),
Math.min(deploymentStop, exportStart + chunkMillis), tethysExportParams, streamExportParams);
exportStart += chunkMillis;
}
return ok;
}
/**
* Load and export data for a given time period. This may be a complete deployment, it may be a short section. Do as told !
* Hopefully data interval is small enough to hold all in memory - it needs to be if the document will fit in mempory, so should be OK
* @param dataBlock * @param dataBlock
* @param deployment * @param deployments
* @param max * @return
* @param min
* @param tethysExportParams
* @param streamExportParams
*/ */
private boolean loadAndExport(PamDataBlock dataBlock, Deployment deployment, long startTimeMillis, long endTimeMillis, public StreamDetectionsSummary getStreamDetections(PamDataBlock dataBlock, ArrayList<PDeployment> deployments) {
TethysExportParams tethysExportParams, StreamExportParams streamExportParams) { // get the basic data for each document including it's Description.
// load the data
dataBlock.loadViewerData(startTimeMillis, endTimeMillis, null); ArrayList<PDetections> detectionsDocs = new ArrayList<>();
DataSelector dataSelector = dataBlock.getDataSelector(tethysControl.getDataSelectName(), false); for (PDeployment aDep : deployments) {
/* ArrayList<String> someNames = tethysControl.getDbxmlQueries().getDetectionsDocuments(dataBlock, aDep.deployment.getId());
* for easier synching, get a copy of the data and also apply the data selector right away so that if (someNames == null) {
* we've a list of exactly the right data. continue;
*/ }
ArrayList<PamDataUnit> data = dataBlock.getDataCopy(startTimeMillis, endTimeMillis, true, dataSelector); // no have a list of all the Detections documents of interest for this datablock.
/* for (String aDoc : someNames) {
* Here, make Detection object and add the DetectionEffort data. Detections detections = tethysControl.getDbxmlQueries().getDetectionsDocInfo(aDoc);
*/ int count = tethysControl.getDbxmlQueries().countDetections2(aDoc);
DeploymentData globalDeplData = tethysControl.getGlobalDeplopymentData(); PDetections pDetections = new PDetections(detections, null, count);
TethysDataProvider dataProvider = dataBlock.getTethysDataProvider(); detectionsDocs.add(pDetections);
Detections detections = new Detections();
// String prefix = getDetectionsDocIdPrefix(globalDeplData.getProject(), dataBlock);
String prefix = deployment.getId();
detections.setId(String.format("%s_%d", prefix, uniqueDetectionsId++));
detections.setDescription(dataProvider.getDescription(deployment, tethysExportParams));
DataSourceType dataSource = new DataSourceType();
dataSource.setDeploymentId(deployment.getId());
// dataSource.setEnsembleId(""); ToDo
detections.setDataSource(dataSource);
detections.setAlgorithm(dataProvider.getAlgorithm());
detections.setUserId("Unknown user");
detections.setEffort(getDetectorEffort(deployment, startTimeMillis, endTimeMillis));
DetectionGroup detectionGroup = new DetectionGroup();
detections.setOnEffort(detectionGroup);
List<Detection> detectionList = detectionGroup.getDetection();
for (int i = 0; i < data.size(); i++) {
PamDataUnit dataUnit = data.get(i);
Detection detection = dataProvider.createDetection(dataUnit, tethysExportParams, streamExportParams);
if (detection != null) {
detectionList.add(detection);
} }
} }
System.out.printf("Exporting %d %s detections for time period %s to %s\n", detectionList.size(), dataBlock.getDataName(), return new StreamDetectionsSummary(detectionsDocs);
detections.getEffort().getStart().toString(), detections.getEffort().getEnd().toString());
/*
* We should now have a fully populated Detections object, so write it to the database
* using functions in DBXMLConnect
*/
ArrayList<Detections> detectionDocuments = new ArrayList();
detectionDocuments.add(detections);
// tethysControl.getDbxmlConnect().postToTethys(detectionDocuments); // call whatever you need to call in here to write the Detections.
return true;
} }
// /**
// * Here is where we export data for a specific data stream to Tethys.
// *
// * @param aDataBlock
// * @param aDeployment
// * @param tethysExportParams
// * @param streamExportParams
// */
// public boolean exportDetections(PamDataBlock aDataBlock, Deployment deployment, DetectionGranularity granularity, TethysExportParams tethysExportParams,
// StreamExportParams streamExportParams) {
// if (granularity == null || granularity.granularity == null) {
// granularity = new DetectionGranularity(GRANULARITY.TIME, 3600);
// }
// switch (granularity.granularity) {
// case BINARYFILE:
// return exportByBinaryFile(aDataBlock, deployment, tethysExportParams, streamExportParams);
// case NONE:
// return exportEverything(aDataBlock, deployment, tethysExportParams, streamExportParams);
// case TIME:
// return exportByTimeChunk(aDataBlock, deployment, granularity.granularityIntervalSeconds, tethysExportParams, streamExportParams);
// default:
// break;
// }
//
// return false;
//
//
// }
//
// private boolean exportByBinaryFile(PamDataBlock dataBlock, Deployment deployment,
// TethysExportParams tethysExportParams, StreamExportParams streamExportParams) {
// long deploymentStart = TethysTimeFuncs.millisFromGregorianXML(deployment.getDeploymentDetails().getAudioTimeStamp());
// long deploymentStop = TethysTimeFuncs.millisFromGregorianXML(deployment.getRecoveryDetails().getAudioTimeStamp());
// /*
// * there should be a pretty good correspondence between the start of a binary file and the deploymentStart
// * since they all derived from the same start clock.
// */
// OfflineDataMap dataMap = dataBlock.getPrimaryDataMap();
// if (dataMap == null) {
// return false;
// }
// List<OfflineDataMapPoint> mapPoints = dataMap.getMapPoints();
// boolean ok = true;
// for (OfflineDataMapPoint mapPoint : mapPoints) {
// if (mapPoint.getEndTime() < deploymentStart) {
// continue;
// }
// if (mapPoint.getStartTime() >= deploymentStop) {
// continue;
// }
// ok &= loadAndExport(dataBlock, deployment, Math.max(deploymentStart, mapPoint.getStartTime()),
// Math.min(deploymentStop, mapPoint.getEndTime()), tethysExportParams, streamExportParams);
// }
//
//
// return ok;
// }
//
// private boolean exportEverything(PamDataBlock dataBlock, Deployment deployment,
// TethysExportParams tethysExportParams, StreamExportParams streamExportParams) {
// long deploymentStart = TethysTimeFuncs.millisFromGregorianXML(deployment.getDeploymentDetails().getAudioTimeStamp());
// long deploymentStop = TethysTimeFuncs.millisFromGregorianXML(deployment.getRecoveryDetails().getAudioTimeStamp());
// return loadAndExport(dataBlock, deployment, deploymentStart, deploymentStop, tethysExportParams, streamExportParams);
// }
//
// private boolean exportByTimeChunk(PamDataBlock dataBlock, Deployment deployment, long granularityIntervalSeconds,
// TethysExportParams tethysExportParams, StreamExportParams streamExportParams) {
//
// long deploymentStart = TethysTimeFuncs.millisFromGregorianXML(deployment.getDeploymentDetails().getAudioTimeStamp());
// long deploymentStop = TethysTimeFuncs.millisFromGregorianXML(deployment.getRecoveryDetails().getAudioTimeStamp());
// long chunkMillis = granularityIntervalSeconds*1000;
// long exportStart = deploymentStart / chunkMillis;
// exportStart *= chunkMillis;
// boolean ok = true;
// while (exportStart < deploymentStop) {
// ok &= loadAndExport(dataBlock, deployment, Math.max(deploymentStart, exportStart),
// Math.min(deploymentStop, exportStart + chunkMillis), tethysExportParams, streamExportParams);
// exportStart += chunkMillis;
// }
//
// return ok;
// }
//
///**
// * Load and export data for a given time period. This may be a complete deployment, it may be a short section. Do as told !
// * Hopefully data interval is small enough to hold all in memory - it needs to be if the document will fit in mempory, so should be OK
// * @param dataBlock
// * @param deployment
// * @param max
// * @param min
// * @param tethysExportParams
// * @param streamExportParams
// */
// private boolean loadAndExport(PamDataBlock dataBlock, Deployment deployment, long startTimeMillis, long endTimeMillis,
// TethysExportParams tethysExportParams, StreamExportParams streamExportParams) {
// // load the data
// dataBlock.loadViewerData(startTimeMillis, endTimeMillis, null);
// DataSelector dataSelector = dataBlock.getDataSelector(tethysControl.getDataSelectName(), false);
// /*
// * for easier synching, get a copy of the data and also apply the data selector right away so that
// * we've a list of exactly the right data.
// */
// ArrayList<PamDataUnit> data = dataBlock.getDataCopy(startTimeMillis, endTimeMillis, true, dataSelector);
// /*
// * Here, make Detection object and add the DetectionEffort data.
// */
// DeploymentData globalDeplData = tethysControl.getGlobalDeplopymentData();
// TethysDataProvider dataProvider = dataBlock.getTethysDataProvider();
// Detections detections = new Detections();
//// String prefix = getDetectionsDocIdPrefix(globalDeplData.getProject(), dataBlock);
// String prefix = deployment.getId();
// detections.setId(String.format("%s_%d", prefix, uniqueDetectionsId++));
// detections.setDescription(dataProvider.getDescription(deployment, tethysExportParams));
// DataSourceType dataSource = new DataSourceType();
// dataSource.setDeploymentId(deployment.getId());
//// dataSource.setEnsembleId(""); ToDo
// detections.setDataSource(dataSource);
// detections.setAlgorithm(dataProvider.getAlgorithm());
// detections.setUserId("Unknown user");
// detections.setEffort(getDetectorEffort(deployment, startTimeMillis, endTimeMillis));
// DetectionGroup detectionGroup = new DetectionGroup();
// detections.setOnEffort(detectionGroup);
// List<Detection> detectionList = detectionGroup.getDetection();
// for (int i = 0; i < data.size(); i++) {
// PamDataUnit dataUnit = data.get(i);
// Detection detection = dataProvider.createDetection(dataUnit, tethysExportParams, streamExportParams);
// if (detection != null) {
// detectionList.add(detection);
// }
// }
// System.out.printf("Exporting %d %s detections for time period %s to %s\n", detectionList.size(), dataBlock.getDataName(),
// detections.getEffort().getStart().toString(), detections.getEffort().getEnd().toString());
// /*
// * We should now have a fully populated Detections object, so write it to the database
// * using functions in DBXMLConnect
// */
// ArrayList<Detections> detectionDocuments = new ArrayList();
// detectionDocuments.add(detections);
//
//// tethysControl.getDbxmlConnect().postToTethys(detectionDocuments); // call whatever you need to call in here to write the Detections.
//
//
// return true;
//
// }
// private boolean exportByTimeChunk(PamDataBlock aDataBlock, Deployment deployment, long granularityIntervalSeconds, // private boolean exportByTimeChunk(PamDataBlock aDataBlock, Deployment deployment, long granularityIntervalSeconds,
// TethysExportParams tethysExportParams, StreamExportParams streamExportParams) { // TethysExportParams tethysExportParams, StreamExportParams streamExportParams) {
// // TODO Auto-generated method stub // // TODO Auto-generated method stub
@ -218,6 +279,60 @@ public class DetectionsHandler {
return effort; return effort;
} }
/**
* Method string for Detections Algorithm documents.
* @param dataBlock
* @return
*/
public String getMethodString(PamDataBlock dataBlock) {
if (dataBlock == null) {
return null;
}
PamProcess process = dataBlock.getParentProcess();
return "PAMGuard " + process.getProcessName();
}
/**
* Software string for Detections Algorithm documents.
* @param dataBlock
* @return
*/
public String getSoftwareString(PamDataBlock dataBlock) {
if (dataBlock == null) {
return null;
}
return dataBlock.getLongDataName();
}
/**
* Software string for Detections Algorithm documents.
* @param dataBlock
* @return
*/
public String getVersionString(PamDataBlock dataBlock) {
if (dataBlock == null) {
return null;
}
PamProcess process = dataBlock.getParentProcess();
PamControlledUnit pcu = process.getPamControlledUnit();
PamPluginInterface plugin = pcu.getPlugin();
if (plugin == null) {
return PamguardVersionInfo.version;
}
else {
return plugin.getVersion();
}
}
public String getSupportSoftware(PamDataBlock dataBlock) {
return "PAMGuard";
}
public String getSupportSoftwareVersion(PamDataBlock dataBlock) {
// should try to dig into the binary store and get the version from there.
return PamguardVersionInfo.version;
}
// /** // /**
// * Get a prefix for a id for a Detections document. This is just the project name // * Get a prefix for a id for a Detections document. This is just the project name
// * and the datablock name. Something may need to be added to allow for multiple // * and the datablock name. Something may need to be added to allow for multiple
@ -229,4 +344,201 @@ public class DetectionsHandler {
// public static final String getDetectionsDocIdPrefix(String project, PamDataBlock dataBlock) { // public static final String getDetectionsDocIdPrefix(String project, PamDataBlock dataBlock) {
// return project + "_" + dataBlock.getDataName(); // return project + "_" + dataBlock.getDataName();
// } // }
/**
* Detections will be exported in a separate worker thread since export may take some time and
* the user should be given ample opportunity to cancel it.
* @param pamDataBlock
* @param streamExportParams
* @param exportWorkerCard
*/
public void startExportThread(PamDataBlock pamDataBlock, StreamExportParams streamExportParams, DetectionExportObserver exportObserver) {
tethysControl.getTethysExportParams().setStreamParams(pamDataBlock, streamExportParams);
activeExport = true;
exportWorker = new ExportWorker(pamDataBlock, streamExportParams, exportObserver);
exportWorker.execute();
}
public void cancelExport() {
activeExport = false;
}
/**
* Export detections in all deployments for this PAMGuard dataset.
* @param dataBlock
* @param streamExportParams
* @param exportObserver
* @return
*/
private int exportDetections(PamDataBlock dataBlock, StreamExportParams streamExportParams, DetectionExportObserver exportObserver) {
/*
* This is currently called for the entire dataset, but we will need to loop over specific Deployment documents
* and export the content of each separately.
*/
TethysExportParams exportParams = tethysControl.getTethysExportParams();
DBXMLConnect dbxmlConnect = tethysControl.getDbxmlConnect();
DeploymentHandler depHandler = tethysControl.getDeploymentHandler();
ArrayList<PDeployment> deployments = depHandler.getMatchedDeployments();
Detections currentDetections = null;
OfflineDataMap dataMap = dataBlock.getPrimaryDataMap();
TethysDataProvider dataProvider = dataBlock.getTethysDataProvider();
DataSelector dataSelector = dataBlock.getDataSelector(tethysControl.getDataSelectName(), false);
int totalCount = dataMap.getDataCount();
int skipCount = 0;
int exportCount = 0;
long lastUnitTime = 0;
DetectionExportProgress prog;
for (PDeployment deployment : deployments) {
int documentCount = 0;
prog = new DetectionExportProgress(deployment, null,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_GATHERING);
exportObserver.update(prog);
// export everything in that deployment.
// need to loop through all map points in this interval.
List<OfflineDataMapPoint> mapPoints = dataMap.getMapPoints();
for (OfflineDataMapPoint mapPoint : mapPoints) {
if (activeExport == false) {
prog = new DetectionExportProgress(deployment, currentDetections,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_CANCELED);
exportObserver.update(prog);
}
if (currentDetections == null) {
currentDetections = startDetectionsDocument(deployment, dataBlock, streamExportParams);
currentDetections.getEffort().setStart(TethysTimeFuncs.xmlGregCalFromMillis(mapPoint.getStartTime()));
}
if (mapPoint.getEndTime() < deployment.getAudioStart()) {
continue;
}
if (mapPoint.getStartTime() >= deployment.getAudioEnd()) {
break;
}
dataBlock.loadViewerData(mapPoint.getStartTime(), mapPoint.getEndTime(), null);
ArrayList<PamDataUnit> dataCopy = dataBlock.getDataCopy(deployment.getAudioStart(), deployment.getAudioEnd(), true, dataSelector);
skipCount += dataBlock.getUnitsCount() - dataCopy.size();
DetectionGroup onEffort = currentDetections.getOnEffort();
for (PamDataUnit dataUnit : dataCopy) {
Detection det = dataProvider.createDetection(dataUnit, exportParams, streamExportParams);
exportCount++;
documentCount++;
onEffort.getDetection().add(det);
lastUnitTime = dataUnit.getTimeMilliseconds();
}
prog = new DetectionExportProgress(deployment, currentDetections,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_GATHERING);
exportObserver.update(prog);
if (documentCount > 500000 && mapPoint != dataMap.getLastMapPoint()) {
prog = new DetectionExportProgress(deployment, currentDetections,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_WRITING);
exportObserver.update(prog);
closeDetectionsDocument(currentDetections, mapPoint.getEndTime());
dbxmlConnect.postToTethys(currentDetections);
currentDetections = null;
}
}
if (currentDetections != null) {
prog = new DetectionExportProgress(deployment, currentDetections,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_WRITING);
closeDetectionsDocument(currentDetections, deployment.getAudioEnd());
dbxmlConnect.postToTethys(currentDetections);
currentDetections = null;
}
}
prog = new DetectionExportProgress(null, null,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_COMPLETE);
exportObserver.update(prog);
return DetectionExportProgress.STATE_COMPLETE;
}
private Detections startDetectionsDocument(PDeployment deployment, PamDataBlock dataBlock,
StreamExportParams exportParams) {
Detections detections = new Detections();
try {
Helper.createRequiredElements(detections);
} catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
return null;
}
String prefix = deployment.deployment.getId();
detections.setId(String.format("%s_%d", prefix, uniqueDetectionsId++));
// detections.setDescription(dataProvider.getDescription(deployment, tethysExportParams));
detections.setDescription(exportParams.detectionDescription);
DataSourceType dataSource = new DataSourceType();
dataSource.setDeploymentId(deployment.deployment.getId());
// dataSource.setEnsembleId(""); ToDo
detections.setDataSource(dataSource);
AlgorithmType algorithm = detections.getAlgorithm();
algorithm.setMethod(getMethodString(dataBlock));
algorithm.setSoftware(getSoftwareString(dataBlock));
algorithm.setVersion(getVersionString(dataBlock));
List<SupportSoftware> supSoft = algorithm.getSupportSoftware();
SupportSoftware supportSoft = new SupportSoftware();
supportSoft.setSoftware(getSupportSoftware(dataBlock));
supportSoft.setVersion(getSupportSoftwareVersion(dataBlock));
supSoft.add(supportSoft);
detections.setAlgorithm(algorithm);
detections.setUserId("Unknown user");
detections.setEffort(getDetectorEffort(deployment.deployment, deployment.getAudioStart(), deployment.getAudioEnd()));
return detections;
}
/**
* Close a detections document. This basically just means rewriting the end time and it's only
* important in the event that a document got too big and has to be restarted.
* @param detections
* @param audioEnd
*/
private void closeDetectionsDocument(Detections detections, Long audioEnd) {
detections.getEffort().setEnd(TethysTimeFuncs.xmlGregCalFromMillis(audioEnd));
}
private class ExportWorker extends SwingWorker<Integer, DetectionExportProgress> implements DetectionExportObserver {
private PamDataBlock dataBlock;
private StreamExportParams exportParams;
private DetectionExportObserver exportObserver;
public ExportWorker(PamDataBlock dataBlock, StreamExportParams exportParams,
DetectionExportObserver exportObserver) {
super();
this.dataBlock = dataBlock;
this.exportParams = exportParams;
this.exportObserver = exportObserver;
}
public void publish(DetectionExportProgress exportProgress) {
super.publish(exportProgress);
}
@Override
protected Integer doInBackground() throws Exception {
// eventually need to switch over the four granularity options here.
return exportDetections(dataBlock, exportParams, this);
}
@Override
protected void done() {
// this.
DetectionExportProgress prog = new DetectionExportProgress(null, null, 0, 0, 0, 0, DetectionExportProgress.STATE_COMPLETE);
exportObserver.update(prog);
}
@Override
protected void process(List<DetectionExportProgress> chunks) {
for (DetectionExportProgress prog : chunks) {
exportObserver.update(prog);
}
}
@Override
public void update(DetectionExportProgress progress) {
publish(progress);
}
}
} }

View File

@ -0,0 +1,21 @@
package tethys.detection;
import java.util.ArrayList;
import tethys.niluswraps.PDetections;
/**
* Summary information on all Detections documents for a Stream for this
* PAMGuard dataset.
* @author dg50
*
*/
public class StreamDetectionsSummary {
public ArrayList<PDetections> detectionsDocs;
public StreamDetectionsSummary(ArrayList<PDetections> detectionsDocs) {
this.detectionsDocs = detectionsDocs;
}
}

View File

@ -0,0 +1,23 @@
package tethys.niluswraps;
import nilus.Detections;
public class PDetections {
public Detections detections;
public Integer count;
public PDeployment deployment;
public PDetections(Detections detections, PDeployment deployment, Integer count) {
super();
this.detections = detections;
this.deployment = deployment;
this.count = count;
}
}

View File

@ -204,16 +204,16 @@ public class TethysExporter {
// * Outer loop is through deployemnt documents. Will then export detections within each // * Outer loop is through deployemnt documents. Will then export detections within each
// * deployment detector by detector // * deployment detector by detector
// */ // */
for (Deployment aDeployment : deploymentDocs) { // for (Deployment aDeployment : deploymentDocs) {
for (PamDataBlock aDataBlock : allDataBlocks) { // for (PamDataBlock aDataBlock : allDataBlocks) {
StreamExportParams streamExportParams = tethysExportParams.getStreamParams(aDataBlock); // StreamExportParams streamExportParams = tethysExportParams.getStreamParams(aDataBlock);
if (streamExportParams == null || !streamExportParams.selected) { // if (streamExportParams == null || !streamExportParams.selected) {
continue; // not interested in this one. // continue; // not interested in this one.
} // }
detectionsHandler.exportDetections(aDataBlock, aDeployment, // detectionsHandler.exportDetections(aDataBlock, aDeployment,
new DetectionGranularity(GRANULARITY.TIME, 3600*12), tethysExportParams, streamExportParams); // new DetectionGranularity(GRANULARITY.TIME, 3600*12), tethysExportParams, streamExportParams);
} // }
} // }
/* /*
* Then do whatever else is needed to complete the document. * Then do whatever else is needed to complete the document.
*/ */

View File

@ -1,10 +1,16 @@
package tethys.swing; package tethys.swing;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.JTable; import javax.swing.JTable;
import javax.swing.border.TitledBorder; import javax.swing.border.TitledBorder;
@ -12,7 +18,10 @@ import javax.swing.table.AbstractTableModel;
import PamView.tables.SwingTableColumnWidths; import PamView.tables.SwingTableColumnWidths;
import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataBlock;
import nilus.Detections;
import tethys.TethysControl; import tethys.TethysControl;
import tethys.detection.StreamDetectionsSummary;
import tethys.niluswraps.PDetections;
/** /**
* Table of Detections documents for a single PAMGuard datablock. * Table of Detections documents for a single PAMGuard datablock.
@ -33,6 +42,8 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa
private PamDataBlock dataBlock; private PamDataBlock dataBlock;
private StreamDetectionsSummary streamDetectionsSummary;
public DatablockDetectionsPanel(TethysControl tethysControl) { public DatablockDetectionsPanel(TethysControl tethysControl) {
super(tethysControl); super(tethysControl);
mainPanel = new JPanel(new BorderLayout()); mainPanel = new JPanel(new BorderLayout());
@ -46,6 +57,7 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa
new SwingTableColumnWidths(tethysControl.getUnitName() + getClass().getName(), table); new SwingTableColumnWidths(tethysControl.getUnitName() + getClass().getName(), table);
table.addMouseListener(new MouseActions());
} }
@Override @Override
@ -57,16 +69,78 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa
public void selectDataBlock(PamDataBlock dataBlock) { public void selectDataBlock(PamDataBlock dataBlock) {
this.dataBlock = dataBlock; this.dataBlock = dataBlock;
dataBlockName.setText(dataBlock.getLongDataName()); dataBlockName.setText(dataBlock.getLongDataName());
streamDetectionsSummary = getTethysControl().getDetectionsHandler().getStreamDetections(dataBlock);
tableModel.fireTableDataChanged();
}
private class MouseActions extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
showPopupMenu(e);
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
showPopupMenu(e);
}
}
}
public void showPopupMenu(MouseEvent e) {
int row = table.getSelectedRow();
if (row < 0) {
return;
}
PDetections pDets = detectionsForRow(row);
if (pDets == null) {
return;
}
JMenuItem menuItem = new JMenuItem("Delete " + pDets.detections.getId());
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
deleteDocument(pDets);
}
});
JPopupMenu popMenu = new JPopupMenu();
popMenu.add(menuItem);
popMenu.show(e.getComponent(), e.getX(), e.getY());
}
protected void deleteDocument(PDetections pDets) {
getTethysControl().getDbxmlConnect().deleteDocument(pDets.detections);
selectDataBlock(dataBlock); // force table update.
}
private PDetections detectionsForRow(int iRow) {
if (streamDetectionsSummary == null || streamDetectionsSummary.detectionsDocs == null) {
return null;
}
if (iRow < 0 || iRow >= streamDetectionsSummary.detectionsDocs.size()) {
return null;
}
return streamDetectionsSummary.detectionsDocs.get(iRow);
} }
private class TableModel extends AbstractTableModel { private class TableModel extends AbstractTableModel {
private String[] colNames = {"Person", "Name", "Abstract"}; private String[] colNames = {"Document", "Count", "Abstract"};
@Override @Override
public int getRowCount() { public int getRowCount() {
// TODO Auto-generated method stub if (streamDetectionsSummary == null || streamDetectionsSummary.detectionsDocs == null) {
return 0; return 0;
}
return streamDetectionsSummary.detectionsDocs.size();
} }
@Override @Override
@ -81,7 +155,26 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa
@Override @Override
public Object getValueAt(int rowIndex, int columnIndex) { public Object getValueAt(int rowIndex, int columnIndex) {
// TODO Auto-generated method stub PDetections pDets = detectionsForRow(rowIndex);
return getValueAt(pDets, columnIndex);
}
private Object getValueAt(PDetections pDets, int columnIndex) {
if (pDets == null) {
return null;
}
Detections dets = pDets.detections;
if (dets == null) {
return "Error in doc";
}
switch (columnIndex) {
case 0:
return dets.getId();
case 1:
return pDets.count;
case 2:
return dets.getDescription().getAbstract();
}
return null; return null;
} }

View File

@ -55,9 +55,11 @@ public class TethysMainPanel extends TethysGUIPanel {
southEastPanel.add(detectionsExportPanel.getComponent(), BorderLayout.EAST); southEastPanel.add(detectionsExportPanel.getComponent(), BorderLayout.EAST);
splitPane.add(southwestSplit); splitPane.add(southwestSplit);
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
// these only work if called after display is visible
@Override @Override
public void run() { public void run() {
splitPane.setDividerLocation(0.5); splitPane.setDividerLocation(0.5);
southwestSplit.setDividerLocation(0.5);
} }
}); });
} }

View File

@ -0,0 +1,77 @@
package tethys.swing.export;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import PamController.PamControlledUnit;
import PamView.dialog.PamGridBagContraints;
import PamguardMVC.PamDataBlock;
import tethys.TethysControl;
import tethys.detection.DetectionsHandler;
import tethys.output.StreamExportParams;
public class AlgorithmCard extends ExportWizardCard {
private JTextField method, software, version, supportSoftware;
public AlgorithmCard(TethysControl tethysControl, PamDataBlock dataBlock) {
super(tethysControl, "Algorithm", dataBlock);
setBorder(new TitledBorder("Algorithm details"));
method = new JTextField(40);
software = new JTextField(40);
version = new JTextField(40);
supportSoftware = new JTextField(40);
JPanel nPanel = new JPanel(new GridBagLayout());
this.setLayout(new BorderLayout());
this.add(BorderLayout.NORTH, nPanel);
GridBagConstraints c = new PamGridBagContraints();
nPanel.add(new JLabel("Method ", JLabel.LEFT), c);
c.gridy++;
nPanel.add(method, c);
// c.gridx = 0;
c.gridy++;
nPanel.add(new JLabel("Software ", JLabel.LEFT), c);
c.gridy++;
nPanel.add(software, c);
c.gridx = 0;
c.gridy++;
nPanel.add(new JLabel("Version ", JLabel.LEFT), c);
c.gridy++;
nPanel.add(version, c);
c.gridx = 0;
c.gridy++;
nPanel.add(new JLabel("Support Software ", JLabel.LEFT), c);
c.gridy++;
nPanel.add(supportSoftware, c);
c.gridx = 0;
c.gridy++;
method.setEditable(false);
version.setEditable(false);
software.setEditable(false);
supportSoftware.setEditable(false);
}
@Override
public boolean getParams(StreamExportParams streamExportParams) {
// Nothing to actually enter here.
return true;
}
@Override
public void setParams(StreamExportParams streamExportParams) {
PamDataBlock dataBlock = getDataBlock();
DetectionsHandler detHandler = getTethysControl().getDetectionsHandler();
method.setText(detHandler.getMethodString(dataBlock));
software.setText(detHandler.getSoftwareString(dataBlock));
version.setText(detHandler.getVersionString(dataBlock));
supportSoftware.setText(detHandler.getSupportSoftware(dataBlock) + " V" + detHandler.getSupportSoftwareVersion(dataBlock));
}
}

View File

@ -9,6 +9,7 @@ import java.awt.event.ActionListener;
import java.util.ArrayList; import java.util.ArrayList;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JTextArea; import javax.swing.JTextArea;
import javax.swing.border.TitledBorder; import javax.swing.border.TitledBorder;
@ -22,26 +23,37 @@ public class DetectionsExportWizard extends PamDialog {
private PamDataBlock dataBlock; private PamDataBlock dataBlock;
private CardLayout cardLayout; private CardLayout cardLayout;
private JPanel mainPanel; private JPanel cardPanel;
private GranularityCard granularityCard; private GranularityCard granularityCard;
private DescriptionCard descriptionCard; private DescriptionCard descriptionCard;
private JButton prevButton; private JButton prevButton;
private StreamExportParams streamExportParams; private StreamExportParams streamExportParams;
private ArrayList<ExportWizardCard> wizardCards = new ArrayList(); private ArrayList<ExportWizardCard> wizardCards = new ArrayList();
private AlgorithmCard algorithmCard;
private ExportWorkerCard exportWorkerCard;
private DetectionsExportWizard(Window parentFrame, TethysControl tethysControl, PamDataBlock dataBlock) { private DetectionsExportWizard(Window parentFrame, TethysControl tethysControl, PamDataBlock dataBlock) {
super(parentFrame, "Detections Export", false); super(parentFrame, "Detections Export", false);
this.dataBlock = dataBlock; this.dataBlock = dataBlock;
cardLayout = new CardLayout();
mainPanel = new JPanel(cardLayout);
streamExportParams = tethysControl.getTethysExportParams().getStreamParams(dataBlock);
if (streamExportParams == null) {
streamExportParams = new StreamExportParams(dataBlock.getLongDataName(), false);
}
cardLayout = new CardLayout();
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(BorderLayout.NORTH, new ExportStreamInfoPanel(dataBlock));
cardPanel = new JPanel(cardLayout);
mainPanel.add(BorderLayout.CENTER, cardPanel);
addCard(algorithmCard = new AlgorithmCard(tethysControl, dataBlock));
addCard(granularityCard = new GranularityCard(tethysControl, dataBlock)); addCard(granularityCard = new GranularityCard(tethysControl, dataBlock));
addCard(descriptionCard = new DescriptionCard(tethysControl, dataBlock)); addCard(descriptionCard = new DescriptionCard(tethysControl, dataBlock));
addCard(exportWorkerCard = new ExportWorkerCard(tethysControl, dataBlock));
streamExportParams = tethysControl.getTethysExportParams().getStreamParams(dataBlock);
cardLayout.first(mainPanel); cardLayout.first(cardPanel);
setDialogComponent(mainPanel); setDialogComponent(mainPanel);
@ -56,10 +68,12 @@ public class DetectionsExportWizard extends PamDialog {
}); });
setResizable(true); setResizable(true);
// this.get
} }
private void addCard(ExportWizardCard wizPanel) { private void addCard(ExportWizardCard wizPanel) {
mainPanel.add(wizPanel, wizPanel.getTitle()); cardPanel.add(wizPanel, wizPanel.getTitle());
wizardCards.add(wizPanel); wizardCards.add(wizPanel);
} }
@ -73,6 +87,7 @@ public class DetectionsExportWizard extends PamDialog {
for (ExportWizardCard wizCard : wizardCards) { for (ExportWizardCard wizCard : wizardCards) {
wizCard.setParams(streamExportParams); wizCard.setParams(streamExportParams);
} }
enableControls();
// granularityCard.setParams(streamExportParams); // granularityCard.setParams(streamExportParams);
} }
@ -80,7 +95,7 @@ public class DetectionsExportWizard extends PamDialog {
* Called when 'previous' button is clicked. * Called when 'previous' button is clicked.
*/ */
protected void previousButton() { protected void previousButton() {
cardLayout.previous(mainPanel); cardLayout.previous(cardPanel);
enableControls(); enableControls();
} }
@ -89,7 +104,7 @@ public class DetectionsExportWizard extends PamDialog {
int iCard = getCardIndex(); int iCard = getCardIndex();
if (iCard < wizardCards.size()-1) { if (iCard < wizardCards.size()-1) {
if (checkCurrentCard()) { if (checkCurrentCard()) {
cardLayout.next(mainPanel); cardLayout.next(cardPanel);
enableControls(); enableControls();
} }
return false; return false;
@ -123,7 +138,8 @@ public class DetectionsExportWizard extends PamDialog {
int iCard = getCardIndex(); int iCard = getCardIndex();
prevButton.setEnabled(iCard > 0); prevButton.setEnabled(iCard > 0);
boolean isLast = iCard == wizardCards.size()-1; boolean isLast = iCard == wizardCards.size()-1;
getOkButton().setText(isLast ? "Export" : "Next"); getOkButton().setEnabled(!isLast);
// getOkButton().setText(isLast ? "Export" : "Next");
} }
private boolean checkCurrentCard() { private boolean checkCurrentCard() {
@ -135,8 +151,8 @@ public class DetectionsExportWizard extends PamDialog {
} }
private int getCardIndex() { private int getCardIndex() {
for (int i = 0; i < mainPanel.getComponentCount(); i++) { for (int i = 0; i < cardPanel.getComponentCount(); i++) {
Component component = mainPanel.getComponent(i); Component component = cardPanel.getComponent(i);
if (component.isVisible()) { if (component.isVisible()) {
return i; return i;
} }

View File

@ -0,0 +1,95 @@
package tethys.swing.export;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.Enumeration;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.TitledBorder;
import PamUtils.PamCalendar;
import PamView.dialog.PamGridBagContraints;
import PamguardMVC.PamDataBlock;
import dataMap.OfflineDataMap;
public class ExportStreamInfoPanel extends JPanel {
private PamDataBlock dataBlock;
public ExportStreamInfoPanel(PamDataBlock dataBlock) {
this.dataBlock = dataBlock;
setBorder(new TitledBorder("Stream information"));
JPanel infoPanel = new JPanel();
this.setLayout(new BorderLayout());
this.add(BorderLayout.WEST, infoPanel);
infoPanel.setLayout(new GridBagLayout());
GridBagConstraints c = new PamGridBagContraints();
infoPanel.add(new JLabel(dataBlock.getLongDataName(), JLabel.LEFT), c);
c.gridy++;
OfflineDataMap dataMap = dataBlock.getPrimaryDataMap();
if (dataMap == null) {
infoPanel.add(new JLabel("This stream contains no mapped data!!"), c);
return;
}
else {
String mapName = dataMap.getDataMapName();
int nData = dataMap.getDataCount();
int nPoints = dataMap.getNumMapPoints();
if (nPoints == 0) {
infoPanel.add(new JLabel("This stream contains no mapped data!!"), c);
return;
}
long startT = dataMap.getMapStartTime();
long endT = dataMap.getMapEndTime();
String str = String.format("Data stream contains %d data items", nData);
c.gridy++;
infoPanel.add(new JLabel(str, JLabel.LEFT), c);
str = String.format("Between %s and %s UTC", PamCalendar.formatDBDateTime(startT), PamCalendar.formatDBDateTime(endT));
c.gridy++;
infoPanel.add(new JLabel(str, JLabel.LEFT), c);
// for (Enumeration keys = UIManager.getDefaults().keys(); keys.hasMoreElements();) {
// Object key = keys.nextElement();
// Object value = UIManager.get(key);
//// if (key.toLowerCase().contains("frame") )
// String opStr = String.format("key %s value %s", key, value);
// if (opStr.toLowerCase().contains("window") && opStr.toLowerCase().contains("color")) {
// System.out.println(opStr);
// }
// }
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Object titleColour = UIManager.get("window");
if (titleColour instanceof Color) {
setBackground(ExportStreamInfoPanel.this, (Color) titleColour);
}
else {
setBackground(ExportStreamInfoPanel.this, Color.WHITE);
}
}
});
}
}
public void setBackground(Component component, Color bg) {
component.setBackground(bg);
if (component instanceof JComponent) {
JComponent jComponent = (JComponent) component;
int nSub = jComponent.getComponentCount();
for (int i = 0; i < nSub; i++) {
setBackground(jComponent.getComponent(i), bg);
}
}
}
}

View File

@ -0,0 +1,163 @@
package tethys.swing.export;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import PamView.dialog.PamGridBagContraints;
import PamView.panel.PamNorthPanel;
import PamguardMVC.PamDataBlock;
import tethys.TethysControl;
import tethys.TethysState;
import tethys.TethysStateObserver;
import tethys.detection.DetectionExportObserver;
import tethys.detection.DetectionExportProgress;
import tethys.detection.DetectionsHandler;
import tethys.output.StreamExportParams;
public class ExportWorkerCard extends ExportWizardCard implements DetectionExportObserver {
private JProgressBar progressBar;
private JTextField progressText;
private JTextField itemCount, skipCount, projectedCount;
private JButton export, cancel;
private StreamExportParams streamExportParams;
public ExportWorkerCard(TethysControl tethysControl, PamDataBlock dataBlock) {
super(tethysControl, "Export", dataBlock);
setLayout(new BorderLayout());
setBorder(new TitledBorder("Export data"));
JPanel exPanel = new PamNorthPanel(new GridBagLayout());
this.add(BorderLayout.WEST, exPanel);
GridBagConstraints c = new PamGridBagContraints();
progressBar = new JProgressBar();
progressText = new JTextField(30);
itemCount = new JTextField(6);
skipCount = new JTextField(6);
projectedCount = new JTextField(6);
progressText.setEditable(false);
itemCount.setEditable(false);
skipCount.setEditable(false);
projectedCount.setEditable(false);
export = new JButton("Export data");
cancel = new JButton("Cancel export");
cancel.setEnabled(false);
export.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
exportData();
}
});
cancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cancelExport();
}
});
exPanel.add(new JLabel("Items written ", JLabel.RIGHT), c);
c.gridx++;
exPanel.add(itemCount, c);
c.gridx = 0;
c.gridy++;
exPanel.add(new JLabel("Items skipped ", JLabel.RIGHT), c);
c.gridx++;
exPanel.add(skipCount, c);
c.gridx = 0;
c.gridy++;
exPanel.add(new JLabel("Total expected ", JLabel.RIGHT), c);
c.gridx++;
exPanel.add(projectedCount, c);
c.gridx = 0;
c.gridy++;
exPanel.add(new JLabel("Progress ... ", JLabel.RIGHT), c);
c.gridx++;
c.gridwidth = 3;
exPanel.add(progressBar, c);
c.gridy++;
exPanel.add(progressText, c);
c.gridwidth = 1;
c.gridx = 1;
c.gridy++;
exPanel.add(export, c);
c.gridx++;
exPanel.add(cancel, c);
}
protected void exportData() {
DetectionsHandler detHandler = getTethysControl().getDetectionsHandler();
detHandler.startExportThread(getDataBlock(), streamExportParams, this);
enableControls(DetectionExportProgress.STATE_GATHERING);
}
protected void cancelExport() {
DetectionsHandler detHandler = getTethysControl().getDetectionsHandler();
detHandler.cancelExport();
}
@Override
public boolean getParams(StreamExportParams streamExportParams) {
// TODO Auto-generated method stub
return true;
}
@Override
public void setParams(StreamExportParams streamExportParams) {
this.streamExportParams = streamExportParams;
}
@Override
public void update(DetectionExportProgress progress) {
if (progress == null) {
return;
}
if (progress.totalUnits > 0) {
itemCount.setText(String.format("%d", progress.exportCount));
skipCount.setText(String.format("%d", progress.skipCount));
long totExpected = progress.totalUnits;
if (progress.exportCount +progress.skipCount > 0) {
totExpected *= progress.exportCount/(progress.exportCount+progress.skipCount);
}
projectedCount.setText(String.format("%d", totExpected));
itemCount.setText(String.format("%d", totExpected));
long perc = (progress.exportCount+progress.skipCount) * 100 / progress.totalUnits;
progressBar.setValue((int) perc);
}
switch (progress.state) {
case DetectionExportProgress.STATE_GATHERING:
progressText.setText("Running export");
break;
case DetectionExportProgress.STATE_CANCELED:
progressText.setText("Export cancelled");
break;
case DetectionExportProgress.STATE_COMPLETE:
progressText.setText("Export complete");
break;
case DetectionExportProgress.STATE_WRITING:
progressText.setText("Writing to Tethys: " + progress.currentDetections.getId());
break;
}
enableControls(progress.state);
}
private void enableControls(int state) {
boolean stopped = state == DetectionExportProgress.STATE_CANCELED || state == DetectionExportProgress.STATE_COMPLETE;
export.setEnabled(stopped);
cancel.setEnabled(!stopped);
}
}

View File

@ -21,6 +21,7 @@ import org.w3c.dom.Document;
import PamController.settings.output.xml.PamguardXMLWriter; import PamController.settings.output.xml.PamguardXMLWriter;
import PamView.dialog.PamGridBagContraints; import PamView.dialog.PamGridBagContraints;
import PamView.panel.WestAlignedPanel;
import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataBlock;
import PamguardMVC.dataSelector.DataSelectParams; import PamguardMVC.dataSelector.DataSelectParams;
import PamguardMVC.dataSelector.DataSelector; import PamguardMVC.dataSelector.DataSelector;
@ -47,7 +48,7 @@ public class GranularityCard extends ExportWizardCard {
// granularity // granularity
GranularityEnumType[] grans = GranularityEnumType.values(); GranularityEnumType[] grans = GranularityEnumType.values();
granularities = new JRadioButton[grans.length]; granularities = new JRadioButton[grans.length];
JPanel granPanel = new JPanel(new GridBagLayout()); JPanel granPanel = new WestAlignedPanel(new GridBagLayout());
GridBagConstraints c = new PamGridBagContraints(); GridBagConstraints c = new PamGridBagContraints();
granPanel.setBorder(new TitledBorder("Granularity")); granPanel.setBorder(new TitledBorder("Granularity"));
ButtonGroup granGroup = new ButtonGroup(); ButtonGroup granGroup = new ButtonGroup();