GUI Work.

working on some GUI / control options. Semi functional. Seem to have a
problem with time zones converting from XML time to millis which need
sorting.
This commit is contained in:
Douglas Gillespie 2023-03-21 20:05:38 +00:00
parent f51a519d82
commit c7ceba1604
31 changed files with 2423 additions and 237 deletions

View File

@ -45,6 +45,8 @@ public class ArrayDialog extends PamDialog implements ActionListener {
private EnvironmentPanel environmentPanel; private EnvironmentPanel environmentPanel;
private HydrophoneDiagram hydrophoneDiagram; private HydrophoneDiagram hydrophoneDiagram;
private InstrumentIdentityPanel instrumentIdentityPanel;
private JButton okButton, cancelButton; private JButton okButton, cancelButton;
@ -73,6 +75,7 @@ public class ArrayDialog extends PamDialog implements ActionListener {
eastPanel.add(channelPanel.getChannelPanel()); eastPanel.add(channelPanel.getChannelPanel());
environmentPanel = new EnvironmentPanel(this); environmentPanel = new EnvironmentPanel(this);
instrumentIdentityPanel = new InstrumentIdentityPanel();
// eastPanel.add(environmentPanel.getEnvironmentPanel()); // eastPanel.add(environmentPanel.getEnvironmentPanel());
@ -80,6 +83,7 @@ public class ArrayDialog extends PamDialog implements ActionListener {
JPanel westPanel = new JPanel(new BorderLayout()); JPanel westPanel = new JPanel(new BorderLayout());
westPanel.add(BorderLayout.CENTER, hydrophoneDiagram.getPlotPanel()); westPanel.add(BorderLayout.CENTER, hydrophoneDiagram.getPlotPanel());
westPanel.add(BorderLayout.SOUTH, environmentPanel.getEnvironmentPanel()); westPanel.add(BorderLayout.SOUTH, environmentPanel.getEnvironmentPanel());
westPanel.add(BorderLayout.NORTH, instrumentIdentityPanel.getComponent());
splitPanel.add(westPanel); splitPanel.add(westPanel);
@ -150,6 +154,7 @@ public class ArrayDialog extends PamDialog implements ActionListener {
hydrophoneDialogPanel.setParams(selArray); hydrophoneDialogPanel.setParams(selArray);
channelPanel.setParams(); channelPanel.setParams();
hydrophoneDiagram.rePaint(); hydrophoneDiagram.rePaint();
instrumentIdentityPanel.setParams(selArray);
if (selArray != null) { if (selArray != null) {
environmentPanel.setNewSpeed(selArray.getSpeedOfSound()); environmentPanel.setNewSpeed(selArray.getSpeedOfSound());
} }
@ -177,6 +182,7 @@ public class ArrayDialog extends PamDialog implements ActionListener {
array.setSpeedOfSound(environmentPanel.getNewSpeed()); array.setSpeedOfSound(environmentPanel.getNewSpeed());
array.setSpeedOfSoundError(environmentPanel.getNewError()); array.setSpeedOfSoundError(environmentPanel.getNewError());
hydrophoneDialogPanel.getParams(); hydrophoneDialogPanel.getParams();
instrumentIdentityPanel.getParams(array);
if (checkDaqChannels(array) == false) { if (checkDaqChannels(array) == false) {
return false; return false;
@ -256,6 +262,7 @@ public class ArrayDialog extends PamDialog implements ActionListener {
environmentPanel.setNewSpeed(currentArray.getSpeedOfSound()); environmentPanel.setNewSpeed(currentArray.getSpeedOfSound());
environmentPanel.setNewError(currentArray.getSpeedOfSoundError()); environmentPanel.setNewError(currentArray.getSpeedOfSoundError());
} }
instrumentIdentityPanel.setParams(currentArray);
} }
void newChannelSelection() { void newChannelSelection() {

View File

@ -0,0 +1,72 @@
package Array;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import PamView.dialog.PamGridBagContraints;
import PamView.panel.WestAlignedPanel;
/**
* Instrument identity panel, contrians additional fields required by Tethys.
* @author dg50
*
*/
public class InstrumentIdentityPanel {
private JPanel mainPanel;
private JTextField instrumentId;
private JTextField instrumentType;
public InstrumentIdentityPanel() {
mainPanel = new WestAlignedPanel();
mainPanel.setBorder(new TitledBorder("Instrument information"));
mainPanel.setLayout(new GridBagLayout());
GridBagConstraints c = new PamGridBagContraints();
mainPanel.add(new JLabel("Instrument Type ", JLabel.RIGHT), c);
c.gridx++;
mainPanel.add(instrumentType = new JTextField(20), c);
c.gridx = 0;
c.gridy++;
mainPanel.add(new JLabel("Instrument Id ", JLabel.RIGHT), c);
c.gridx++;
mainPanel.add(instrumentId = new JTextField(20), c);
instrumentType.setToolTipText("Instrument type, e.g. Towed array, HARP, EAR, Popup, DMON, Rock Hopper, etc.");
instrumentId.setToolTipText("Instrument identifier, e.g. serial number");
}
public JComponent getComponent() {
return mainPanel;
}
public void setParams(PamArray currentArray) {
if (currentArray == null) {
currentArray = ArrayManager.getArrayManager().getCurrentArray();
}
if (currentArray == null) {
return;
}
instrumentType.setText(currentArray.getInstrumentType());
instrumentId.setText(currentArray.getInstrumentId());
}
public void getParams(PamArray currentArray) {
if (currentArray == null) {
currentArray = ArrayManager.getArrayManager().getCurrentArray();
}
if (currentArray == null) {
return;
}
currentArray.setInstrumentType(instrumentType.getText());
currentArray.setInstrumentId(instrumentId.getText());
}
}

View File

@ -90,6 +90,32 @@ public class PamArray implements Serializable, Cloneable, ManagedParameters {
private String arrayName; private String arrayName;
private String arrayFile; private String arrayFile;
/**
* Type, used for Tethys and other meta data control
*/
private String instrumentType;
public String getInstrumentType() {
return instrumentType;
}
public void setInstrumentType(String instrumentType) {
this.instrumentType = instrumentType;
}
public String getInstrumentId() {
return instrumentId;
}
public void setInstrumentId(String instrumentId) {
this.instrumentId = instrumentId;
}
/**
* Array Id. Can be anything. Compulsory for Tethys.
*/
private String instrumentId;
// private int originInterpolation = ORIGIN_USE_LATEST; // private int originInterpolation = ORIGIN_USE_LATEST;
private int originInterpolation = ORIGIN_USE_PRECEEDING; private int originInterpolation = ORIGIN_USE_PRECEEDING;

View File

@ -56,25 +56,25 @@ public class DeploymentData implements Serializable, Cloneable, ManagedParameter
*/ */
private String cruise; private String cruise;
/** // /**
* On what platform is the instrument deployed? (e.g. mooring, tag) // * On what platform is the instrument deployed? (e.g. mooring, tag)
*/ // */
private String platform = "Unknown"; // private String platform = "Unknown";
/** /**
* Name of geographic region. * Name of geographic region.
*/ */
private String region; private String region;
/** // /**
* Instrument type, e.g. HARP, EAR, Popup, DMON, etc. // * Instrument type, e.g. HARP, EAR, Popup, DMON, etc.
*/ // */
private String instrumentType; // private String instrumentType;
//
/** // /**
* Instrument identifier, e.g. serial number // * Instrument identifier, e.g. serial number
*/ // */
private String instrumentId; // private String instrumentId;
public DeploymentData() { public DeploymentData() {
} }
@ -207,19 +207,19 @@ public class DeploymentData implements Serializable, Cloneable, ManagedParameter
this.cruise = cruise; this.cruise = cruise;
} }
/** // /**
* @return the platform // * @return the platform
*/ // */
public String getPlatform() { // public String getPlatform() {
return platform; // return platform;
} // }
//
/** // /**
* @param platform the platform to set // * @param platform the platform to set
*/ // */
public void setPlatform(String platform) { // public void setPlatform(String platform) {
this.platform = platform; // this.platform = platform;
} // }
/** /**
* @return the region * @return the region
@ -235,32 +235,32 @@ public class DeploymentData implements Serializable, Cloneable, ManagedParameter
this.region = region; this.region = region;
} }
/** // /**
* @return the instrumentType // * @return the instrumentType
*/ // */
public String getInstrumentType() { // public String getInstrumentType() {
return instrumentType; // return instrumentType;
} // }
//
/** // /**
* @param instrumentType the instrumentType to set // * @param instrumentType the instrumentType to set
*/ // */
public void setInstrumentType(String instrumentType) { // public void setInstrumentType(String instrumentType) {
this.instrumentType = instrumentType; // this.instrumentType = instrumentType;
} // }
//
/** // /**
* @return the instrumentId // * @return the instrumentId
*/ // */
public String getInstrumentId() { // public String getInstrumentId() {
return instrumentId; // return instrumentId;
} // }
//
/** // /**
* @param instrumentId the instrumentId to set // * @param instrumentId the instrumentId to set
*/ // */
public void setInstrumentId(String instrumentId) { // public void setInstrumentId(String instrumentId) {
this.instrumentId = instrumentId; // this.instrumentId = instrumentId;
} // }
} }

View File

@ -4,6 +4,7 @@ import java.awt.Desktop;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
@ -12,19 +13,28 @@ import java.util.ArrayList;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JMenu; import javax.swing.JMenu;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import PamController.PamControlledUnit; import PamController.PamControlledUnit;
import PamController.PamControlledUnitSettings;
import PamController.PamController; import PamController.PamController;
import PamController.PamSettingManager;
import PamController.PamSettings;
import PamView.PamTabPanel; import PamView.PamTabPanel;
import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataBlock;
import metadata.MetaDataContol; import metadata.MetaDataContol;
import metadata.deployment.DeploymentData; import metadata.deployment.DeploymentData;
import nilus.Deployment.Instrument; import pamViewFX.PamSettingsMenuPane;
import tethys.TethysState.StateType;
import tethys.dbxml.DBXMLConnect; import tethys.dbxml.DBXMLConnect;
import tethys.dbxml.DBXMLQueries; import tethys.dbxml.DBXMLQueries;
import tethys.dbxml.ServerStatus;
import tethys.deployment.DeploymentHandler;
import tethys.detection.DetectionsHandler;
import tethys.niluswraps.PDeployment;
import tethys.output.DatablockSynchInfo;
//import nilus.Deployment; //import nilus.Deployment;
//import nilus.Deployment.Instrument;
import tethys.output.StreamExportParams;
import tethys.output.TethysExportParams; import tethys.output.TethysExportParams;
import tethys.output.TethysExporter; import tethys.output.TethysExporter;
import tethys.output.swing.TethysExportDialog; import tethys.output.swing.TethysExportDialog;
@ -37,13 +47,12 @@ import tethys.swing.TethysTabPanel;
* @author dg50 * @author dg50
* *
*/ */
public class TethysControl extends PamControlledUnit { public class TethysControl extends PamControlledUnit implements PamSettings, TethysStateObserver {
public static final String unitType = "Tethys Interface"; public static final String unitType = "Tethys Interface";
public static String defaultName = "Tethys"; public static String defaultName = "Tethys";
public static String xmlNameSpace = "http://tethys.sdsu.edu/schema/1.0"; public static String xmlNameSpace = "http://tethys.sdsu.edu/schema/1.0";
private TethysExportParams tethysExportParams = new TethysExportParams(); private TethysExportParams tethysExportParams = new TethysExportParams();
private DBXMLConnect dbxmlConnect; private DBXMLConnect dbxmlConnect;
@ -53,12 +62,40 @@ public class TethysControl extends PamControlledUnit {
private DBXMLQueries dbxmlQueries; private DBXMLQueries dbxmlQueries;
private ArrayList<TethysStateObserver> stateObservers; private ArrayList<TethysStateObserver> stateObservers;
private Timer serverCheckTimer;
private ServerStatus lastServerStatus;
private ArrayList<DatablockSynchInfo> dataBlockSynchInfos;
private DeploymentHandler deploymentHandler;
public TethysControl(String unitName) { public TethysControl(String unitName) {
super(unitType, unitName); super(unitType, unitName);
stateObservers = new ArrayList(); stateObservers = new ArrayList();
dbxmlConnect = new DBXMLConnect(this); dbxmlConnect = new DBXMLConnect(this);
dbxmlQueries = new DBXMLQueries(this); dbxmlQueries = new DBXMLQueries(this);
deploymentHandler = new DeploymentHandler(this);
serverCheckTimer = new Timer(10000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
checkServer();
}
});
serverCheckTimer.setInitialDelay(0);
PamSettingManager.getInstance().registerSettings(this);
addStateObserver(this);
if (PamController.getInstance().isInitializationComplete()) {
// must be adding module later on ...
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
initializationStuff();
}
});
}
} }
/** /**
@ -91,7 +128,60 @@ public class TethysControl extends PamControlledUnit {
tethysMenu.add(openClient); tethysMenu.add(openClient);
return tethysMenu; return tethysMenu;
} }
public ArrayList<PamDataBlock> getExportableDataBlocks() {
ArrayList<PamDataBlock> sets = new ArrayList<>();
ArrayList<PamDataBlock> allDataBlocks = PamController.getInstance().getDataBlocks();
for (PamDataBlock aDataBlock : allDataBlocks) {
if (aDataBlock.getTethysDataProvider() != null) {
sets.add(aDataBlock);
}
}
return sets;
}
/**
* Get the synchronisation info for all datablocks.
* This list should be static, but check it in case something has been
* added or removed.
* @return
*/
public ArrayList<DatablockSynchInfo> getSynchronisationInfos() {
if (dataBlockSynchInfos == null) {
dataBlockSynchInfos = new ArrayList<>();
}
ArrayList<PamDataBlock> dataBlocks = getExportableDataBlocks();
// check all datablocks are in there ...
for (PamDataBlock aBlock : dataBlocks) {
if (findDatablockSynchInfo(aBlock) == null) {
dataBlockSynchInfos.add(new DatablockSynchInfo(this, aBlock));
}
}
// and remove any which are no longer there.
for (DatablockSynchInfo synchInfo : dataBlockSynchInfos) {
if (dataBlocks.contains(synchInfo.getDataBlock()) == false) {
dataBlockSynchInfos.remove(synchInfo);
}
}
return dataBlockSynchInfos;
}
public DatablockSynchInfo findDatablockSynchInfo(PamDataBlock dataBlock) {
if (dataBlockSynchInfos == null) {
return null;
}
for (DatablockSynchInfo synchInfo : dataBlockSynchInfos) {
if (synchInfo.getDataBlock() == dataBlock) {
return synchInfo;
}
}
return null;
}
/**
* open client in the default web browser
*/
protected void openTethysClient() { protected void openTethysClient() {
String urlString = tethysExportParams.getFullServerName() + "/Client"; String urlString = tethysExportParams.getFullServerName() + "/Client";
System.out.println("Opening url " + urlString); System.out.println("Opening url " + urlString);
@ -148,8 +238,17 @@ public class TethysControl extends PamControlledUnit {
private void exportTethysData(TethysExportParams tethysExportParams) { private void exportTethysData(TethysExportParams tethysExportParams) {
TethysExporter tethysExporter = new TethysExporter(this, tethysExportParams); TethysExporter tethysExporter = new TethysExporter(this, tethysExportParams);
tethysExporter.doExport(); tethysExporter.doExport();
sendStateUpdate(new TethysState(StateType.TRANSFERDATA));
countProjectDetections();
sendStateUpdate(new TethysState(StateType.NEWPAMGUARDSELECTION));
} }
/**
* Get global deployment data. This is a bit of a mess, trying to use a separate module
* so that the rest of PAMGuard can use it, but creating the
* @return
*/
public DeploymentData getGlobalDeplopymentData() { public DeploymentData getGlobalDeplopymentData() {
PamControlledUnit aUnit = PamController.getInstance().findControlledUnit(MetaDataContol.class, null); PamControlledUnit aUnit = PamController.getInstance().findControlledUnit(MetaDataContol.class, null);
// if (aUnit instanceof MetaDataContol == false || true) { // if (aUnit instanceof MetaDataContol == false || true) {
@ -163,20 +262,29 @@ public class TethysControl extends PamControlledUnit {
// } // }
MetaDataContol metaControl = (MetaDataContol) aUnit; MetaDataContol metaControl = (MetaDataContol) aUnit;
DeploymentData deploymentData = metaControl != null ? metaControl.getDeploymentData() : new DeploymentData(); DeploymentData deploymentData = metaControl != null ? metaControl.getDeploymentData() : getTethysProjectData();
deploymentData.setProject("thisIsAProject"); // deploymentData.setProject("thisIsAProject");
deploymentData.setPlatform("Yay a platform"); //// deploymentData.setPlatform("Yay a platform");
deploymentData.setCruise("cruisey"); // deploymentData.setCruise("cruisey");
deploymentData.setDeploymentId(142536); // deploymentData.setDeploymentId(142536);
deploymentData.setInstrumentId("super instrument"); //// deploymentData.setInstrumentId("super instrument");
deploymentData.setSite("in the ocean somewhere"); // deploymentData.setSite("in the ocean somewhere");
deploymentData.setRegion("ocean water"); // deploymentData.setRegion("ocean water");
deploymentData.setInstrumentType("sensor of sorts"); //// deploymentData.setInstrumentType("sensor of sorts");
return deploymentData; return deploymentData;
} }
/**
* Gets a copy of Deployment data stored with other Tethys params when the more
* general meta data provider is not present.
* @return
*/
private DeploymentData getTethysProjectData() {
return tethysExportParams.getProjectData();
}
/** /**
* Add a new state observer. * Add a new state observer.
* @param stateObserver * @param stateObserver
@ -215,4 +323,98 @@ public class TethysControl extends PamControlledUnit {
return dbxmlQueries; return dbxmlQueries;
} }
@Override
public void notifyModelChanged(int changeType) {
super.notifyModelChanged(changeType);
switch (changeType) {
case PamController.INITIALIZATION_COMPLETE:
initializationStuff();
break;
}
}
/**
* Stuff to do on initial load (initialization complete or addition of
* a Tethys module after initialisation).
*/
private void initializationStuff() {
deploymentHandler.createPamguardOverview();
serverCheckTimer.start();
updateState(new TethysState(StateType.NEWPAMGUARDSELECTION));
}
/**
* Check the server. This will send around a notification if the state
* has changed since the last call to this function, so it's unlikely you'll
* need to use the return value
* @return server status.
*/
public ServerStatus checkServer() {
ServerStatus serverState = dbxmlConnect.pingServer();
if (lastServerStatus == null || lastServerStatus.ok != serverState.ok) {
sendStateUpdate(new TethysState(StateType.UPDATESERVER));
}
lastServerStatus = serverState;
return serverState;
}
@Override
public Serializable getSettingsReference() {
return tethysExportParams;
}
@Override
public long getSettingsVersion() {
return TethysExportParams.serialVersionUID;
}
@Override
public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
tethysExportParams = (TethysExportParams) pamControlledUnitSettings.getSettings();
return true;
}
@Override
public void updateState(TethysState tethysState) {
switch (tethysState.stateType) {
case NEWPROJECTSELECTION:
countProjectDetections();
break;
}
}
private void countProjectDetections() {
if (dataBlockSynchInfos == null) {
return;
}
DeploymentData deplData = getGlobalDeplopymentData();
String[] dataPrefixes = new String[dataBlockSynchInfos.size()];
int i = 0;
ArrayList<PDeployment> matchedDeployments = deploymentHandler.getMatchedDeployments();
for (DatablockSynchInfo synchInfo : dataBlockSynchInfos) {
// dataPrefixes[i] = DetectionsHandler.getDetectionsDocIdPrefix(deplData.getProject(), synchInfo.getDataBlock());
int count = 0;
for (PDeployment pDepl : matchedDeployments) {
count += dbxmlQueries.countData(synchInfo.getDataBlock(), pDepl.deployment.getId());
}
synchInfo.setDataCount(count);
i++;
}
// int[] counts = dbxmlQueries.countDataForProject(deplData.getProject(), dataPrefixes);
// if (counts != null) {
// for ( i = 0; i < counts.length; i++ ) {
// dataBlockSynchInfos.get(i).setDataCount(counts[i]);
// }
// }
}
/**
* One stop place to get Deployment information. Will provide
* both information on record periods in PAMGuard and also Deployment docs in Tethys.
* @return set of functions for handling deployments.
*/
public DeploymentHandler getDeploymentHandler() {
return deploymentHandler;
}
} }

View File

@ -0,0 +1,61 @@
package tethys;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import tethys.niluswraps.PDeployment;
/*
* Some standard meny dirven functions which we may want to call from
* a few different places.
*/
public class TethysMenuActions {
private TethysControl tethysControl;
public TethysMenuActions(TethysControl tethysControl) {
super();
this.tethysControl = tethysControl;
}
public void deploymentMouseActions(MouseEvent e, PDeployment pDeployment) {
ArrayList<String> detDocNames = tethysControl.getDbxmlQueries().getDetectionsDocsIds(pDeployment.deployment.getId());
// System.out.println("Detections for deployment " + pDeployment.deployment.getId());
// for (String detName : detDocNames) {
// System.out.println(detName);
// }
JPopupMenu menu = new JPopupMenu();
if (detDocNames.size() == 0) {
JMenuItem menuItem = new JMenuItem("Delete deployment " + pDeployment.deployment.getId());
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
deleteDeployment(pDeployment);
}
});
menu.add(menuItem);
}
else {
String str = String.format("Delete deployment %s and %d Detections documents", pDeployment.deployment.getId(), detDocNames.size());
JMenuItem menuItem = new JMenuItem(str);
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
deleteDeployment(pDeployment);
}
});
menu.add(menuItem);
}
menu.show(e.getComponent(), e.getX(), e.getY());
}
protected void deleteDeployment(PDeployment pDeployment) {
tethysControl.getDbxmlConnect().deleteDeployment(pDeployment.deployment.getId());
}
}

View File

@ -8,7 +8,12 @@ package tethys;
*/ */
public class TethysState { public class TethysState {
public enum StateType {UPDATESERVER, TRANSFERDATA}; public enum StateType {UPDATESERVER, // Server connection or status has changed
TRANSFERDATA, // data have been transferred from PAMGuard to Tethys
NEWPROJECTSELECTION, // a new Tethys project has been selected in the GUI
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!)
};
public StateType stateType; public StateType stateType;

View File

@ -1,11 +1,18 @@
package tethys; package tethys;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.TimeZone;
import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.datatype.XMLGregorianCalendar;
import PamUtils.PamCalendar;
public class TethysTimeFuncs { public class TethysTimeFuncs {
/* /*
@ -36,4 +43,43 @@ public class TethysTimeFuncs {
GregorianCalendar gc2 = xmlGregorian.toGregorianCalendar(); GregorianCalendar gc2 = xmlGregorian.toGregorianCalendar();
return gc2.getTimeInMillis(); return gc2.getTimeInMillis();
} }
/**
* Make a Gregorian calendar object from a returned XML string.
* @param gregorianString
* @return
*/
public static XMLGregorianCalendar fromGregorianXML(String gregorianString) {
// typical string is 2018-10-20T00:00:00Z
if (gregorianString == null) {
return null;
}
// GregorianCalendar gCal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
gregorianString = gregorianString.replace("T", " ");
gregorianString = gregorianString.replace("Z", "");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = null;
try {
date = df.parse(gregorianString);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
return xmlGregCalFromMillis(date.getTime());
// gCal.setTimeInMillis(date.getTime());
//// gCal.se
// return gCal;
}
public static String formatGregorianTime(XMLGregorianCalendar gregCal) {
if (gregCal == null) {
return null;
}
Long millis = millisFromGregorianXML(gregCal);
if (millis == null) {
return gregCal.toString();
}
return PamCalendar.formatDBDateTime(millis);
}
} }

View File

@ -0,0 +1,26 @@
package tethys.dbxml;
public class DBQueryResult {
public long queryTimeMillis;
public String queryResult;
public String schemaPlan;
public Exception queryException;
public DBQueryResult(long queryTimeMillis, String queryResult, String schemaPlan) {
super();
this.queryTimeMillis = queryTimeMillis;
this.queryResult = queryResult;
this.schemaPlan = schemaPlan;
}
public DBQueryResult(long queryTimeMillis, Exception queryException) {
super();
this.queryTimeMillis = queryTimeMillis;
this.queryException = queryException;
}
}

View File

@ -2,6 +2,7 @@ package tethys.dbxml;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.xml.bind.JAXBException; import javax.xml.bind.JAXBException;
@ -58,7 +59,7 @@ public class DBXMLConnect {
fileError = Importer.ImportFiles(params.getFullServerName(), collection, fileError = Importer.ImportFiles(params.getFullServerName(), collection,
new String[] { tempFile.toString() }, "", "", false); new String[] { tempFile.toString() }, "", "", false);
System.out.println(fileError); // System.out.println(fileError);
tempFile.toFile().deleteOnExit(); tempFile.toFile().deleteOnExit();
} }
@ -77,11 +78,11 @@ public class DBXMLConnect {
} }
/** /**
* get tethys collection name from nilus collection objects * get Tethys collection name from nilus collection objects
* @param className nilus object Class Name * @param className nilus object Class Name
* @return name of Tethys collection * @return name of Tethys collection
*/ */
private String getTethysCollection(String className) { public String getTethysCollection(String className) {
switch(className) { switch(className) {
case "nilus.Deployment": case "nilus.Deployment":
return "Deployments"; return "Deployments";
@ -106,6 +107,44 @@ public class DBXMLConnect {
} }
} }
/**
* Delete a Deploymnet and any contained Detections document. Doesn't work !
* @param deploymentId
* @return
*/
public boolean deleteDeployment(String deploymentId) {
ArrayList<String> detDocNames = tethysControl.getDbxmlQueries().getDetectionsDocsIds(deploymentId);
JerseyClient jerseyClient = null;
try {
jerseyClient = new JerseyClient(tethysControl.getTethysExportParams().getFullServerName());
}
catch (Exception e) {
e.printStackTrace();
return false;
}
String result;
for (int i = 0; i < detDocNames.size(); i++) {
try {
System.out.println("Delete " + detDocNames.get(i));
result = jerseyClient.removeDocument("Detections", detDocNames.get(i));
}
catch (Exception e) {
e.printStackTrace();
// return false;
// break;
}
}
try {
result = jerseyClient.removeDocument("Deployments", deploymentId);
}
catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public boolean openDatabase() { public boolean openDatabase() {
return true; return true;
@ -117,7 +156,7 @@ public class DBXMLConnect {
/** /**
* Get the server state via a ping ? * Get the server state via a ping ?
* @return String descritption of state ? * @return Server state ?
*/ */
public ServerStatus pingServer() { public ServerStatus pingServer() {
JerseyClient jerseyClient = new JerseyClient(tethysControl.getTethysExportParams().getFullServerName()); JerseyClient jerseyClient = new JerseyClient(tethysControl.getTethysExportParams().getFullServerName());

View File

@ -4,6 +4,7 @@ import java.io.StringReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
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;
@ -13,12 +14,20 @@ 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 PamController.settings.output.xml.PamguardXMLWriter;
import PamguardMVC.PamDataBlock;
import dbxml.JerseyClient; import dbxml.JerseyClient;
import nilus.Deployment;
import nilus.Deployment.Instrument;
import nilus.DeploymentRecoveryDetails;
import nilus.Helper;
import tethys.TethysControl; import tethys.TethysControl;
import tethys.TethysTimeFuncs;
import tethys.niluswraps.PDeployment;
import tethys.output.TethysExportParams; import tethys.output.TethysExportParams;
/** /**
* Some standard queries we're going to want to make from various * Some standard queries we're going to want to make from various
* parts of the system as the user interracts with the GUI. * parts of the system as the user interracts with the GUI.
* @author dg50 * @author dg50
* *
@ -32,37 +41,57 @@ public class DBXMLQueries {
this.tethysControl = tethysControl; this.tethysControl = tethysControl;
} }
public ArrayList<String> getProjectNames() { /**
* Execute a DBXML query. Returns an object which included the time
* taken to execute the query and either a returned Document or an Exception.
* Or will return null if the server is not connected
* @param jsonQueryString
* @return query result
*/
private DBQueryResult executeQuery(String jsonQueryString) {
long t1 = System.currentTimeMillis();
DBXMLConnect dbxmlConnect = tethysControl.getDbxmlConnect(); DBXMLConnect dbxmlConnect = tethysControl.getDbxmlConnect();
ServerStatus serverStatus = dbxmlConnect.pingServer(); ServerStatus serverStatus = dbxmlConnect.pingServer();
if (serverStatus.ok == false) { if (!serverStatus.ok) {
return null; return null;
} }
Document doc = null;
String queryResult = null;
String schemaPlan = null;
TethysExportParams params = tethysControl.getTethysExportParams(); TethysExportParams params = tethysControl.getTethysExportParams();
try { try {
JerseyClient jerseyClient = new JerseyClient(params.getFullServerName()); JerseyClient jerseyClient = new JerseyClient(params.getFullServerName());
String testJson = "{\"return\":[\"Deployment/Project\"],\"select\":[],\"enclose\":1}"; queryResult = jerseyClient.queryJSON(jsonQueryString, 0);
// web browse to http://localhost:9779/Client schemaPlan = jerseyClient.queryJSON(jsonQueryString, 1);
String testResult = jerseyClient.queryJSON(testJson);
doc = convertStringToXMLDocument(testResult);
} }
catch (Exception e) { catch (Exception e) {
e.printStackTrace(); return new DBQueryResult(System.currentTimeMillis()-t1, e);
} }
if (doc == null) { return new DBQueryResult(System.currentTimeMillis()-t1, queryResult, schemaPlan);
}
public ArrayList<String> getProjectNames() {
String projectQuery = "{\"return\":[\"Deployment/Project\"],\"select\":[],\"enclose\":1}";
DBQueryResult result = executeQuery(projectQuery);
if (result == null || result.queryResult == null) {
return null; return null;
} }
// System.out.println("Project query execution time millis = " + result.queryTimeMillis);
ArrayList<String> projectNames = new ArrayList<>(); ArrayList<String> projectNames = new ArrayList<>();
// iterate through the document and make a list of names, then make them unique. // iterate through the document and make a list of names, then make them unique.
/* looking for elements like this: /* looking for elements like this:
* *
* check out the jaxb unmarshaller ... * check out the jaxb unmarshaller ...
<Return> <Return>
<Deployment> <Deployment>
@ -70,8 +99,12 @@ public class DBXMLQueries {
</Deployment> </Deployment>
</Return> </Return>
*/ */
Document doc = convertStringToXMLDocument(result.queryResult);
if (doc == null) {
return null;
}
NodeList returns = doc.getElementsByTagName("Return"); NodeList returns = doc.getElementsByTagName("Return");
// System.out.println("N projects = " + returns.getLength()); // System.out.println("N projects = " + returns.getLength());
int n = returns.getLength(); int n = returns.getLength();
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
Node aNode = returns.item(i); Node aNode = returns.item(i);
@ -84,19 +117,316 @@ public class DBXMLQueries {
Element projEl = (Element) ((Element) depEl).getFirstChild(); Element projEl = (Element) ((Element) depEl).getFirstChild();
String projName = projEl.getTextContent(); String projName = projEl.getTextContent();
if (projName != null) { if (projName != null) {
if (projectNames.contains(projName) == false) { if (!projectNames.contains(projName)) {
projectNames.add(projName); projectNames.add(projName);
} }
} }
} }
} }
} }
Collections.sort(projectNames); Collections.sort(projectNames);
return projectNames; return projectNames;
} }
/**
* Get some basic (not all) data for deployments associated with a project.
* @param projectName
* @return
*/
public ArrayList<nilus.Deployment> getProjectDeployments(String projectName) {
String qBase = "{\"return\":[\"Deployment\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Deployment/Project\",\"%s\"],\"optype\":\"binary\"}],\"enclose\":1}";
String qStr = String.format(qBase, projectName);
DBQueryResult result = executeQuery(qStr);
if (result == null) {
return null;
}
// System.out.println("Deployment query execution time millis = " + result.queryTimeMillis);
PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
Document doc = convertStringToXMLDocument(result.queryResult);
if (doc == null) {
return null;
}
// System.out.println(pamXMLWriter.getAsString(doc));
ArrayList<Deployment> deployments = new ArrayList<>();
NodeList returns = doc.getElementsByTagName("Return");
// System.out.println("N projects = " + returns.getLength());
int n = returns.getLength();
for (int i = 0; i < n; i++) {
Node aNode = returns.item(i);
if (aNode instanceof Element) {
Element returnedEl = (Element) aNode;
String Id = getElementData(returnedEl, "Id");
String project = getElementData(returnedEl, "Project");
String DeploymentId = getElementData(returnedEl, "DeploymentId");
String instrType = getElementData(returnedEl, "Instrument.Type");
String instrId = getElementData(returnedEl, "Instrument.InstrumentId");
String geometry = getElementData(returnedEl, "Instrument.GeometryType");
String audioStart = getElementData(returnedEl, "DeploymentDetails.AudioTimeStamp");
String audioEnd = getElementData(returnedEl, "RecoveryDetails.AudioTimeStamp");
String region = getElementData(returnedEl, "Region");
Deployment deployment = new Deployment();
try {
Helper.createRequiredElements(deployment);
} catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
deployment.setId(Id);
deployment.setProject(projectName);
deployment.setDeploymentId(Integer.valueOf(DeploymentId));
XMLGregorianCalendar gcStart = TethysTimeFuncs.fromGregorianXML(audioStart);
XMLGregorianCalendar gcEnd = TethysTimeFuncs.fromGregorianXML(audioEnd);
// System.out.printf("Converted %s to %s\n", audioStart,
// PamCalendar.formatDBDateTime(TethysTimeFuncs.millisFromGregorianXML(gcStart), true));
deployment.getDeploymentDetails().setAudioTimeStamp(gcStart);
if (deployment.getRecoveryDetails() == null) {
deployment.setRecoveryDetails(new DeploymentRecoveryDetails());
}
deployment.getRecoveryDetails().setAudioTimeStamp(gcEnd);
if (instrType != null || instrId != null) {
Instrument instrument = new Instrument();
instrument.setType(instrType);
instrument.setInstrumentId(instrId);
instrument.setGeometryType(geometry);
deployment.setInstrument(instrument);
}
deployment.setRegion(region);
deployments.add(deployment);
}
}
return deployments;
}
public int countData(PamDataBlock dataBlock, String deploymentId) {
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 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 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 = convertStringToXMLDocument(queryResult.queryResult);
if (doc == null) {
return 0;
}
int count = 0;
NodeList returns = doc.getElementsByTagName("Return");
for (int i = 0; i < returns.getLength(); i++) {
Node aNode = returns.item(i);
String docName = aNode.getTextContent();
// System.out.println(aNode.getTextContent());
count += countDetecionsData(docName);
}
return count;
}
/**
* Count the data in a detections document.
* @param detectionDocId
* @return count of on effort detections in document.
*/
private int countDetecionsData(String detectionDocId) {
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}";
String query = queryBase.replace("DetectionsDocName", detectionDocId);
DBQueryResult queryResult = executeQuery(query);
Document doc = convertStringToXMLDocument(queryResult.queryResult);
if (doc == null) {
return 0;
}
NodeList returns = doc.getElementsByTagName("Start");
return returns.getLength();
}
/**
* 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();
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;
}
/**
* Get a count of the detections in a detections document.
* Only looking in onEffort so far.
* @param deploymentId
* @param detectionDocId
* @param dataBlock
* @return
*/
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++) {
n[i] += newN[i];
}
}
return n;
}
/**
* Count data within a deployment document which is associated with a set of datablocks
* Since the detections all come back in one query, it's easier to count all datablocks at once so
* that it can all happen off a single query.
* @param id
* @param dataBlockPrefixes
* @return
*/
private int[] countDataForDeployment(String projectId, String deploymentId, String[] dataPrefixes) {
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/OnEffort/Detection/Start\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"ReplaceDeploymentIdString\"],\"optype\":\"binary\"}],\"enclose\":1}";
String queryString = queryBase.replace("ReplaceDeploymentIdString", deploymentId);
DBQueryResult result = executeQuery(queryString);
if (result == null || result.queryResult == null) {
return null;
}
PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
Document doc = convertStringToXMLDocument(result.queryResult);
if (doc == null) {
return null;
}
// System.out.println(pamXMLWriter.getAsString(doc));
NodeList detsDocs = doc.getElementsByTagName("Detections");
int[] blockCounts = new int[dataPrefixes.length];
// String detDocPrefix = projectId + "_" + dataBlock.getDataName();
// int totalCalls = 0;
int detCount = 0;
int dataIndex;
for (int i = 0; i < detsDocs.getLength(); i++) {
Node detNode = detsDocs.item(i);
NodeList childNodes = detNode.getChildNodes();
detCount = childNodes.getLength()-1;
dataIndex = -1;
for (int n = 0; n < childNodes.getLength(); n++) {
Node aNode = childNodes.item(n);
if (aNode instanceof Element) {
Element el = (Element) aNode;
String nodeName = el.getNodeName();
if (nodeName.equals("Id")) {
String id = el.getTextContent();
for (int j = 0; j < dataPrefixes.length; j++) {
if (id != null && id.startsWith(dataPrefixes[j])) {
dataIndex = j;
}
}
// if (id != null && id.startsWith(detDocPrefix) == false) {
// detCount = 0;
// break;
// }
}
}
}
if (dataIndex >= 0) {
blockCounts[dataIndex] += detCount;
}
// System.out.printf("%d Added %d for new total %d\n",i, detCount, totalCalls);
}
return blockCounts;
}
private String getElementData(Element root, String elName) {
String[] tree = elName.split("\\.");
for (String element : tree) {
NodeList nodeList = root.getElementsByTagName(element);
// should only be one node for what we're unpacking.
if (nodeList == null || nodeList.getLength() == 0) {
return null;
}
Node firstNode = nodeList.item(0);
if (firstNode instanceof Element) {
root = (Element) firstNode;
}
}
return root.getTextContent();
}
private Document convertStringToXMLDocument(String xmlString) { private Document convertStringToXMLDocument(String xmlString) {
//Parser that produces DOM object trees from XML content //Parser that produces DOM object trees from XML content
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

View File

@ -21,12 +21,17 @@ import Array.Streamer;
import Array.ThreadingHydrophoneLocator; import Array.ThreadingHydrophoneLocator;
import PamController.PamControlledUnit; import PamController.PamControlledUnit;
import PamController.PamController; import PamController.PamController;
import PamUtils.PamUtils;
import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataBlock;
import SoundRecorder.RecordingInfo;
import javafx.scene.chart.PieChart.Data; import javafx.scene.chart.PieChart.Data;
import metadata.MetaDataContol; import metadata.MetaDataContol;
import metadata.deployment.DeploymentData; import metadata.deployment.DeploymentData;
import nilus.Audio; import nilus.Audio;
import nilus.ChannelInfo; import nilus.ChannelInfo;
import nilus.ChannelInfo.DutyCycle;
import nilus.ChannelInfo.DutyCycle.Regimen.RecordingDurationS;
import nilus.ChannelInfo.DutyCycle.Regimen.RecordingIntervalS;
import nilus.ChannelInfo.Sampling; import nilus.ChannelInfo.Sampling;
import nilus.ChannelInfo.Sampling.Regimen; import nilus.ChannelInfo.Sampling.Regimen;
import nilus.Deployment; import nilus.Deployment;
@ -37,30 +42,89 @@ import nilus.DeploymentRecoveryDetails;
import nilus.GeometryTypeM; import nilus.GeometryTypeM;
import nilus.Helper; import nilus.Helper;
import pamMaths.PamVector; import pamMaths.PamVector;
import pamMaths.STD;
import tethys.TethysControl; import tethys.TethysControl;
import tethys.TethysLocationFuncs; import tethys.TethysLocationFuncs;
import tethys.TethysState;
import tethys.TethysStateObserver;
import tethys.TethysTimeFuncs; import tethys.TethysTimeFuncs;
import tethys.niluswraps.PDeployment;
/** /**
* Functions to gather data for the deployment document from all around PAMGuard. * Functions to gather data for the deployment document from all around PAMGuard.
* There should be just one of these, available from TethysControl and it will try
* to sensible handle when and how it updates it's list of PAMGuard and Tethys information
* <br> Any part of PAMGuard wanting information on Deployments should come here.
* @author dg50 * @author dg50
* *
*/ */
public class DeploymentHandler { public class DeploymentHandler implements TethysStateObserver {
private TethysControl tethysControl; private TethysControl tethysControl;
private DeploymentOverview deploymentOverview;
private ArrayList<PDeployment> projectDeployments;
public DeploymentHandler(TethysControl tethysControl) { public DeploymentHandler(TethysControl tethysControl) {
super(); super();
this.tethysControl = tethysControl; this.tethysControl = tethysControl;
tethysControl.addStateObserver(this);
} }
@Override
public void updateState(TethysState tethysState) {
switch (tethysState.stateType) {
case NEWPROJECTSELECTION:
updateProjectDeployments();
break;
case TRANSFERDATA:
updateProjectDeployments();
break;
case UPDATESERVER:
updateProjectDeployments();
break;
default:
break;
}
}
/**
* Update the list of Tethys deployments
* @return true if OK
*/
public boolean updateProjectDeployments() {
DeploymentData projData = tethysControl.getGlobalDeplopymentData();
ArrayList<Deployment> tethysDocs = tethysControl.getDbxmlQueries().getProjectDeployments(projData.getProject());
if (tethysDocs == null) {
return false;
}
projectDeployments = new ArrayList<>();
for (Deployment deployment : tethysDocs) {
projectDeployments.add(new PDeployment(deployment));
}
matchPamguard2Tethys(deploymentOverview, projectDeployments);
return true;
}
/**
* Get a list of Tethys deployment docs. Note that this
* doesn't update the list, but uses the one currently in memory
* so call updateTethysDeployments() first if necessary.
* @return list of (wrapped) nilus Deployment objects.
*/
public ArrayList<PDeployment> getProjectDeployments() {
if (projectDeployments == null) {
updateProjectDeployments();
}
return projectDeployments;
}
/** /**
* Get an overview of all the deployments. * Get an overview of all the deployments.
* @return * @return
*/ */
public DeploymentOverview createOverview() { public DeploymentOverview createPamguardOverview() {
// first find an acquisition module. // first find an acquisition module.
PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null); PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
if (!(aModule instanceof AcquisitionControl)) { if (!(aModule instanceof AcquisitionControl)) {
@ -118,7 +182,7 @@ public class DeploymentHandler {
if (prevPeriod != null) { if (prevPeriod != null) {
long gap = nextPeriod.getRecordStart() - prevPeriod.getRecordStop(); long gap = nextPeriod.getRecordStart() - prevPeriod.getRecordStop();
long prevDur = prevPeriod.getRecordStop()-prevPeriod.getRecordStart(); long prevDur = prevPeriod.getRecordStop()-prevPeriod.getRecordStart();
if (gap < 3 || gap < prevDur/50) { if (gap < 3000 || gap < prevDur/50) {
// ignoring up to 3s gap or a sample error < 2%.Dunno if this is sensible or not. // ignoring up to 3s gap or a sample error < 2%.Dunno if this is sensible or not.
prevPeriod.setRecordStop(nextPeriod.getRecordStop()); prevPeriod.setRecordStop(nextPeriod.getRecordStop());
iterator.remove(); iterator.remove();
@ -127,9 +191,20 @@ public class DeploymentHandler {
} }
prevPeriod = nextPeriod; prevPeriod = nextPeriod;
} }
System.out.printf("Data have %d distinct files, but only %d distinct recording periods\n", nPeriods, tempPeriods.size()); // System.out.printf("Data have %d distinct files, but only %d distinct recording periods\n", nPeriods, tempPeriods.size());
DutyCycleInfo dutyCycleinfo = assessDutyCycle(tempPeriods); DutyCycleInfo dutyCycleinfo = assessDutyCycle(tempPeriods);
DeploymentOverview deploymentOverview = new DeploymentOverview(false, 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()));
}
DeploymentOverview deploymentOverview = new DeploymentOverview(dutyCycleinfo, deploymentPeriods);
matchPamguard2Tethys(deploymentOverview, projectDeployments);
this.deploymentOverview = deploymentOverview;
return deploymentOverview; return deploymentOverview;
// find the number of times it started and stopped .... // 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", // System.out.printf("Input map of sound data indicates data from %s to %s with %d starts and %d stops over %d files\n",
@ -138,6 +213,64 @@ public class DeploymentHandler {
} }
public DeploymentOverview getDeploymentOverview() {
return deploymentOverview;
}
/**
* Match what we think the PAMGuard deployment times are with Tethys Deployments read back
* from the database.
* @param deploymentOverview
* @param deployments
*/
private void matchPamguard2Tethys(DeploymentOverview deploymentOverview, ArrayList<PDeployment> deployments) {
if (deployments == null || deploymentOverview == null) {
return;
}
ArrayList<RecordingPeriod> recordingPeriods = deploymentOverview.getRecordingPeriods();
for (RecordingPeriod aPeriod : recordingPeriods) {
PDeployment closestDeployment = findClosestDeployment(aPeriod, deployments);
aPeriod.setMatchedTethysDeployment(closestDeployment);
if (closestDeployment != null) {
closestDeployment.setMatchedPAMGaurdPeriod(aPeriod);
}
}
}
/**
* find the Tethys deployment that most closely matches the PAMGuard recording period.
* @param aPeriod
* @param deployments
* @return
*/
private PDeployment findClosestDeployment(RecordingPeriod aPeriod, ArrayList<PDeployment> deployments) {
double overlap = -1;
PDeployment bestDeployment = null;
for (PDeployment aDeployment : deployments) {
double newOverlap = getDeploymentOverlap(aDeployment, aPeriod);
if (newOverlap > overlap) {
bestDeployment = aDeployment;
overlap = newOverlap;
}
}
return bestDeployment;
}
/**
* Get the overlap in mills between a nilus Deployment and a PAMGuard recording period
* @param aDeployment nilus Deployment from Tethys
* @param aPeriod PAMGuard recording period
* @return overlap in milliseconds
*/
public long getDeploymentOverlap(PDeployment aDeployment, RecordingPeriod aPeriod) {
long start = aPeriod.getRecordStart();
long stop = aPeriod.getRecordStop();
long depStart = aDeployment.getAudioStart();
long depStop = aDeployment.getAudioEnd();
long overlap = (Math.min(stop, depStop)-Math.max(start, depStart));
return overlap;
}
/** /**
* Work out whether or not the data are evenly duty cycled by testing the * Work out whether or not the data are evenly duty cycled by testing the
@ -148,14 +281,23 @@ public class DeploymentHandler {
private DutyCycleInfo assessDutyCycle(ArrayList<RecordingPeriod> tempPeriods) { private DutyCycleInfo assessDutyCycle(ArrayList<RecordingPeriod> tempPeriods) {
int n = tempPeriods.size(); int n = tempPeriods.size();
if (n < 2) { if (n < 2) {
return null; 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[] ons = new double[n-1]; // ignore the last one since it may be artificially shortened which is OK
double[] gaps = new double[n-1]; double[] gaps = new double[n-1];
for (int i = 0; i < n-1; i++) { for (int i = 0; i < n-1; i++) {
ons[i] = tempPeriods.get(i).getDuration(); ons[i] = tempPeriods.get(i).getDuration()/1000.;
gaps[i] = (tempPeriods.get(i+1).getRecordStart()-tempPeriods.get(i).getRecordStop())/1000.;
} }
return null; // now look at how consistent those values are
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;
} }
@ -195,102 +337,160 @@ public class DeploymentHandler {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return null;
} }
//in each channel /**
public ArrayList<DeploymentRecoveryPair> getDeployments() { * Get a list of Tethys Deployment docs that match the current PAMGuard data.
* @return
DeploymentOverview recordingOverview = createOverview(); */
public ArrayList<PDeployment> getMatchedDeployments() {
// first find an acquisition module. ArrayList<PDeployment> matched = new ArrayList<>();
PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null); if (deploymentOverview == null) {
if (!(aModule instanceof AcquisitionControl)) { return matched;
// 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. for (RecordingPeriod period : deploymentOverview.getRecordingPeriods()) {
AcquisitionControl daqControl = (AcquisitionControl) aModule; if (period.getMatchedTethysDeployment() != null) {
AcquisitionParameters daqParams = daqControl.getAcquisitionParameters(); matched.add(period.getMatchedTethysDeployment());
/**
* 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();
long dataStart = Long.MAX_VALUE;
long dataEnd = Long.MIN_VALUE;
if (allStatusData != null && allStatusData.size() > 0) {
// find the number of times it started and stopped ....
int nStart = 0, nStop = 0, nFile=0;
for (DaqStatusDataUnit daqStatus : allStatusData) {
switch (daqStatus.getStatus()) {
case "Start":
nStart++;
dataStart = Math.min(dataStart, daqStatus.getTimeMilliseconds());
break;
case "Stop":
nStop++;
dataEnd = Math.max(dataEnd, daqStatus.getEndTimeInMilliseconds());
break;
case "NextFile":
nFile++;
break;
}
} }
// 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);
} }
return matched;
// // and we find the datamap within that ...
// OfflineDataMap daqMap = daqInfoDataBlock.getOfflineDataMap(DBControlUnit.findDatabaseControl());
// if (daqMap != null) {
// // iterate through it.
// long dataStart = daqMap.getFirstDataTime();
// long dataEnd = daqMap.getLastDataTime();
// List<OfflineDataMapPoint> mapPoints = daqMap.getMapPoints();
// System.out.printf("Input map of sound data indicates data from %s to %s with %d individual files\n",
// PamCalendar.formatDateTime(dataStart), PamCalendar.formatDateTime(dataEnd), mapPoints.size());
// /*
// * clearly in the first database I've been looking at of Tinas data, this is NOT getting sensible start and
// * end times. Print them out to see what's going on.
// */
//// for ()
// }
DeploymentRecoveryPair pair = new DeploymentRecoveryPair();
DeploymentRecoveryDetails deployment = new DeploymentRecoveryDetails();
DeploymentRecoveryDetails recovery = new DeploymentRecoveryDetails();
pair.deploymentDetails = deployment;
pair.recoveryDetails = recovery;
deployment.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataStart));
deployment.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataStart));
recovery.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataEnd));
recovery.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataEnd));
ArrayList<DeploymentRecoveryPair> drPairs = new ArrayList<>();
drPairs.add(pair);
return drPairs;
} }
public Deployment createDeploymentDocument(int i, DeploymentRecoveryPair drd) { /**
* Get a list of instruments from the current project deployments.
* This may be a shorter list than the list of deployments.
* @return
*/
public ArrayList<PInstrument> getProjectInstruments() {
if (projectDeployments == null) {
return null;
}
ArrayList<PInstrument> instruments = new ArrayList<>();
for (PDeployment aDepl : projectDeployments) {
Instrument intr = aDepl.deployment.getInstrument();
if (intr == null) {
continue;
}
PInstrument pInstr = new PInstrument(intr.getType(), intr.getInstrumentId());
if (instruments.contains(pInstr) == false) {
instruments.add(pInstr);
}
}
return instruments;
}
//in each channel
// public ArrayList<DeploymentRecoveryPair> getDeployments() {
//
// DeploymentOverview recordingOverview = this.deploymentOverview;
//
// // 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();
// long dataStart = Long.MAX_VALUE;
// long dataEnd = Long.MIN_VALUE;
// if (allStatusData != null && allStatusData.size() > 0) {
// // find the number of times it started and stopped ....
// int nStart = 0, nStop = 0, nFile=0;
// for (DaqStatusDataUnit daqStatus : allStatusData) {
// switch (daqStatus.getStatus()) {
// case "Start":
// nStart++;
// dataStart = Math.min(dataStart, daqStatus.getTimeMilliseconds());
// break;
// case "Stop":
// nStop++;
// dataEnd = Math.max(dataEnd, daqStatus.getEndTimeInMilliseconds());
// break;
// case "NextFile":
// nFile++;
// break;
// }
// }
//
//// 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);
//
// }
//
//// // and we find the datamap within that ...
//// OfflineDataMap daqMap = daqInfoDataBlock.getOfflineDataMap(DBControlUnit.findDatabaseControl());
//// if (daqMap != null) {
//// // iterate through it.
//// long dataStart = daqMap.getFirstDataTime();
//// long dataEnd = daqMap.getLastDataTime();
//// List<OfflineDataMapPoint> mapPoints = daqMap.getMapPoints();
//// System.out.printf("Input map of sound data indicates data from %s to %s with %d individual files\n",
//// PamCalendar.formatDateTime(dataStart), PamCalendar.formatDateTime(dataEnd), mapPoints.size());
//// /*
//// * clearly in the first database I've been looking at of Tinas data, this is NOT getting sensible start and
//// * end times. Print them out to see what's going on.
//// */
////// for ()
//// }
// DeploymentRecoveryPair pair = new DeploymentRecoveryPair();
// DeploymentRecoveryDetails deployment = new DeploymentRecoveryDetails();
// DeploymentRecoveryDetails recovery = new DeploymentRecoveryDetails();
// pair.deploymentDetails = deployment;
// pair.recoveryDetails = recovery;
//
// deployment.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataStart));
// deployment.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataStart));
// recovery.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataEnd));
// recovery.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataEnd));
//
// ArrayList<DeploymentRecoveryPair> drPairs = new ArrayList<>();
// drPairs.add(pair);
// return drPairs;
//
// }
/**
* Get the first free deploymendId. This will get appended to
* the ProjectName to make and id for each Deployment document
* @return
*/
public int getFirstFreeDeploymentId() {
/**
* This is an integer used for the DeploymentId. Note that the String Id (currentl9) is just the Project name
* appended with this number.
*/
int firstFree = 0;
if (projectDeployments != null) {
for (PDeployment dep : projectDeployments) {
firstFree = Math.max(firstFree, dep.deployment.getDeploymentId()+1);
}
}
return firstFree;
}
public Deployment createDeploymentDocument(int i, RecordingPeriod recordingPeriod) {
Deployment deployment = new Deployment(); Deployment deployment = new Deployment();
try { try {
nilus.Helper.createRequiredElements(deployment); nilus.Helper.createRequiredElements(deployment);
@ -304,17 +504,26 @@ public class DeploymentHandler {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
String id = String.format("%d", i); DeploymentData globalDeplData = tethysControl.getGlobalDeplopymentData();
String id = String.format("%s%d", globalDeplData.getProject(), i);
deployment.setId(id); deployment.setId(id);
deployment.setDeploymentId(i); deployment.setDeploymentId(i);
deployment.setDeploymentDetails(drd.deploymentDetails);
deployment.setRecoveryDetails(drd.recoveryDetails); DeploymentRecoveryDetails deploymentDetails = new DeploymentRecoveryDetails();
DeploymentRecoveryDetails recoveryDetails = new DeploymentRecoveryDetails();
deploymentDetails.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStart()));
deploymentDetails.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStart()));
recoveryDetails.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStop()));
recoveryDetails.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStop()));
deployment.setDeploymentDetails(deploymentDetails);
deployment.setRecoveryDetails(recoveryDetails);
TethysLocationFuncs.getTrackAndPositionData(deployment); TethysLocationFuncs.getTrackAndPositionData(deployment);
getProjectData(deployment); getProjectData(deployment);
getSamplingDetails(deployment); getSamplingDetails(deployment, recordingPeriod);
getSensorDetails(deployment); getSensorDetails(deployment);
@ -354,11 +563,11 @@ public class DeploymentHandler {
deployment.setDeploymentAlias(deploymentData.getDeploymentAlias()); deployment.setDeploymentAlias(deploymentData.getDeploymentAlias());
deployment.setSite(deploymentData.getSite()); deployment.setSite(deploymentData.getSite());
deployment.setCruise(deploymentData.getCruise()); deployment.setCruise(deploymentData.getCruise());
deployment.setPlatform(deploymentData.getPlatform()); deployment.setPlatform(getPlatform());
deployment.setRegion(deploymentData.getRegion()); deployment.setRegion(deploymentData.getRegion());
Instrument instrument = new Instrument(); Instrument instrument = new Instrument();
instrument.setType(deploymentData.getInstrumentType()); instrument.setType(getInstrumentType());
instrument.setInstrumentId(deploymentData.getInstrumentId()); instrument.setInstrumentId(getInstrumentId());
// get the geometry type from the array manager. // get the geometry type from the array manager.
String geomType = getGeometryType(); String geomType = getGeometryType();
instrument.setGeometryType(geomType); instrument.setGeometryType(geomType);
@ -366,6 +575,62 @@ public class DeploymentHandler {
return true; return true;
} }
/**
* Instrument identifier, e.g. serial number
* @return
*/
private String getInstrumentId() {
return ArrayManager.getArrayManager().getCurrentArray().getInstrumentId();
}
/**
* Test to see if it's possible to export Deployment documents. This is basically a test of
* various metadata fields that are required, such as instrument id's.
* @return null if OK, or a string describing the first encountered error
*/
public String canExportDeployments() {
DeploymentData globalDeplData = tethysControl.getGlobalDeplopymentData();
if (globalDeplData.getProject() == null) {
return "You must set a project name";
}
PInstrument arrayInstrument = getCurrentArrayInstrument();
if (arrayInstrument == null) {
return "No 'Instrument' set. Goto array manager";
}
return null;
}
/**
* Get the Instrument info for the current array.
* @return
*/
public PInstrument getCurrentArrayInstrument() {
PamArray currentArray = ArrayManager.getArrayManager().getCurrentArray();
String currType = currentArray.getInstrumentType();
String currId = currentArray.getInstrumentId();
PInstrument currentInstrument = null;
if (currType != null || currId != null) {
currentInstrument = new PInstrument(currType, currId);
}
return currentInstrument;
}
/**
* On what platform is the instrument deployed? (e.g. mooring, tag)
* @return
*/
private String getPlatform() {
return getGeometryType();
}
/**
* Instrument type, e.g. HARP, EAR, Popup, DMON, Rock Hopper, etc.
* @return
*/
private String getInstrumentType() {
return ArrayManager.getArrayManager().getCurrentArray().getInstrumentType();
}
/** /**
* Get a geometry type string for Tethys based on information in the array manager. * Get a geometry type string for Tethys based on information in the array manager.
* @return * @return
@ -445,8 +710,9 @@ public class DeploymentHandler {
/** /**
* Fill in the sampling details in a Deployment document. * Fill in the sampling details in a Deployment document.
* @param deployment * @param deployment
* @param recordingPeriod
*/ */
private boolean getSamplingDetails(Deployment deployment) { private boolean getSamplingDetails(Deployment deployment, RecordingPeriod recordingPeriod) {
SamplingDetails samplingDetails = new SamplingDetails(); SamplingDetails samplingDetails = new SamplingDetails();
// this is basically going to be a list of almost identical channel information // this is basically going to be a list of almost identical channel information
// currently just for the first acquisition. May extend to more. // currently just for the first acquisition. May extend to more.
@ -496,6 +762,23 @@ public class DeploymentHandler {
regimen.setSampleBits(system.getSampleBits()); regimen.setSampleBits(system.getSampleBits());
} }
regimens.add(regimen); regimens.add(regimen);
DutyCycleInfo dutyCycleInf = deploymentOverview.getDutyCycleInfo();
boolean isDS = dutyCycleInf != null && dutyCycleInf.isDutyCycled;
if (isDS) {
DutyCycle dutyCycle = new DutyCycle();
List<nilus.ChannelInfo.DutyCycle.Regimen> reg = dutyCycle.getRegimen();
nilus.ChannelInfo.DutyCycle.Regimen dsr = new nilus.ChannelInfo.DutyCycle.Regimen();
reg.add(dsr);
RecordingDurationS ssss = new RecordingDurationS();
ssss.setValue(dutyCycleInf.meanOnTimeS);
dsr.setRecordingDurationS(ssss);
RecordingIntervalS ris = new RecordingIntervalS();
ris.setValue(dutyCycleInf.meanOnTimeS + dutyCycleInf.meanGapS);
dsr.setRecordingIntervalS(ris);
dsr.setTimeStamp(deployment.getDeploymentDetails().getAudioTimeStamp());
channelInfo.setDutyCycle(dutyCycle);
}
channelInfo.setSampling(sampling); channelInfo.setSampling(sampling);

View File

@ -14,14 +14,15 @@ public class DeploymentOverview {
private ArrayList<RecordingPeriod> recordingPeriods = new ArrayList<>(); private ArrayList<RecordingPeriod> recordingPeriods = new ArrayList<>();
private boolean dutyCycled; private DutyCycleInfo dutyCycleInfo;
public DeploymentOverview(boolean dutyCycled) { public DeploymentOverview(DutyCycleInfo dutyCycleInfo) {
super(); super();
this.dutyCycled = dutyCycled; this.dutyCycleInfo = dutyCycleInfo;
} }
public DeploymentOverview(boolean b, ArrayList<RecordingPeriod> tempPeriods) { public DeploymentOverview(DutyCycleInfo dutyCycleInfo, ArrayList<RecordingPeriod> tempPeriods) {
this.dutyCycleInfo = dutyCycleInfo;
this.recordingPeriods = tempPeriods; this.recordingPeriods = tempPeriods;
} }
@ -33,17 +34,35 @@ public class DeploymentOverview {
recordingPeriods.add(recordingPeriod); recordingPeriods.add(recordingPeriod);
} }
public boolean isDutyCycled() {
return dutyCycled;
}
public void setDutyCycled(boolean dutyCycled) {
this.dutyCycled = dutyCycled;
}
public ArrayList<RecordingPeriod> getRecordingPeriods() { public ArrayList<RecordingPeriod> getRecordingPeriods() {
return recordingPeriods; return recordingPeriods;
} }
public DutyCycleInfo getDutyCycleInfo() {
return dutyCycleInfo;
}
/**
* Get the start time of the first recording
* @return
*/
public Long getFirstStart() {
if (recordingPeriods.size() > 0) {
return recordingPeriods.get(0).getRecordStart();
}
return null;
}
/**
* Get the end time of the last recording
* @return
*/
public Long getLastEnd() {
if (recordingPeriods.size() > 0) {
return recordingPeriods.get(recordingPeriods.size()-1).getRecordStop();
}
return null;
}

View File

@ -4,8 +4,8 @@ import nilus.DeploymentRecoveryDetails;
public class DeploymentRecoveryPair { public class DeploymentRecoveryPair {
public DeploymentRecoveryDetails deploymentDetails; // public DeploymentRecoveryDetails deploymentDetails;
//
public DeploymentRecoveryDetails recoveryDetails; // public DeploymentRecoveryDetails recoveryDetails;
} }

View File

@ -2,4 +2,32 @@ package tethys.deployment;
public class DutyCycleInfo { public class DutyCycleInfo {
public boolean isDutyCycled;
public double meanOnTimeS;
public double meanGapS;
int nCycles;
public DutyCycleInfo(boolean isDutyCycled, double meanOnTimeS, double meanGapS, int nCycles) {
super();
this.isDutyCycled = isDutyCycled;
this.meanOnTimeS = meanOnTimeS;
this.meanGapS = meanGapS;
this.nCycles = nCycles;
}
@Override
public String toString() {
if (isDutyCycled == false) {
return "No duty cycle";
}
else {
return String.format("%3.1fs on, %3.1fs off, for %d cycles", meanOnTimeS, meanGapS, nCycles);
}
}
} }

View File

@ -0,0 +1,49 @@
package tethys.deployment;
/**
* Class to handle instrument information
* @author dg50
*
*/
public class PInstrument {
public String instrumentType;
public String instrumentId;
public PInstrument(String instrumentType, String instrumentId) {
super();
this.instrumentType = instrumentType;
this.instrumentId = instrumentId;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof PInstrument == false) {
return false;
}
PInstrument other = (PInstrument) obj;
boolean eq = true;
if (this.instrumentType != null) {
eq &= this.instrumentType.equals(other.instrumentType);
}
if (this.instrumentId != null) {
eq &= this.instrumentId.equals(other.instrumentId);
}
if (other.instrumentType != null) {
eq &= other.instrumentType.equals(this.instrumentType);
}
if (other.instrumentId != null) {
eq &= other.instrumentId.equals(this.instrumentId);
}
return eq;
}
@Override
public String toString() {
return String.format("%s : %s", instrumentType == null ? "Undefined" : instrumentType, instrumentId);
}
}

View File

@ -1,10 +1,18 @@
package tethys.deployment; package tethys.deployment;
import tethys.niluswraps.PDeployment;
public class RecordingPeriod { public class RecordingPeriod {
private long recordStart; private long recordStart;
private long recordStop; private long recordStop;
/**
* Reference to a matched nilus Deployment document retrieved
* from the database.
*/
private PDeployment matchedTethysDeployment;
public RecordingPeriod(long recordStart, long recordStop) { public RecordingPeriod(long recordStart, long recordStop) {
super(); super();
@ -31,6 +39,14 @@ public class RecordingPeriod {
public long getDuration() { public long getDuration() {
return recordStop-recordStart; return recordStop-recordStart;
} }
public PDeployment getMatchedTethysDeployment() {
return matchedTethysDeployment;
}
public void setMatchedTethysDeployment(PDeployment closestDeployment) {
this.matchedTethysDeployment = closestDeployment;
}
} }

View File

@ -10,6 +10,7 @@ import PamguardMVC.PamDataUnit;
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 nilus.DataSourceType; import nilus.DataSourceType;
import nilus.Deployment; import nilus.Deployment;
import nilus.Detection; import nilus.Detection;
@ -143,9 +144,12 @@ public class DetectionsHandler {
/* /*
* Here, make Detection object and add the DetectionEffort data. * Here, make Detection object and add the DetectionEffort data.
*/ */
DeploymentData globalDeplData = tethysControl.getGlobalDeplopymentData();
TethysDataProvider dataProvider = dataBlock.getTethysDataProvider(); TethysDataProvider dataProvider = dataBlock.getTethysDataProvider();
Detections detections = new Detections(); Detections detections = new Detections();
detections.setId(String.format("%d", uniqueDetectionsId++)); // String prefix = getDetectionsDocIdPrefix(globalDeplData.getProject(), dataBlock);
String prefix = deployment.getId();
detections.setId(String.format("%s_%d", prefix, uniqueDetectionsId++));
detections.setDescription(dataProvider.getDescription(deployment, tethysExportParams)); detections.setDescription(dataProvider.getDescription(deployment, tethysExportParams));
DataSourceType dataSource = new DataSourceType(); DataSourceType dataSource = new DataSourceType();
dataSource.setDeploymentId(deployment.getId()); dataSource.setDeploymentId(deployment.getId());
@ -214,4 +218,15 @@ public class DetectionsHandler {
return effort; return effort;
} }
// /**
// * 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
// * analysis going into one database.
// * @param project
// * @param dataBlock
// * @return Detections document prefix.
// */
// public static final String getDetectionsDocIdPrefix(String project, PamDataBlock dataBlock) {
// return project + "_" + dataBlock.getDataName();
// }
} }

View File

@ -0,0 +1,55 @@
package tethys.niluswraps;
import PamUtils.PamCalendar;
import nilus.Deployment;
import nilus.DeploymentRecoveryDetails;
import tethys.TethysTimeFuncs;
import tethys.deployment.RecordingPeriod;
/**
* Wrapper around a nilus Deployment object to provide a bit of extra bookkeeping
* and functionality for PAMGuard.
* @author dg50
*
*/
public class PDeployment {
public Deployment deployment;
private RecordingPeriod matchedPAMGaurdPeriod;
public PDeployment(Deployment deployment) {
super();
this.deployment = deployment;
}
public Long getAudioStart() {
DeploymentRecoveryDetails detail = deployment.getDeploymentDetails();
if (detail == null) {
return null;
}
return TethysTimeFuncs.millisFromGregorianXML(detail.getAudioTimeStamp());
}
public Long getAudioEnd() {
DeploymentRecoveryDetails detail = deployment.getRecoveryDetails();
if (detail == null) {
return null;
}
return TethysTimeFuncs.millisFromGregorianXML(detail.getAudioTimeStamp());
}
@Override
public String toString() {
return String.format("%s:%d; %s - %s", deployment.getId(), deployment.getDeploymentId(),
PamCalendar.formatDBDateTime(getAudioStart()), PamCalendar.formatDBDateTime(getAudioEnd()));
}
public RecordingPeriod getMatchedPAMGaurdPeriod() {
return matchedPAMGaurdPeriod;
}
public void setMatchedPAMGaurdPeriod(RecordingPeriod matchedPAMGaurdPeriod) {
this.matchedPAMGaurdPeriod = matchedPAMGaurdPeriod;
}
}

View File

@ -0,0 +1,48 @@
package tethys.output;
import PamguardMVC.PamDataBlock;
import tethys.TethysControl;
/**
* Data about a PAMDataBlock. <br>
* All the information needed to populate a table row in the synchronisation table.
* some will need to be set as rarely as possible since it may
* be slow to update. <br>
* This needs to sit alongside the StreamExportParams objects since those others are serialisable wheras
* there is a lot of stuff in here which isn't.
* @author dg50
*
*/
public class DatablockSynchInfo {
private PamDataBlock dataBlock;
public PamDataBlock getDataBlock() {
return dataBlock;
}
private TethysControl tethysControl;
private int setDataCount;
public DatablockSynchInfo(TethysControl tethysControl, PamDataBlock dataBlock) {
super();
this.tethysControl = tethysControl;
this.dataBlock = dataBlock;
}
/**
* Get the stored export params for this data block
* @return
*/
public StreamExportParams getExportParams() {
return tethysControl.getTethysExportParams().getStreamParams(dataBlock);
}
public void setDataCount(int n) {
this.setDataCount = n;
}
public int getDataCount() {
return setDataCount;
}
}

View File

@ -3,6 +3,7 @@ package tethys.output;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataBlock;
import metadata.deployment.DeploymentData;
/** /**
@ -28,6 +29,8 @@ public class TethysExportParams implements Serializable, Cloneable{
private HashMap<String, StreamExportParams> streamParamsMap = new HashMap(); private HashMap<String, StreamExportParams> streamParamsMap = new HashMap();
private DeploymentData deploymentData;
@Override @Override
public TethysExportParams clone() { public TethysExportParams clone() {
try { try {
@ -63,4 +66,11 @@ public class TethysExportParams implements Serializable, Cloneable{
return streamParamsMap.get(longDataName); return streamParamsMap.get(longDataName);
} }
public DeploymentData getProjectData() {
if (deploymentData == null) {
deploymentData = new DeploymentData();
}
return deploymentData;
}
} }

View File

@ -33,7 +33,9 @@ import nilus.Deployment;
import tethys.TethysControl; import tethys.TethysControl;
import tethys.dbxml.DBXMLConnect; import tethys.dbxml.DBXMLConnect;
import tethys.deployment.DeploymentHandler; import tethys.deployment.DeploymentHandler;
import tethys.deployment.DeploymentOverview;
import tethys.deployment.DeploymentRecoveryPair; import tethys.deployment.DeploymentRecoveryPair;
import tethys.deployment.RecordingPeriod;
import tethys.detection.DetectionGranularity; import tethys.detection.DetectionGranularity;
import tethys.detection.DetectionGranularity.GRANULARITY; import tethys.detection.DetectionGranularity.GRANULARITY;
import tethys.detection.DetectionsHandler; import tethys.detection.DetectionsHandler;
@ -168,21 +170,23 @@ public class TethysExporter {
//get list of deployment recovery details (start, stop times and lat/long) //get list of deployment recovery details (start, stop times and lat/long)
//deployment details and recovery details are same structure //deployment details and recovery details are same structure
//per pair, go through a loop to fill in each deployment //per pair, go through a loop to fill in each deployment
DeploymentHandler deploymentHandler = new DeploymentHandler(tethysControl); // DeploymentHandler deploymentHandler = new DeploymentHandler(tethysControl);
DeploymentHandler deploymentHandler = tethysControl.getDeploymentHandler();
ArrayList<DeploymentRecoveryPair> deployRecover = deploymentHandler.getDeployments(); // ArrayList<DeploymentRecoveryPair> deployRecover = deploymentHandler.getDeployments();
if (deployRecover == null) { // if (deployRecover == null) {
return false; // return false;
} // }
ArrayList<Deployment> deploymentDocs = new ArrayList<>(); ArrayList<Deployment> deploymentDocs = new ArrayList<>();
/* /*
* This will become the main loop over deployment documents * This will become the main loop over deployment documents
*/ */
int i = 0; DeploymentOverview deploymentOverview = deploymentHandler.getDeploymentOverview();
for (DeploymentRecoveryPair drd : deployRecover) { int i = deploymentHandler.getFirstFreeDeploymentId();
for (RecordingPeriod recordingPeriod : deploymentOverview.getRecordingPeriods()) {
Deployment deployment = deploymentHandler.createDeploymentDocument(i++, drd); Deployment deployment = deploymentHandler.createDeploymentDocument(i++, recordingPeriod);
// System.out.println(deployment.toString()); // System.out.println(deployment.toString());
deploymentDocs.add(deployment); deploymentDocs.add(deployment);
@ -196,10 +200,10 @@ public class TethysExporter {
*/ */
DetectionsHandler detectionsHandler = new DetectionsHandler(tethysControl); DetectionsHandler detectionsHandler = new DetectionsHandler(tethysControl);
ArrayList<PamDataBlock> allDataBlocks = PamController.getInstance().getDataBlocks(); ArrayList<PamDataBlock> allDataBlocks = PamController.getInstance().getDataBlocks();
/** // /**
* 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);
@ -207,7 +211,7 @@ public class TethysExporter {
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), tethysExportParams, streamExportParams); new DetectionGranularity(GRANULARITY.TIME, 3600*12), tethysExportParams, streamExportParams);
} }
} }
/* /*

View File

@ -84,7 +84,7 @@ public class AutoTethysProvider implements TethysDataProvider {
String fullUnitName = pamControlledUnit.getUnitType() + " " + pamControlledUnit.getUnitName(); String fullUnitName = pamControlledUnit.getUnitType() + " " + pamControlledUnit.getUnitName();
description.setAbstract(fullUnitName); description.setAbstract(fullUnitName);
description.setObjectives(fullUnitName); description.setObjectives(fullUnitName);
description.setMethod(pamControlledUnit.getUnitType()); description.setMethod(pamDataBlock.getLongDataName());
return description; return description;
} }

View File

@ -0,0 +1,112 @@
package tethys.swing;
import java.awt.BorderLayout;
import java.util.ArrayList;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.border.TitledBorder;
import javax.swing.table.AbstractTableModel;
import PamUtils.PamCalendar;
import PamView.panel.PamPanel;
import PamView.tables.SwingTableColumnWidths;
import dataMap.OfflineDataMap;
import tethys.TethysControl;
import tethys.TethysState;
import tethys.output.DatablockSynchInfo;
public class DatablockSynchPanel extends TethysGUIPanel {
public JPanel mainPanel;
private JTable synchTable;
private SynchTableModel synchTableModel;
private ArrayList<DatablockSynchInfo> dataBlockSynchInfo;
public DatablockSynchPanel(TethysControl tethysControl) {
super(tethysControl);
mainPanel = new PamPanel(new BorderLayout());
mainPanel.setBorder(new TitledBorder("PAMGuard data blocks"));
synchTableModel = new SynchTableModel();
synchTable = new JTable(synchTableModel);
new SwingTableColumnWidths(tethysControl.getUnitName()+"SynchTable", synchTable);
JScrollPane scrollPane = new JScrollPane(synchTable);
mainPanel.add(BorderLayout.CENTER, scrollPane);
}
@Override
public JComponent getComponent() {
return mainPanel;
}
@Override
public void updateState(TethysState tethysState) {
synchTableModel.fireTableDataChanged();
}
private ArrayList<DatablockSynchInfo> getSychInfos() {
if (dataBlockSynchInfo == null) {
dataBlockSynchInfo = getTethysControl().getSynchronisationInfos();
}
return dataBlockSynchInfo;
}
private class SynchTableModel extends AbstractTableModel {
String[] columnNames = {"Data Stream", "N PAM Datas", "PAMGuard Time", "N Tethys Datas", "Tethys Time", "Options"};
@Override
public int getRowCount() {
return getSychInfos().size();
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public String getColumnName(int column) {
return columnNames[column];
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
DatablockSynchInfo synchInfo = getSychInfos().get(rowIndex);
return getValueAt(synchInfo, columnIndex);
}
private Object getValueAt(DatablockSynchInfo synchInfo, int columnIndex) {
OfflineDataMap dataMap = synchInfo.getDataBlock().getPrimaryDataMap();
switch (columnIndex) {
case 0:
return synchInfo.getDataBlock().getDataName();
case 1:
if (dataMap == null) {
return null;
}
return synchInfo.getDataBlock().getPrimaryDataMap().getDataCount();
case 2:
if (dataMap == null) {
return null;
}
if (dataMap.getDataCount() == 0) {
return "No data";
}
long start = synchInfo.getDataBlock().getPrimaryDataMap().getFirstDataTime();
long stop = synchInfo.getDataBlock().getPrimaryDataMap().getLastDataTime();
return String.format("%s - %s", PamCalendar.formatDBDateTime(start), PamCalendar.formatDBDateTime(stop));
case 3:
return synchInfo.getDataCount();
}
return null;
}
}
}

View File

@ -0,0 +1,48 @@
package tethys.swing;
import java.awt.BorderLayout;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import javax.swing.border.TitledBorder;
import PamView.panel.PamPanel;
import tethys.TethysControl;
public class DeploymentsPanel extends TethysGUIPanel {
private JPanel mainPanel;
private PAMGuardDeploymentsTable pamDeploymentsTable;
private TethysDeploymentsTable tethysDeploymentsTable;
public DeploymentsPanel(TethysControl tethysControl) {
super(tethysControl);
pamDeploymentsTable = new PAMGuardDeploymentsTable(tethysControl);
tethysDeploymentsTable = new TethysDeploymentsTable(tethysControl);
mainPanel = new PamPanel(new BorderLayout());
mainPanel.setBorder(new TitledBorder("Deployment information"));
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splitPane.add(pamDeploymentsTable.getComponent());
splitPane.add(tethysDeploymentsTable.getComponent());
mainPanel.add(splitPane,BorderLayout.CENTER);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
splitPane.setDividerLocation(0.6);
}
});
}
@Override
public JComponent getComponent() {
return mainPanel;
}
}

View File

@ -0,0 +1,91 @@
package tethys.swing;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Window;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import PamView.dialog.PamGridBagContraints;
import metadata.deployment.DeploymentData;
import tethys.TethysControl;
public class NewProjectDialog extends PamView.dialog.PamDialog {
private static final long serialVersionUID = 1L;
private static NewProjectDialog singleInstance;
private JTextField projectName;
private JTextField projectRegion;
private DeploymentData deploymentData;
private NewProjectDialog(Window parentFrame, TethysControl tethysControl) {
super(parentFrame, "New Project", false);
JPanel mainPanel = new JPanel(new GridBagLayout());
mainPanel.setBorder(new TitledBorder("Project details"));
GridBagConstraints c = new PamGridBagContraints();
mainPanel.add(new JLabel("Project name ", JLabel.RIGHT), c);
c.gridx++;
mainPanel.add(projectName = new JTextField(30), c);
c.gridx = 0;
c.gridy++;
mainPanel.add(new JLabel("Geographic region ", JLabel.RIGHT), c);
c.gridx++;
mainPanel.add(projectRegion = new JTextField(30), c);
projectName.setToolTipText("Name of project associated with this deployment. Can be related to a geographic region, funding source, etc");
projectRegion.setToolTipText("Name of geographic region (optional)");
setDialogComponent(mainPanel);
}
public static DeploymentData showDialog(Window parent, TethysControl tethysControl, DeploymentData deploymentData) {
if (singleInstance == null) {
singleInstance = new NewProjectDialog(parent, tethysControl);
}
singleInstance.setParams(deploymentData);
singleInstance.setVisible(true);
return singleInstance.deploymentData;
}
private void setParams(DeploymentData deploymentData) {
if (deploymentData == null) {
return;
}
this.deploymentData = deploymentData;
projectName.setText(deploymentData.getProject());
projectRegion.setText(deploymentData.getRegion());
}
@Override
public boolean getParams() {
if (deploymentData == null) {
return false;
}
deploymentData.setProject(projectName.getText());
deploymentData.setRegion(projectRegion.getText());
if (deploymentData.getProject() == null || deploymentData.getProject().length() == 0) {
return showWarning("you must specify a project name");
}
return true;
}
@Override
public void cancelButtonPressed() {
deploymentData = null;
}
@Override
public void restoreDefaultSettings() {
// TODO Auto-generated method stub
}
}

View File

@ -0,0 +1,215 @@
package tethys.swing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;
import javax.swing.table.AbstractTableModel;
import PamUtils.PamCalendar;
import PamView.panel.PamPanel;
import PamView.tables.SwingTableColumnWidths;
import tethys.TethysControl;
import tethys.TethysState;
import tethys.deployment.DeploymentHandler;
import tethys.deployment.DeploymentOverview;
import tethys.deployment.RecordingPeriod;
import tethys.niluswraps.PDeployment;
/**
* Table view of PAMGuard deployments. For a really simple deployment, this may have only
* one line. For towed surveys where we stop and start a lot, it may have a LOT of lines.
* @author dg50
*
*/
public class PAMGuardDeploymentsTable extends TethysGUIPanel {
private TableModel tableModel;
private JTable table;
private JPanel mainPanel;
private DeploymentOverview deploymentOverview;
public PAMGuardDeploymentsTable(TethysControl tethysControl) {
super(tethysControl);
// deploymentHandler = new DeploymentHandler(getTethysControl());
mainPanel = new PamPanel(new BorderLayout());
mainPanel.setBorder(new TitledBorder("PAMGuard recording periods"));
tableModel = new TableModel();
table = new JTable(tableModel);
table.setRowSelectionAllowed(true);
table.addMouseListener(new TableMouse());
JScrollPane scrollPane = new JScrollPane(table);
mainPanel.add(BorderLayout.CENTER, scrollPane);
new SwingTableColumnWidths(tethysControl.getUnitName()+"PAMDeploymensTable", table);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
}
@Override
public JComponent getComponent() {
return mainPanel;
}
private class TableMouse extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
showPopup();
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
showPopup();
}
}
}
public void showPopup() {
int aRow = table.getSelectedRow();
int[] selRows = table.getSelectedRows();
if (selRows == null || selRows.length == 0) {
if (aRow >= 0) {
selRows = new int[1];
selRows[0] = aRow;
}
else {
return;
}
}
// make a list of RecordingPeriods which don't currently have a Deployment document
ArrayList<RecordingPeriod> newPeriods = new ArrayList<>();
ArrayList<RecordingPeriod> allPeriods = deploymentOverview.getRecordingPeriods();
for (int i = 0; i < selRows.length; i++) {
if (allPeriods.get(selRows[i]).getMatchedTethysDeployment() == null) {
newPeriods.add(allPeriods.get(i));
}
}
if (newPeriods.size() == 0) {
return;
}
/*
* if we get here, we've one or more rows without a Tethys output, so can have
* a menu to create them.
*/
}
@Override
public void updateState(TethysState tethysState) {
switch(tethysState.stateType) {
case NEWPROJECTSELECTION:
case NEWPAMGUARDSELECTION:
updateDeployments();
break;
case UPDATEMETADATA:
checkExportMeta();
}
tableModel.fireTableDataChanged();
}
private void checkExportMeta() {
String metaErr = getTethysControl().getDeploymentHandler().canExportDeployments();
if (metaErr != null) {
mainPanel.setBackground(Color.RED);
}
else {
JPanel anyPanel = new JPanel();
mainPanel.setBackground(anyPanel.getBackground());
}
}
private void updateDeployments() {
DeploymentHandler deploymentHandler = getTethysControl().getDeploymentHandler();
deploymentOverview = deploymentHandler.getDeploymentOverview();
tableModel.fireTableDataChanged();
// DeploymentData deplData = getTethysControl().getGlobalDeplopymentData();
// ArrayList<Deployment> projectDeployments = getTethysControl().getDbxmlQueries().getProjectDeployments(deplData.getProject());
// deploymentHandler.matchPamguard2Tethys(deploymentOverview, projectDeployments);
}
private class TableModel extends AbstractTableModel {
private String[] columnNames = {"Id", "Start", "Stop", "Duration", "Cycle", "Tethys Deployment"};
@Override
public int getRowCount() {
if (deploymentOverview == null) {
return 0;
}
else {
return deploymentOverview.getRecordingPeriods().size();
}
}
@Override
public String getColumnName(int column) {
return columnNames[column];
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
RecordingPeriod period = deploymentOverview.getRecordingPeriods().get(rowIndex);
// DeploymentRecoveryPair deplInfo = deploymentInfo.get(rowIndex);
if (columnIndex == 4) {
return deploymentOverview.getDutyCycleInfo();
}
return getValueAt(period, rowIndex, columnIndex);
}
private Object getValueAt(RecordingPeriod period, int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return rowIndex;
case 1:
return PamCalendar.formatDBDateTime(period.getRecordStart());
// return TethysTimeFuncs.formatGregorianTime(deplInfo.deploymentDetails.getAudioTimeStamp());
case 2:
return PamCalendar.formatDBDateTime(period.getRecordStop());
// return TethysTimeFuncs.formatGregorianTime(deplInfo.recoveryDetails.getAudioTimeStamp());
case 3:
// long t1 = TethysTimeFuncs.millisFromGregorianXML(deplInfo.deploymentDetails.getAudioTimeStamp());
// long t2 = TethysTimeFuncs.millisFromGregorianXML(deplInfo.recoveryDetails.getAudioTimeStamp());
return PamCalendar.formatDuration(period.getRecordStop()-period.getRecordStart());
case 5:
PDeployment deployment = period.getMatchedTethysDeployment();
return makeDeplString(period, deployment);
}
return null;
}
private String makeDeplString(RecordingPeriod period, PDeployment deployment) {
if (deployment == null) {
return "no match";
}
DeploymentHandler deploymentHandler = getTethysControl().getDeploymentHandler();
long overlap = deploymentHandler.getDeploymentOverlap(deployment, period);
long start = period.getRecordStart();
long stop = period.getRecordStop();
double percOverlap = (overlap*100.) / (stop-start);
return String.format("%s : %3.1f%% overlap", deployment.toString(), percOverlap);
}
}
}

View File

@ -6,6 +6,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.util.ArrayList; import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComboBox; import javax.swing.JComboBox;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JLabel; import javax.swing.JLabel;
@ -13,16 +14,24 @@ import javax.swing.JPanel;
import javax.swing.JTextField; import javax.swing.JTextField;
import javax.swing.border.TitledBorder; import javax.swing.border.TitledBorder;
import Array.ArrayDialog;
import Array.ArrayManager;
import Array.PamArray;
import PamView.dialog.PamGridBagContraints; import PamView.dialog.PamGridBagContraints;
import PamView.dialog.ScrollingPamLabel; import PamView.dialog.ScrollingPamLabel;
import PamView.dialog.SettingsButton; import PamView.dialog.SettingsButton;
import PamView.panel.PamPanel; import PamView.panel.PamPanel;
import PamView.panel.WestAlignedPanel; import PamView.panel.WestAlignedPanel;
import metadata.deployment.DeploymentData;
import nilus.Deployment;
import pamViewFX.fxNodes.PamComboBox; import pamViewFX.fxNodes.PamComboBox;
import tethys.TethysControl; import tethys.TethysControl;
import tethys.TethysState; import tethys.TethysState;
import tethys.TethysState.StateType; import tethys.TethysState.StateType;
import tethys.TethysTimeFuncs;
import tethys.dbxml.ServerStatus; import tethys.dbxml.ServerStatus;
import tethys.deployment.PInstrument;
import tethys.niluswraps.PDeployment;
import tethys.output.TethysExportParams; import tethys.output.TethysExportParams;
/** /**
@ -45,6 +54,14 @@ public class TethysConnectionPanel extends TethysGUIPanel {
private JComboBox<String> projectList; private JComboBox<String> projectList;
// private JComboBox<PDeployment> deploymentList;
private JButton newProjectButton;
private JComboBox<PInstrument> projectInstruments;
private JButton newInstrument;
public TethysConnectionPanel(TethysControl tethysControl) { public TethysConnectionPanel(TethysControl tethysControl) {
super(tethysControl); super(tethysControl);
mainPanel = new WestAlignedPanel(new GridBagLayout()); mainPanel = new WestAlignedPanel(new GridBagLayout());
@ -61,6 +78,39 @@ public class TethysConnectionPanel extends TethysGUIPanel {
selectServer(); selectServer();
} }
}); });
newProjectButton = new JButton("New project");
newProjectButton.setToolTipText("Create new project information");
newProjectButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
createNewProject();
}
});
projectList = new JComboBox<>();
projectList.setToolTipText("All projects present in the current Tethys database");
projectList.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
newProjectSelect();
}
});
projectInstruments = new JComboBox<PInstrument>();
newInstrument = new JButton("New / Edit");
projectInstruments.setToolTipText("Instruments currently listed within all deployments of the current project");
newInstrument.setToolTipText("Edit or create a new instrument (uses PAMGuard Array dialog)");
projectInstruments.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
newInstrumentSelect();
}
});
newInstrument.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
createNewInstrument();
}
});
// deploymentList = new JComboBox<PDeployment>();
GridBagConstraints c = new PamGridBagContraints(); GridBagConstraints c = new PamGridBagContraints();
mainPanel.add(new JLabel("Tethys Server "), c); mainPanel.add(new JLabel("Tethys Server "), c);
@ -69,23 +119,110 @@ public class TethysConnectionPanel extends TethysGUIPanel {
c.gridx++; c.gridx++;
mainPanel.add(serverSelButton, c); mainPanel.add(serverSelButton, c);
c.gridx++; c.gridx++;
c.gridwidth = 2;
mainPanel.add(serverStatus, c); mainPanel.add(serverStatus, c);
c.gridx++;
c.gridx =0; c.gridx =0;
c.gridy++; c.gridy++;
mainPanel.add(new JLabel("Projects "), c); c.gridwidth = 1;
mainPanel.add(new JLabel("Projects ", JLabel.RIGHT), c);
c.gridx++; c.gridx++;
mainPanel.add(projectList = new JComboBox<>(), c); mainPanel.add(projectList, c);
c.gridx++;
mainPanel.add(newProjectButton, c);
fillServerControl(); // instrument section
c.gridx++;
mainPanel.add(new JLabel(" Instruments ", JLabel.RIGHT), c);
c.gridx++;
mainPanel.add(projectInstruments, c);
c.gridx++;
mainPanel.add(newInstrument, c);
// c.gridx = 0;
// c.gridy++;
// mainPanel.add(new JLabel("Deployments ", JLabel.RIGHT), c);
// c.gridx += c.gridwidth;
// c.gridwidth = 2;
// mainPanel.add(deploymentList, c);
// fillServerControl(); // no need Will get set from TethysControl as soon as all initialised.
} }
protected void newInstrumentSelect() {
PInstrument pInstr = (PInstrument) projectInstruments.getSelectedItem();
if (pInstr == null) {
return;
}
PamArray currentArray = ArrayManager.getArrayManager().getCurrentArray();
currentArray.setInstrumentType(pInstr.instrumentType);
currentArray.setInstrumentId(pInstr.instrumentId);
getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATEMETADATA));
}
protected void createNewInstrument() {
PamArray updatedArray = ArrayDialog.showDialog(getTethysControl().getGuiFrame(), ArrayManager.getArrayManager());
if (updatedArray != null) {
updateInstrumentsList();
}
}
/**
* Action from new project button
*/
protected void createNewProject() {
DeploymentData pamDeploymentData = getTethysControl().getGlobalDeplopymentData();
pamDeploymentData = NewProjectDialog.showDialog(getTethysControl().getGuiFrame(), getTethysControl(), pamDeploymentData);
if (pamDeploymentData != null) {
updateProjectList();
}
}
protected void newProjectSelect() {
String project = (String) projectList.getSelectedItem();
if (project == null) {
return;
}
DeploymentData globData = getTethysControl().getGlobalDeplopymentData();
globData.setProject(project);
getTethysControl().getDeploymentHandler().updateProjectDeployments();
/*
* if there are existing deployment data, then copy the info to the
* internal project information
*/
ArrayList<PDeployment> projectDeployments = getTethysControl().getDeploymentHandler().getProjectDeployments();
if (projectDeployments != null && projectDeployments.size() > 0) {
Deployment dep = projectDeployments.get(0).deployment;
globData.setProject(dep.getProject());
globData.setRegion(dep.getRegion());
getTethysControl().sendStateUpdate(new TethysState(TethysState.StateType.NEWPROJECTSELECTION));
}
updateInstrumentsList();
// fillDeploymentsList(project);
}
// private void fillDeploymentsList(String project) {
// ArrayList<PDeployment> projectDeployments = getTethysControl().getDeploymentHandler().getProjectDeployments();
// deploymentList.removeAllItems();
// if (projectDeployments == null) {
// return;
// }
// for (PDeployment dep : projectDeployments) {
//// String str = String.format("%s:%d, %s to %s", dep.getId(), dep.getDeploymentId(),
//// TethysTimeFuncs.formatGregorianTime(dep.getDeploymentDetails().getAudioTimeStamp()),
//// TethysTimeFuncs.formatGregorianTime(dep.getRecoveryDetails().getAudioTimeStamp()));
// deploymentList.addItem(dep);
// }
// }
protected void selectServer() { protected void selectServer() {
// will return the same object at the moment, so no need to do anything. // will return the same object at the moment, so no need to do anything.
TethysExportParams newParams = SelectServerdDialog.showDialog(getTethysControl(), getTethysControl().getGuiFrame(), getTethysControl().getTethysExportParams()); TethysExportParams newParams = SelectServerdDialog.showDialog(getTethysControl(), getTethysControl().getGuiFrame(), getTethysControl().getTethysExportParams());
if (newParams != null) { if (newParams != null) {
getTethysControl().sendStateUpdate(new TethysState(TethysState.StateType.UPDATESERVER)); getTethysControl().checkServer();// sendStateUpdate(new TethysState(TethysState.StateType.UPDATESERVER));
} }
} }
@ -94,8 +231,11 @@ public class TethysConnectionPanel extends TethysGUIPanel {
serverName.setText(exportParams.getFullServerName()); serverName.setText(exportParams.getFullServerName());
ServerStatus status = getTethysControl().getDbxmlConnect().pingServer(); ServerStatus status = getTethysControl().getDbxmlConnect().pingServer();
serverStatus.setText(status.toString()); serverStatus.setText(status.toString());
colourBackground(status.ok ? 0 : 1);
} }
@Override @Override
public JComponent getComponent() { public JComponent getComponent() {
return mainPanel; return mainPanel;
@ -113,13 +253,53 @@ public class TethysConnectionPanel extends TethysGUIPanel {
private void updateProjectList() { private void updateProjectList() {
projectList.removeAllItems(); projectList.removeAllItems();
ArrayList<String> dbNames = getTethysControl().getDbxmlQueries().getProjectNames(); /*
if (dbNames == null || dbNames.size() == 0) { * put the project name assigned within this PAMGuard config at the top of the
System.out.println("No existing projects"); * list.
*/
String localProjName = null;
DeploymentData pamDeploymentData = getTethysControl().getGlobalDeplopymentData();
if (pamDeploymentData != null && pamDeploymentData.getProject() != null) {
localProjName = pamDeploymentData.getProject();
if (localProjName.length() == 0) {
localProjName = null;
}
}
if (localProjName != null) {
projectList.addItem(localProjName);
}
ArrayList<String> projectNames = getTethysControl().getDbxmlQueries().getProjectNames();
if (projectNames == null || projectNames.size() == 0) {
// System.out.println("No existing projects");
return; return;
} }
for (int i = 0; i < dbNames.size(); i++) { for (int i = 0; i < projectNames.size(); i++) {
projectList.addItem(dbNames.get(i)); String projName = projectNames.get(i);
if (projName.equals(localProjName)) {
continue;
}
projectList.addItem(projectNames.get(i));
}
}
/**
* Update displayed list of instruments
*/
private void updateInstrumentsList() {
projectInstruments.removeAllItems();
PInstrument currentInstrument = getTethysControl().getDeploymentHandler().getCurrentArrayInstrument();
if (currentInstrument != null) {
projectInstruments.addItem(currentInstrument);
}
ArrayList<PInstrument> projectInst = getTethysControl().getDeploymentHandler().getProjectInstruments();
if (projectInst == null) {
return;
}
for (int i = 0; i < projectInst.size(); i++) {
if (projectInst.get(i).equals(currentInstrument) == false) {
projectInstruments.addItem(projectInst.get(i));
}
} }
} }

View File

@ -0,0 +1,151 @@
package tethys.swing;
import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;
import javax.swing.table.AbstractTableModel;
import PamView.panel.PamPanel;
import PamView.tables.SwingTableColumnWidths;
import tethys.TethysControl;
import tethys.TethysMenuActions;
import tethys.TethysState;
import tethys.deployment.DeploymentOverview;
import tethys.niluswraps.PDeployment;
public class TethysDeploymentsTable extends TethysGUIPanel {
private JPanel mainPanel;
private TableModel tableModel;
private JTable table;
private ArrayList<PDeployment> projectDeployments;
private DeploymentOverview deploymentOverview;
public TethysDeploymentsTable(TethysControl tethysControl) {
super(tethysControl);
mainPanel = new PamPanel(new BorderLayout());
mainPanel.setBorder(new TitledBorder("All project deployments"));
tableModel = new TableModel();
table = new JTable(tableModel);
table.setRowSelectionAllowed(true);
table.addMouseListener(new TableMouse());
JScrollPane scrollPane = new JScrollPane(table);
mainPanel.add(BorderLayout.CENTER, scrollPane);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
new SwingTableColumnWidths(tethysControl.getUnitName()+"AllProjectDeploymentsTable", table);
}
private class TableMouse extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
showPopupMenu(e);
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
showPopupMenu(e);
}
}
}
protected void showPopupMenu(MouseEvent e) {
int row = table.getSelectedRow();
if (row < 0) {
return;
}
PDeployment pDeployment = projectDeployments.get(row);
TethysMenuActions menuActions = new TethysMenuActions(getTethysControl());
menuActions.deploymentMouseActions(e, pDeployment);
}
@Override
public JComponent getComponent() {
return mainPanel;
}
@Override
public void updateState(TethysState tethysState) {
projectDeployments = getTethysControl().getDeploymentHandler().getProjectDeployments();
deploymentOverview = getTethysControl().getDeploymentHandler().getDeploymentOverview();
tableModel.fireTableDataChanged();
}
private class TableModel extends AbstractTableModel {
private String[] columnNames = {"Deployment document", "PAMGuard Match"};
@Override
public int getRowCount() {
return projectDeployments == null ? 0 : projectDeployments.size();
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
PDeployment deployment = projectDeployments.get(rowIndex);
switch (columnIndex) {
case 0:
return deployment.toString();
case 1:
return getMatchText(deployment);
}
return null;
}
@Override
public String getColumnName(int column) {
return columnNames[column];
}
public String getMatchText(PDeployment deployment) {
// TODO Auto-generated method stub
if (deployment.getMatchedPAMGaurdPeriod() != null) {
return "Matched to PAMGaurd data";
};
if (deploymentOverview == null) {
return "No PAMGuard data";
}
Long depStart = deploymentOverview.getFirstStart();
Long depEnd = deploymentOverview.getLastEnd();
if (depStart == null) {
return "No PAMGuard recordings";
}
if (deployment.getAudioEnd() < depStart) {
return "Earlier than PAMGuard data";
}
if (deployment.getAudioStart() > depEnd) {
return "Later than PAMGuard data";
}
return "Partial overlap with PAMGuard data, but no match";
}
}
}

View File

@ -1,6 +1,10 @@
package tethys.swing; package tethys.swing;
import java.awt.Color;
import java.awt.Component;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JPanel;
import tethys.TethysControl; import tethys.TethysControl;
import tethys.TethysState; import tethys.TethysState;
@ -27,5 +31,28 @@ public abstract class TethysGUIPanel implements TethysStateObserver {
} }
public Color getNormalColour() {
return new JPanel().getBackground();
}
public Color getErrorColour() {
return Color.ORANGE;
}
public void colourBackground(int iCol) {
Color col = iCol == 0 ? getNormalColour() : getErrorColour();
colourPanels(getComponent(), col);
}
private void colourPanels(JComponent component, Color col) {
component.setBackground(col);
int nChild = component.getComponentCount();
for (int i = 0; i < nChild; i++) {
Component aChild = component.getComponent(i);
if (aChild instanceof JPanel) {
colourPanels((JComponent) aChild, col);
}
}
}
} }

View File

@ -4,6 +4,8 @@ import java.awt.BorderLayout;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import tethys.TethysControl; import tethys.TethysControl;
@ -15,12 +17,31 @@ public class TethysMainPanel extends TethysGUIPanel {
private TethysConnectionPanel connectionPanel; private TethysConnectionPanel connectionPanel;
private DatablockSynchPanel datablockSynchPanel;
private DeploymentsPanel deploymentsPanel;
public TethysMainPanel(TethysControl tethysControl) { public TethysMainPanel(TethysControl tethysControl) {
super(tethysControl); super(tethysControl);
this.tethysControl = tethysControl; this.tethysControl = tethysControl;
mainPanel = new JPanel(new BorderLayout()); mainPanel = new JPanel(new BorderLayout());
connectionPanel = new TethysConnectionPanel(tethysControl); connectionPanel = new TethysConnectionPanel(tethysControl);
datablockSynchPanel = new DatablockSynchPanel(tethysControl);
deploymentsPanel = new DeploymentsPanel(tethysControl);
mainPanel.add(BorderLayout.NORTH, connectionPanel.getComponent()); mainPanel.add(BorderLayout.NORTH, connectionPanel.getComponent());
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
// splitPane.set
mainPanel.add(BorderLayout.CENTER, splitPane);
// mainPanel.add(BorderLayout.CENTER, datablockSynchPanel.getComponent());
splitPane.add(deploymentsPanel.getComponent());
splitPane.add(datablockSynchPanel.getComponent());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
splitPane.setDividerLocation(0.5);
}
});
} }
public JPanel getMainPanel() { public JPanel getMainPanel() {