Calibrations Export

Functional Calibrations export wizard and display
This commit is contained in:
Douglas Gillespie 2023-12-04 21:27:00 +00:00
parent 275a53c042
commit 9939e8aa85
23 changed files with 962 additions and 158 deletions

View File

@ -0,0 +1,160 @@
package PamView.wizard;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JPanel;
import PamView.dialog.PamDialog;
import tethys.swing.export.ExportStreamInfoPanel;
import tethys.swing.export.ExportWizardCard;
abstract public class PamWizard extends PamDialog {
private static final long serialVersionUID = 1L;
private JPanel cardPanel;
private CardLayout cardLayout;
private JPanel mainPanel;
private JButton prevButton;
private ArrayList<PamWizardCard> wizardCards = new ArrayList();
public PamWizard(Window parentFrame, String title) {
super(parentFrame, title, false);
cardLayout = new CardLayout();
mainPanel = new JPanel(new BorderLayout());
cardPanel = new JPanel(cardLayout);
mainPanel.add(BorderLayout.CENTER, cardPanel);
setDialogComponent(mainPanel);
getOkButton().setText("Finish");
prevButton = new JButton("Previous");
getButtonPanel().add(prevButton, 0);
prevButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
previousButton();
}
});
setResizable(true);
}
public void addCard(PamWizardCard wizPanel) {
cardPanel.add(wizPanel, wizPanel.getTitle());
wizardCards.add(wizPanel);
}
/**
* Get the main panel. This is the main dialog panel and uses a borderlayout
* with the cards in the CENTER of the panel. Additional information panels
* (generally fixed and not changing with the dialog) can be added NORTH, SOUTH, WEST and EAST.
* @return main Panel.
*/
public JPanel getMainPanel() {
return mainPanel;
}
/**
* Called when 'previous' button is clicked.
*/
protected void previousButton() {
cardLayout.previous(cardPanel);
enableControls();
}
public void enableControls() {
int iCard = getCardIndex();
prevButton.setEnabled(iCard > 0);
boolean isLast = iCard == wizardCards.size()-1;
// getOkButton().setEnabled(!isLast);
getOkButton().setText(isLast ? "Finish" : "Next");
}
private boolean checkCurrentCard() {
int iCard = getCardIndex();
if (iCard < 0) {
return true;
}
return getCardParams(wizardCards.get(iCard));
}
abstract public void setCardParams(PamWizardCard wizardCard);
abstract public boolean getCardParams(PamWizardCard wizardCard);
public int getCardIndex() {
for (int i = 0; i < cardPanel.getComponentCount(); i++) {
Component component = cardPanel.getComponent(i);
if (component.isVisible()) {
return i;
}
}
return -1;
}
public JButton getPreviousButton() {
return prevButton;
}
public void setParams() {
for (PamWizardCard wizCard : wizardCards) {
setCardParams(wizCard);
}
enableControls();
}
@Override
public boolean getParams() {
/**
* This is the OK button, so we need to NOT return OK, which would close the
* dialog until we're on the last card.
*/
if (checkCurrentCard() == false) {
return false;
}
int iCard = getCardIndex();
if (iCard < wizardCards.size()-1) {
cardLayout.next(cardPanel);
enableControls();
return false;
}
return true;
}
@Override
public void restoreDefaultSettings() {
// TODO Auto-generated method stub
}
/**
* Move to the first card in the stack
*/
public void moveFirst() {
cardLayout.first(cardPanel);
}
/**
* Move to the last card in the stack
*/
public void moveLast() {
cardLayout.last(cardPanel);
}
}

View File

@ -0,0 +1,45 @@
package PamView.wizard;
import java.io.Serializable;
import javax.swing.JPanel;
/**
* Base class for PAMGuard wizard cards.
* @author dg50
*
* @param <T> class type for parameters to set and get.
*/
abstract public class PamWizardCard<T extends Object> extends JPanel {
private static final long serialVersionUID = 1L;
private String title;
private PamWizard pamWizard;
/**
* @param title
*/
public PamWizardCard(PamWizard pamWizard, String title) {
this.pamWizard = pamWizard;
this.title = title;
}
public abstract boolean getParams(T cardParams);
public abstract void setParams(T cardParams);
public String getTitle() {
return title;
}
/**
* @return the pamWizard
*/
public PamWizard getPamWizard() {
return pamWizard;
}
}

View File

@ -8,7 +8,7 @@ package tethys;
*/
public enum Collection {
Deployments, Detections, Calibrations, Localizations, SpeciesAbbreviations, Ensembles, SourceMaps, ITIS, ITIS_ranks;
Deployments, Detections, Calibrations, Localizations, SpeciesAbbreviations, Ensembles, SourceMaps, ITIS, ITIS_ranks, OTHER;
/**
* A list of the main collections in the database, i.e. ones the user will

View File

@ -704,9 +704,9 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
* @param dataBlock
*/
public void exportedDetections(PamDataBlock dataBlock) {
sendStateUpdate(new TethysState(StateType.TRANSFERDATA));
sendStateUpdate(new TethysState(StateType.EXPORTRDATA, Collection.Detections));
countProjectDetections();
sendStateUpdate(new TethysState(StateType.NEWPAMGUARDSELECTION));
sendStateUpdate(new TethysState(StateType.NEWPAMGUARDSELECTION, Collection.Detections));
}
/**

View File

@ -9,27 +9,46 @@ package tethys;
public class TethysState {
public enum StateType {UPDATESERVER, // Server connection or status has changed
TRANSFERDATA, // data have been transferred from PAMGuard to Tethys
EXPORTRDATA, // 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!)
EXPORTING // currently exporting data. may be a while ...
EXPORTING, // currently exporting data. may be a while ...
DELETEDATA // data were deleted
}
public StateType stateType;
private Object stateObject;
public Collection collection;
public TethysState(StateType stateType) {
super();
this.stateType = stateType;
collection = Collection.OTHER;
}
public TethysState(StateType stateType, Object stateObject) {
public TethysState(StateType stateType, Collection collection) {
this.stateType = stateType;
this.stateObject = stateObject;
this.collection = collection;
if (this.collection == null) {
this.collection = Collection.OTHER;
}
}
public Object getStateObject() {
return stateObject;
/**
* @return the collection associated with this notification. Note that there is
* an OTHER category in Collections which is used for server / project updates, making
* it easier to switch on the collection type when notifications are received.
*/
public Collection getCollection() {
return collection;
}
/**
* @return the stateType
*/
public StateType getStateType() {
return stateType;
}
}

View File

@ -5,7 +5,7 @@ public interface TethysStateObserver {
/**
* Receive state updates when Tethys has done something (made a connection, moved some data, etc.)<br>
* Note that this is for RECEIVING state updates, not for sending them. To avoid infinite notifications
* loops, use tethysControl.sendStateUpdate(TethysState) if this component knows something.
* loops, use tethysControl.sendStateUpdate(TethysState) to send out state notifications.
* @param tethysState
*/
public void updateState(TethysState tethysState);

View File

@ -8,21 +8,27 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.xml.bind.JAXBException;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import Acquisition.AcquisitionControl;
import Acquisition.AcquisitionParameters;
import Acquisition.AcquisitionProcess;
import Array.ArrayManager;
import Array.Hydrophone;
import Array.PamArray;
import Array.Preamplifier;
import PamController.PamController;
import PamController.soundMedium.GlobalMedium;
import PamController.soundMedium.GlobalMedium.SoundMedium;
import PamUtils.PamCalendar;
import PamView.dialog.warn.WarnOnce;
import dbxml.Queries;
import PamController.soundMedium.GlobalMediumManager;
import nilus.AlgorithmType.Parameters;
import nilus.Calibration;
import nilus.Calibration.FrequencyResponse;
import nilus.Calibration.QualityAssurance;
@ -37,6 +43,7 @@ import tethys.TethysControl;
import tethys.TethysState;
import tethys.TethysStateObserver;
import tethys.TethysTimeFuncs;
import tethys.calibration.swing.CalibrationsExportWizard;
import tethys.dbxml.DBXMLConnect;
import tethys.dbxml.TethysException;
import tethys.niluswraps.NilusUnpacker;
@ -46,15 +53,26 @@ public class CalibrationHandler implements TethysStateObserver {
private TethysControl tethysControl;
private ArrayList<DocumentNilusObject<Calibration>> calibrationDataBlock;
private ArrayList<DocumentNilusObject<Calibration>> calibrationsList;
public static final String[] updateOptions = {"as-needed", "unplanned", "yearly"};
public static final String[] calibrationMethods = {"Reference hydrophone", "Manufacturers specification", "Piston phone", "Other calibrated source", "Unknown"};
public static final String[] qaTypes = {"unverified", "valid", "invalid"};
private Helper nilusHelper;
/**
* @param tethysControl
*/
public CalibrationHandler(TethysControl tethysControl) {
this.tethysControl = tethysControl;
calibrationDataBlock = new ArrayList();
tethysControl.addStateObserver(this);
calibrationsList = new ArrayList();
tethysControl.addStateObserver(this); try {
nilusHelper = new Helper();
} catch (JAXBException e) {
e.printStackTrace();
}
}
@Override
@ -64,20 +82,43 @@ public class CalibrationHandler implements TethysStateObserver {
break;
case NEWPAMGUARDSELECTION:
case NEWPROJECTSELECTION:
case TRANSFERDATA:
case EXPORTRDATA:
case DELETEDATA:
case UPDATEMETADATA:
case UPDATESERVER:
updateDocumentsList();
if (isWantedState(tethysState)) {
updateDocumentsList();
}
default:
break;
}
}
/**
* Is it a state notification we want to respond to
* @param state
* @return true if worth it.
*/
protected boolean isWantedState(TethysState state) {
if (state.collection == null) {
return true;
}
switch (state.collection) {
case OTHER:
case Calibrations:
return true;
}
return false;
}
/**
* Update the list of documents associated with the selected instrument.
*/
private void updateDocumentsList() {
ArrayList<DocumentInfo> docsList = getArrayCalibrations();
// now immediately read the calibrations in again.
calibrationDataBlock.clear();;
calibrationsList.clear();;
NilusUnpacker unpacker = new NilusUnpacker();
for (DocumentInfo aDoc : docsList) {
Queries queries = tethysControl.getDbxmlConnect().getTethysQueries();
@ -109,7 +150,7 @@ public class CalibrationHandler implements TethysStateObserver {
}
DocumentNilusObject<Calibration> calDataUnit = new DocumentNilusObject(Collection.Calibrations, aDoc.getDocumentName(), calObj.getId(), calObj);
calibrationDataBlock.add(calDataUnit);
calibrationsList.add(calDataUnit);
// System.out.println(result);
} catch (Exception e) {
// TODO Auto-generated catch block
@ -119,47 +160,105 @@ public class CalibrationHandler implements TethysStateObserver {
}
public int exportAllCalibrations() {
Calibration sampleCal = new Calibration();
try {
Helper.createRequiredElements(sampleCal);
} catch (IllegalArgumentException | IllegalAccessException | InstantiationException e1) {
e1.printStackTrace();
}
sampleCal = CalibrationsExportWizard.showWizard(tethysControl.getGuiFrame(), sampleCal);
if (sampleCal == null) {
return 0;
}
PamArray array = ArrayManager.getArrayManager().getCurrentArray();
int nPhone = array.getHydrophoneCount();
DBXMLConnect dbxml = tethysControl.getDbxmlConnect();
int nExport = 0;
boolean overwrite = false;
boolean exists;
for (int i = 0; i < nPhone; i++) {
// String docName = getHydrophoneId(i);
Calibration calDoc = createCalibrationDocument(i);
String calDocName = getDocumentName(calDoc, i);
if (sampleCal != null) {
calDoc.setMetadataInfo(sampleCal.getMetadataInfo());
MetadataInfo oldMeta = calDoc.getMetadataInfo();
MetadataInfo newMeta = sampleCal.getMetadataInfo();
calDoc.setProcess(sampleCal.getProcess());
calDoc.setQualityAssurance(sampleCal.getQualityAssurance());
calDoc.setResponsibleParty(sampleCal.getResponsibleParty());
calDoc.setTimeStamp(sampleCal.getTimeStamp());
}
addParameterDetails(calDoc, i);
String calDocName = createDocumentName(calDoc, i);
exists = calDocumentExists(calDocName);
if (exists && overwrite == false) {
String msg = String.format("Calibration document %s already exists. Do you want to overwrite it and other documents from this date?", calDocName);
int ans = WarnOnce.showWarning("Calibration Export", msg, WarnOnce.OK_CANCEL_OPTION);
if (ans == WarnOnce.OK_OPTION) {
overwrite = true;
}
else {
return nExport;
}
}
boolean ok = false;
if (exists == true && overwrite == false) {
continue;
}
try {
if (exists) {
ok = dbxml.removeDocument(Collection.Calibrations, calDocName);
}
ok = dbxml.postAndLog(calDoc, calDocName);
} catch (TethysException e) {
// TODO Auto-generated catch block
e.printStackTrace();
tethysControl.showException(e);
ok = false;
break;
}
if (ok) {
nExport++;
}
}
tethysControl.sendStateUpdate(new TethysState(TethysState.StateType.EXPORTRDATA, Collection.Calibrations));
return nExport;
}
/**
* Get a name for the document, which is a bit like the id within
* the document, but also contain a yymmdd data string.
* Add the separate pamguard parameters to the document which are used
* to make up the overall calibration.
* @param calDoc
* @param i channel
* @return document name
* @param i
*/
private String getDocumentName(Calibration calDoc, int iChan) {
long docDate = System.currentTimeMillis();
XMLGregorianCalendar date = calDoc.getMetadataInfo().getDate();
if (date != null) {
docDate = TethysTimeFuncs.millisFromGregorianXML(date);
private void addParameterDetails(Calibration calDoc, int i) {
Parameters params = calDoc.getProcess().getParameters();
PamArray array = ArrayManager.getArrayManager().getCurrentArray();
AcquisitionControl daqControl = (AcquisitionControl) PamController.getInstance().findControlledUnit(AcquisitionControl.unitType);
AcquisitionParameters daqParams = daqControl.getAcquisitionParameters();
Hydrophone phone = array.getHydrophoneArray().get(i);
try {
nilusHelper.AddAnyElement(params.getAny(), "HydrophoneType", phone.getType());
nilusHelper.AddAnyElement(params.getAny(), "Sensitivity", String.format("%3.1f", phone.getSensitivity()));
nilusHelper.AddAnyElement(params.getAny(), "PreampGain", String.format("%3.1f", phone.getPreampGain()));
nilusHelper.AddAnyElement(params.getAny(), "ADCp-p", String.format("%3.2fV", daqParams.getVoltsPeak2Peak()));
Preamplifier preamp = daqParams.preamplifier;
if (preamp != null) {
nilusHelper.AddAnyElement(params.getAny(), "ADCAmplifier", String.format("%3.2fdB", preamp.getGain()));
}
} catch (JAXBException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
String dateStr = formatDate(docDate);
String name = String.format("%s_%s_ch%d", getCalibrationDocumentRoot(), dateStr, iChan);
return name;
}
/**
* Format the data in the dd MMMM yyyy format
* @param timeInMillis time in milliseconds
@ -176,12 +275,30 @@ public class CalibrationHandler implements TethysStateObserver {
}
/**
* Get a name for the document, which is a bit like the id within
* the document, but also contain a yymmdd data string.
* @param calDoc
* @param i channel
* @return document name
*/
private String createDocumentName(Calibration calDoc, int iChan) {
long docDate = System.currentTimeMillis();
XMLGregorianCalendar date = calDoc.getMetadataInfo().getDate();
if (date != null) {
docDate = TethysTimeFuncs.millisFromGregorianXML(date);
}
String dateStr = formatDate(docDate);
String name = String.format("%s_%s_ch%d", createCalibrationDocumentRoot(), dateStr, iChan);
return name;
}
/**
* Get a start of name for a calibration document. This will be used in the document name
* with a date and a channel, and the document Id just of the root and the channel.
* @return root string for document names and document id's.
*/
public String getCalibrationDocumentRoot() {
public String createCalibrationDocumentRoot() {
PamArray array = ArrayManager.getArrayManager().getCurrentArray();
if (array == null) {
return null;
@ -308,6 +425,59 @@ public class CalibrationHandler implements TethysStateObserver {
return calibration;
}
/**
* See if a document already exists. This should only occur if you
* try to export the same document twice with the same calibration date.
* @param documentName
* @return true if a document already exists.
*/
public boolean calDocumentExists(String documentName) {
if (calibrationsList == null) {
return false;
}
for (int i = 0; i < calibrationsList.size(); i++) {
if (calibrationsList.get(i).getDocumentName().equalsIgnoreCase(documentName)) {
return true;
}
}
return false;
}
/**
* Return if we have at least one document for every channel.
* @return true if all cal documents exist.
*/
public boolean haveAllChannelCalibrations() {
PamArray array = ArrayManager.getArrayManager().getCurrentArray();
int nPhone = array.getHydrophoneCount();
for (int i = 0; i < nPhone; i++) {
if (haveChannelCalibration(i) == false) {
return false;
}
}
return true;
}
/**
* Find whether we have a document for this instrument and channel.
* @param iChan
* @return true if we have an appropriate doc.
*/
public boolean haveChannelCalibration(int iChan) {
if (calibrationsList == null) {
return false;
}
String seachPattern = makeChannelNamePart(iChan);
for (int i = 0; i < calibrationsList.size(); i++) {
String docName = calibrationsList.get(i).getDocumentName();
if (docName.endsWith(seachPattern)) {
return true;
}
}
return false;
}
/**
* Get an id based on the instrument identifiers and channel number.
@ -321,21 +491,34 @@ public class CalibrationHandler implements TethysStateObserver {
if (array == null) {
return null;
}
String id = String.format("%s_ch%02d", getCalibrationDocumentRoot(), channelIndex);
String id = String.format("%s_%s", createCalibrationDocumentRoot(), makeChannelNamePart(channelIndex));
id = id.replace(" ", "_");
return id;
}
/**
* Make the final part of the document name / id which is the channel number.
* @param channelIndex channel index
* @return string in the form ch%02d (e.g. ch03)
*/
public String makeChannelNamePart(int channelIndex) {
return String.format("ch%02d", channelIndex);
}
/**
* @return the calibrationDataBlock
*/
public ArrayList<DocumentNilusObject<Calibration>> getCalibrationDataList() {
return calibrationDataBlock;
return calibrationsList;
}
/**
* Make a list of document names associated with this instrument.
* @return list of calibration documents using this instrument, based on the start of the document name.
*/
private ArrayList<DocumentInfo> getArrayCalibrations() {
ArrayList<DocumentInfo> allCals = tethysControl.getDbxmlQueries().getCollectionDocumentList(Collection.Calibrations);
String prefix = getCalibrationDocumentRoot();
String prefix = createCalibrationDocumentRoot();
// find doc names that have that root.
ArrayList<DocumentInfo> theseCals = new ArrayList<>();
for (DocumentInfo aDoc : allCals) {

View File

@ -0,0 +1,164 @@
package tethys.calibration.swing;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.List;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import PamView.dialog.PamGridBagContraints;
import PamView.wizard.PamWizard;
import nilus.AlgorithmType;
import nilus.AlgorithmType.Parameters;
import nilus.AlgorithmType.SupportSoftware;
import nilus.Calibration;
import nilus.Calibration.QualityAssurance;
import nilus.QualityValueBasic;
import tethys.calibration.CalibrationHandler;
public class CalibrationProcessCard extends CalibrationsCard {
private JPanel processPanel;
private JComboBox<String> calMethod;
private JTextArea software;
private JTextField version;
private JComboBox<String> qaQuality;
private JTextField qaComment;
public CalibrationProcessCard(PamWizard pamWizard) {
super(pamWizard, "Calibration Process");
this.setLayout(new BorderLayout());
processPanel = new JPanel(new GridBagLayout());
processPanel.setBorder(new TitledBorder("Calibration Process"));
this.add(BorderLayout.NORTH, processPanel);
GridBagConstraints c = new PamGridBagContraints();
calMethod = new JComboBox<String>();
String[] meths = CalibrationHandler.calibrationMethods;
for (int i = 0; i < meths.length; i++) {
calMethod.addItem(meths[i]);
}
qaQuality = new JComboBox<>();
String[] vals = CalibrationHandler.qaTypes;
for (int i = 0; i < vals.length; i++) {
qaQuality.addItem(vals[i]);
}
software = new JTextArea(5, 25);
software.setLineWrap(true);
software.setWrapStyleWord(true);
software.setToolTipText("Details of calibration method and software used");
version = new JTextField(20);
version.setToolTipText("Serial number of calibration device");
qaComment = new JTextField(20);
qaComment.setToolTipText("Comment on calibration quality");
processPanel.add(new JLabel("Method ", JLabel.RIGHT), c);
c.gridx++;
processPanel.add(calMethod, c);
c.gridx = 0;
c.gridy++;
c.gridwidth = 1;
processPanel.add(new JLabel("Serial number ", JLabel.RIGHT), c);
c.gridx++;
processPanel.add(version, c);
c.gridx = 0;
c.gridy++;
processPanel.add(new JLabel("Quality ", JLabel.RIGHT), c);
c.gridx++;
processPanel.add(qaQuality, c);
c.gridx = 0;
c.gridy++;
processPanel.add(new JLabel("QA Comment ", JLabel.RIGHT), c);
c.gridx++;
processPanel.add(qaComment, c);
this.add(BorderLayout.CENTER, makeScrollablePanel(software, "Calibration method"));
}
private JScrollPane makeScrollablePanel(JTextArea textArea, String title) {
// TODO Auto-generated method stub
// mainPanel.add(new Label(title, JLabel.LEFT));
// textArea.setMinimumSize(new Dimension(200, 200));
JScrollPane scrollPane = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBorder(new TitledBorder(title));
scrollPane.setPreferredSize(new Dimension(scrollPane.getPreferredSize().height/2, 0));
return scrollPane;
}
@Override
public boolean getParams(Calibration calibration) {
if (calibration == null) {
return false;
}
AlgorithmType process = calibration.getProcess();
if (process == null) {
process = new AlgorithmType();
calibration.setProcess(process);
}
process.setMethod((String) calMethod.getSelectedItem());
process.setVersion(version.getText());
process.setSoftware(software.getText());
if (software.getText() == null) {
getPamWizard().showWarning("You must specify the calibratin method used");
}
QualityAssurance qa = calibration.getQualityAssurance();
if (qa == null) {
qa = new QualityAssurance();
calibration.setQualityAssurance(qa);
}
qa.setComment(qaComment.getText());
qa.setQuality(QualityValueBasic.fromValue((String) qaQuality.getSelectedItem()));
// need to add a few fixed things for this to work...
// List<SupportSoftware> supportSoftware = process.getSupportSoftware();
Parameters params = process.getParameters();
if (params == null) {
params = new Parameters();
process.setParameters(params);
}
return true;
}
@Override
public void setParams(Calibration calibration) {
if (calibration == null) {
return;
}
AlgorithmType process = calibration.getProcess();
if (process != null) {
calMethod.setSelectedItem(process.getMethod());
version.setText(process.getVersion());
software.setText(process.getSoftware());
}
QualityAssurance qa = calibration.getQualityAssurance();
if (qa != null) {
QualityValueBasic qb = qa.getQuality();
if (qb != null) {
qaQuality.setSelectedItem(qb.value());
}
qaComment.setText(qa.getComment());
}
}
}

View File

@ -0,0 +1,13 @@
package tethys.calibration.swing;
import PamView.wizard.PamWizard;
import PamView.wizard.PamWizardCard;
import nilus.Calibration;
abstract public class CalibrationsCard extends PamWizardCard<Calibration> {
public CalibrationsCard(PamWizard pamWizard, String title) {
super(pamWizard, title);
}
}

View File

@ -0,0 +1,181 @@
package tethys.calibration.swing;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.xml.datatype.XMLGregorianCalendar;
import org.jdesktop.swingx.JXDatePicker;
import PamView.dialog.PamDialog;
import PamView.dialog.PamGridBagContraints;
import PamView.wizard.PamWizard;
import nilus.Calibration;
import nilus.ContactInfo;
import nilus.MetadataInfo;
import nilus.ResponsibleParty;
import tethys.TethysTimeFuncs;
import tethys.calibration.CalibrationHandler;
public class CalibrationsContactCard extends CalibrationsCard {
private JXDatePicker datePicker;
private JTextField individual, organisation, position, email;
private JComboBox<String> updateInterval;
public CalibrationsContactCard(PamWizard pamWizard) {
super(pamWizard, "Contact Details");
// TODO Auto-generated constructor stub
// setBorder(new TitledBorder("Contact"));
setLayout(new BorderLayout());
updateInterval = new JComboBox<>();
String[] vals = CalibrationHandler.updateOptions;
for (int i = 0; i < vals.length; i++) {
updateInterval.addItem(vals[i]);
}
JPanel datePanel = new JPanel(new GridBagLayout());
datePanel.setBorder(new TitledBorder("Calibration date"));
add(BorderLayout.NORTH, datePanel);
GridBagConstraints c = new PamGridBagContraints();
datePanel.add(new JLabel("Calibration date: ", JLabel.RIGHT), c);
datePicker = new JXDatePicker();
c.gridx++;
datePanel.add(datePicker, c);
c.gridx = 0;
c.gridy++;
datePanel.add(new JLabel("Update Frequency", JLabel.RIGHT), c);
c.gridx++;
datePanel.add(updateInterval, c);
JPanel contactPanel = new JPanel(new GridBagLayout());
contactPanel.setBorder(new TitledBorder("Contact"));
this.add(BorderLayout.CENTER, contactPanel);
c = new PamGridBagContraints();
contactPanel.add(new JLabel("Individual Name "), c);
c.gridx++;
contactPanel.add(individual = new JTextField(15), c);
c.gridx = 0;
c.gridy++;
contactPanel.add(new JLabel("Organisation "), c);
c.gridx++;
contactPanel.add(organisation = new JTextField(15), c);
c.gridx = 0;
c.gridy++;
contactPanel.add(new JLabel("Position "), c);
c.gridx++;
contactPanel.add(position = new JTextField(15), c);
c.gridx = 0;
c.gridy++;
contactPanel.add(new JLabel("Email "), c);
c.gridx++;
contactPanel.add(email = new JTextField(15), c);
c.gridx = 0;
c.gridy++;
}
@Override
public boolean getParams(Calibration cardParams) {
if (cardParams == null) {
return false;
}
MetadataInfo metaInf = cardParams.getMetadataInfo();
if (metaInf == null) {
metaInf = new MetadataInfo();
cardParams.setMetadataInfo(metaInf);
}
ResponsibleParty contact = metaInf.getContact();
if (contact == null) {
contact = new ResponsibleParty();
metaInf.setContact(contact);
}
ContactInfo contactInfo = contact.getContactInfo();
if (contactInfo == null) {
contactInfo = new ContactInfo();
contact.setContactInfo(contactInfo);
}
// so far as I'm aware, the meta info contains the time we create this record
// and the other timestamp is the data the calibration was donw.
metaInf.setDate(TethysTimeFuncs.xmlGregCalFromMillis(System.currentTimeMillis()));
metaInf.setUpdateFrequency((String) updateInterval.getSelectedItem());
contact.setIndividualName(individual.getText());
contact.setOrganizationName(organisation.getText());
contact.setPositionName(position.getText());
contactInfo.setContactInstructions(email.getText());
// and set this both as the RepsonsiblePArty and in the metadata.
cardParams.setResponsibleParty(contact);
Date date = datePicker.getDate();
if (date == null) {
return getPamWizard().showWarning("You must specify the data of the calibration");
}
long millis = date.getTime();
cardParams.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(millis));
return true;
}
private ResponsibleParty findResponsibleParty(Calibration cal) {
if (cal == null) {
return null;
}
MetadataInfo metaInfo = cal.getMetadataInfo();
if (metaInfo != null) {
ResponsibleParty resp = metaInfo.getContact();
if (resp != null && resp.getIndividualName() != null) {
return resp;
}
}
return cal.getResponsibleParty();
}
@Override
public void setParams(Calibration cardParams) {
// fill in as much as possible from the existing Calibration
ResponsibleParty resp = findResponsibleParty(cardParams);
if (resp != null) {
individual.setText(resp.getIndividualName());
organisation.setText(resp.getOrganizationName());
position.setText(resp.getPositionName());
ContactInfo cInf = resp.getContactInfo();
if (cInf != null) {
email.setText(cInf.getContactInstructions());
}
}
MetadataInfo metaInf = cardParams.getMetadataInfo();
if (metaInf != null) {
String uf = metaInf.getUpdateFrequency();
if (uf != null) {
updateInterval.setSelectedItem(uf);
}
}
XMLGregorianCalendar ts = cardParams.getTimeStamp();
if (ts != null) {
datePicker.setDate(new Date(TethysTimeFuncs.millisFromGregorianXML(ts)));
}
}
}

View File

@ -0,0 +1,42 @@
package tethys.calibration.swing;
import java.awt.Window;
import PamView.wizard.PamWizard;
import PamView.wizard.PamWizardCard;
import nilus.Calibration;
public class CalibrationsExportWizard extends PamWizard {
private Calibration sampleDocument;
private CalibrationsExportWizard(Window parentFrame, Calibration sampleDocument) {
super(parentFrame, "Calibrations Export");
this.sampleDocument = sampleDocument;
addCard(new CalibrationProcessCard(this));
addCard(new CalibrationsContactCard(this));
}
public static Calibration showWizard(Window parentFrame, Calibration sampleDocument) {
CalibrationsExportWizard wiz = new CalibrationsExportWizard(parentFrame, sampleDocument);
wiz.setParams();
wiz.setVisible(true);
return wiz.sampleDocument;
}
@Override
public void setCardParams(PamWizardCard wizardCard) {
wizardCard.setParams(sampleDocument);
}
@Override
public boolean getCardParams(PamWizardCard wizardCard) {
return wizardCard.getParams(sampleDocument);
}
@Override
public void cancelButtonPressed() {
sampleDocument = null;
}
}

View File

@ -0,0 +1,66 @@
package tethys.calibration.swing;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
import PamView.panel.PamPanel;
import tethys.TethysControl;
import tethys.calibration.CalibrationHandler;
import tethys.swing.TethysGUIPanel;
public class CalibrationsMainPanel extends TethysGUIPanel {
private CalibrationHandler calibrationHandler;
private CalibrationsTable calibrationsTable;
private JPanel mainPanel;
private JPanel ctrlPanel;
private JButton exportButton;
private JLabel warning;
public CalibrationsMainPanel(TethysControl tethysControl, CalibrationHandler calibrationHandler) {
super(tethysControl);
this.calibrationHandler = calibrationHandler;
mainPanel = new PamPanel(new BorderLayout());
mainPanel.setBorder(new TitledBorder("Instrument calibration information"));
calibrationsTable = new CalibrationsTable(tethysControl, calibrationHandler);
mainPanel.add(BorderLayout.CENTER, calibrationsTable.getComponent());
ctrlPanel = new PamPanel(new BorderLayout());
exportButton = new JButton("Export ...");
ctrlPanel.add(BorderLayout.WEST, exportButton);
warning = new JLabel();
ctrlPanel.add(BorderLayout.CENTER, warning);
mainPanel.add(BorderLayout.NORTH, ctrlPanel);
exportButton.setToolTipText("Export calibration data to database");
exportButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
exportCalibrations();
}
});
}
protected void exportCalibrations() {
calibrationHandler.exportAllCalibrations();
}
@Override
public JComponent getComponent() {
return mainPanel;
}
}

View File

@ -33,7 +33,7 @@ import tethys.calibration.CalibrationHandler;
import tethys.dbxml.TethysException;
import tethys.swing.TethysGUIPanel;
public class CalibrationsPanel extends TethysGUIPanel {
public class CalibrationsTable extends TethysGUIPanel {
private CalibrationHandler calibrationHandler;
@ -48,7 +48,7 @@ public class CalibrationsPanel extends TethysGUIPanel {
/**
* @param calibrationHandler
*/
public CalibrationsPanel(TethysControl tethysControl, CalibrationHandler calibrationHandler) {
public CalibrationsTable(TethysControl tethysControl, CalibrationHandler calibrationHandler) {
super(tethysControl);
this.tethysControl = tethysControl;
this.calibrationHandler = calibrationHandler;
@ -60,7 +60,6 @@ public class CalibrationsPanel extends TethysGUIPanel {
JScrollPane scrollPane = new JScrollPane(calTable);
mainPanel = new PamPanel(new BorderLayout());
mainPanel.setBorder(new TitledBorder("Instrument calibration information"));
mainPanel.add(BorderLayout.CENTER, scrollPane);
calTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
@ -177,7 +176,7 @@ public class CalibrationsPanel extends TethysGUIPanel {
try {
DocumentNilusObject<Calibration> doc = calibrationHandler.getCalibrationDataList().get(rows[i]);
docName = doc.getDocumentName();
tethysControl.getDbxmlConnect().removeDocument(Collection.Calibrations.collectionName(), docName);
tethysControl.getDbxmlConnect().removeDocument(Collection.Calibrations, docName);
} catch (TethysException e) {
System.out.println("Failed to delete " + docName);
System.out.println(e.getMessage());
@ -189,7 +188,7 @@ public class CalibrationsPanel extends TethysGUIPanel {
}
private void updateEverything() {
calibrationHandler.updateState(new TethysState(StateType.TRANSFERDATA));
getTethysControl().sendStateUpdate(new TethysState(StateType.DELETEDATA, Collection.Calibrations));
}
class CalibrationsTableModel extends AbstractTableModel {

View File

@ -282,7 +282,7 @@ An error will throw an exception.
}
return true;
}
/**
* Remove a document based on a collection name and a cdocument Id.
* @param collection collection name.
@ -290,23 +290,32 @@ An error will throw an exception.
* @return
* @throws TethysException
*/
public boolean removeDocument(String collection, String documentName) throws TethysException {
public boolean removeDocument(Collection collection, String documentName) throws TethysException {
return removeDocument(collection.collectionName(), documentName);
}
/**
* Remove a document based on a collection name and a document namw.
* @param collectionName collection name.
* @param documentName document name (not the internal Document Id)
* @return
* @throws TethysException
*/
public boolean removeDocument(String collectionName, String documentName) throws TethysException {
try {
// docId = "SoundTrap_600_HF_7129_ch00";
Object result = jerseyClient.removeDocument(collection, documentName );
Object result = jerseyClient.removeDocument(collectionName, documentName );
/**
* Return from a sucessful delete is something like
*
deployment = getTethysControl().getDeploymentHandler().createDeploymentDocument(freeId++, recordPeriod);
<DELETE>
<ITEM> ['ECoastNARW0'] </ITEM>
</DELETE>
An error will throw an exception.
<ITEM> ['ECoastNARW0'] </ITEM>
</DELETE>
An error will throw an exception.
*/
}
catch (Exception e) {
// System.out.printf("Error deleting %s %s: %s\n", collection, docId, e.getMessage());
String msg = String.format("Error deleting %s:%s", collection, documentName);
String msg = String.format("Error deleting %s:%s", collectionName, documentName);
throw new TethysException(msg, e.getLocalizedMessage());
}
return true;

View File

@ -54,6 +54,7 @@ import nilus.Helper;
import nilus.UnknownSensor;
import pamMaths.PamVector;
import pamMaths.STD;
import tethys.Collection;
import tethys.TethysControl;
import tethys.TethysLocationFuncs;
import tethys.TethysState;
@ -108,7 +109,7 @@ public class DeploymentHandler implements TethysStateObserver {
case NEWPROJECTSELECTION:
updateProjectDeployments();
break;
case TRANSFERDATA:
case EXPORTRDATA:
updateProjectDeployments();
break;
case UPDATESERVER:
@ -334,7 +335,7 @@ public class DeploymentHandler implements TethysStateObserver {
catch (TethysException e) {
getTethysControl().showException(e);
}
getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER));
getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER, Collection.Deployments));
}
/**
@ -372,7 +373,7 @@ public class DeploymentHandler implements TethysStateObserver {
getTethysControl().showException(e);
}
}
getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER));
getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER, Collection.Deployments));
}
/**

View File

@ -196,7 +196,7 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel {
} catch (TethysException e) {
getTethysControl().showException(e);
}
getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER));
getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER, Collection.Deployments));
}
/**

View File

@ -8,7 +8,8 @@ import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import tethys.TethysControl;
import tethys.calibration.swing.CalibrationsPanel;
import tethys.calibration.swing.CalibrationsMainPanel;
import tethys.calibration.swing.CalibrationsTable;
public class TethysMainPanel extends TethysGUIPanel {
@ -26,7 +27,7 @@ public class TethysMainPanel extends TethysGUIPanel {
private DetectionsExportPanel detectionsExportPanel;
private CalibrationsPanel calibrationPanel;
private CalibrationsMainPanel calibrationPanel;
public TethysMainPanel(TethysControl tethysControl) {
super(tethysControl);
@ -39,7 +40,7 @@ public class TethysMainPanel extends TethysGUIPanel {
detectionsExportPanel = new DetectionsExportPanel(tethysControl);
datablockSynchPanel.addTableObserver(detectionsExportPanel);
datablockSynchPanel.addTableObserver(datablockDetectionsPanel);
calibrationPanel = new CalibrationsPanel(tethysControl, tethysControl.getCalibrationHandler());
calibrationPanel = new CalibrationsMainPanel(tethysControl, tethysControl.getCalibrationHandler());
JSplitPane southwestSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
JPanel southEastPanel = new JPanel(new BorderLayout());

View File

@ -21,7 +21,7 @@ public class AlgorithmCard extends ExportWizardCard {
private JTextField method, software, version, supportSoftware;
public AlgorithmCard(DetectionsExportWizard detectionsExportWizard, TethysControl tethysControl, PamDataBlock dataBlock) {
super(tethysControl, "Algorithm", dataBlock);
super(tethysControl, detectionsExportWizard, "Algorithm", dataBlock);
setBorder(new TitledBorder("Algorithm details"));
method = new JTextField(40);
software = new JTextField(40);

View File

@ -11,7 +11,7 @@ public class DescriptionCard extends ExportWizardCard {
private DescriptionTypePanel descriptionPanel;
public DescriptionCard(DetectionsExportWizard detectionsExportWizard, TethysControl tethysControl, PamDataBlock dataBlock) {
super(tethysControl, "Description", dataBlock);
super(tethysControl, detectionsExportWizard, "Description", dataBlock);
this.setLayout(new BorderLayout());
descriptionPanel = new DescriptionTypePanel("Description data", true, true, true);
this.add(BorderLayout.CENTER, descriptionPanel.getMainPanel());

View File

@ -15,28 +15,27 @@ import javax.swing.JTextArea;
import javax.swing.border.TitledBorder;
import PamView.dialog.PamDialog;
import PamView.wizard.PamWizard;
import PamView.wizard.PamWizardCard;
import PamguardMVC.PamDataBlock;
import tethys.TethysControl;
import tethys.output.StreamExportParams;
import tethys.pamdata.TethysDataProvider;
public class DetectionsExportWizard extends PamDialog {
public class DetectionsExportWizard extends PamWizard {
private PamDataBlock dataBlock;
private CardLayout cardLayout;
private JPanel cardPanel;
private GranularityCard granularityCard;
private DescriptionCard descriptionCard;
private JButton prevButton;
private StreamExportParams streamExportParams;
private ArrayList<ExportWizardCard> wizardCards = new ArrayList();
private AlgorithmCard algorithmCard;
private ExportWorkerCard exportWorkerCard;
private TethysDataProvider tethysDataProvider;
private DetectionsExportWizard(Window parentFrame, TethysControl tethysControl, PamDataBlock dataBlock) {
super(parentFrame, "Detections Export", false);
super(parentFrame, "Detections Export");
this.dataBlock = dataBlock;
streamExportParams = tethysControl.getTethysExportParams().getStreamParams(dataBlock);
@ -44,31 +43,15 @@ public class DetectionsExportWizard extends PamDialog {
streamExportParams = new StreamExportParams(tethysControl, dataBlock, false);
}
tethysDataProvider = dataBlock.getTethysDataProvider(tethysControl);
getMainPanel().add(BorderLayout.NORTH, new ExportStreamInfoPanel(dataBlock));
cardLayout = new CardLayout();
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(BorderLayout.NORTH, new ExportStreamInfoPanel(dataBlock));
cardPanel = new JPanel(cardLayout);
mainPanel.add(BorderLayout.CENTER, cardPanel);
addCard(algorithmCard = new AlgorithmCard(this, tethysControl, dataBlock));
addCard(granularityCard = new GranularityCard(this, tethysControl, dataBlock));
addCard(descriptionCard = new DescriptionCard(this, tethysControl, dataBlock));
addCard(exportWorkerCard = new ExportWorkerCard(this, tethysControl, dataBlock));
cardLayout.first(cardPanel);
moveFirst();
setDialogComponent(mainPanel);
getOkButton().setText("Next");
prevButton = new JButton("Previous");
getButtonPanel().add(prevButton, 0);
prevButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
previousButton();
}
});
setResizable(true);
@ -77,8 +60,7 @@ public class DetectionsExportWizard extends PamDialog {
private void addCard(ExportWizardCard wizPanel) {
if (tethysDataProvider.wantExportDialogCard(wizPanel)) {
cardPanel.add(wizPanel, wizPanel.getTitle());
wizardCards.add(wizPanel);
super.addCard(wizPanel);
}
}
@ -88,49 +70,18 @@ public class DetectionsExportWizard extends PamDialog {
wiz.setVisible(true);
}
private void setParams() {
for (ExportWizardCard wizCard : wizardCards) {
wizCard.setParams(streamExportParams);
}
enableControls();
// granularityCard.setParams(streamExportParams);
}
/**
* Called when 'previous' button is clicked.
*/
protected void previousButton() {
cardLayout.previous(cardPanel);
enableControls();
}
public JButton getPreviousButton() {
return prevButton;
@Override
public void setCardParams(PamWizardCard wizardCard) {
wizardCard.setParams(streamExportParams);
}
@Override
public boolean getParams() {
int iCard = getCardIndex();
if (iCard < wizardCards.size()-1) {
if (checkCurrentCard()) {
cardLayout.next(cardPanel);
enableControls();
}
return false;
}
// if (cardLayout.)
// cardLayout.next(mainPanel);
// System.out.println(mainPanel.getComponent(0).isShowing());
/*
* there seems to be no obvious way of knowing which card is showing except
* to go through and see which one has isShowing() == true, then test for first and
* last, etc.
*/
enableControls();
return false;
public boolean getCardParams(PamWizardCard wizardCard) {
return wizardCard.getParams(streamExportParams);
}
@Override
public void cancelButtonPressed() {
// TODO Auto-generated method stub
@ -143,29 +94,5 @@ public class DetectionsExportWizard extends PamDialog {
}
private void enableControls() {
int iCard = getCardIndex();
prevButton.setEnabled(iCard > 0);
boolean isLast = iCard == wizardCards.size()-1;
getOkButton().setEnabled(!isLast);
// getOkButton().setText(isLast ? "Export" : "Next");
}
private boolean checkCurrentCard() {
int iCard = getCardIndex();
if (iCard < 0) {
return true;
}
return wizardCards.get(iCard).getParams(streamExportParams);
}
private int getCardIndex() {
for (int i = 0; i < cardPanel.getComponentCount(); i++) {
Component component = cardPanel.getComponent(i);
if (component.isVisible()) {
return i;
}
}
return -1;
}
}

View File

@ -2,6 +2,8 @@ package tethys.swing.export;
import javax.swing.JPanel;
import PamView.wizard.PamWizard;
import PamView.wizard.PamWizardCard;
import PamguardMVC.PamDataBlock;
import tethys.TethysControl;
import tethys.output.StreamExportParams;
@ -12,7 +14,7 @@ import tethys.output.StreamExportParams;
* @author dg50
*
*/
abstract public class ExportWizardCard extends JPanel {
abstract public class ExportWizardCard extends PamWizardCard<StreamExportParams> {
private static final long serialVersionUID = 1L;
@ -20,9 +22,9 @@ abstract public class ExportWizardCard extends JPanel {
private PamDataBlock dataBlock;
private TethysControl tethysControl;
public ExportWizardCard(TethysControl tethysControl, String title, PamDataBlock dataBlock) {
public ExportWizardCard(TethysControl tethysControl, PamWizard pamWizard, String title, PamDataBlock dataBlock) {
super(pamWizard, title);
this.tethysControl = tethysControl;
this.title = title;
this.dataBlock = dataBlock;
}
@ -33,13 +35,5 @@ abstract public class ExportWizardCard extends JPanel {
public TethysControl getTethysControl() {
return tethysControl;
}
public abstract boolean getParams(StreamExportParams streamExportParams);
public abstract void setParams(StreamExportParams streamExportParams);
public String getTitle() {
return title;
}
}

View File

@ -39,7 +39,7 @@ public class ExportWorkerCard extends ExportWizardCard implements DetectionExpor
private DetectionsExportWizard detectionsExportWizard;
public ExportWorkerCard(DetectionsExportWizard detectionsExportWizard, TethysControl tethysControl, PamDataBlock dataBlock) {
super(tethysControl, "Export", dataBlock);
super(tethysControl, detectionsExportWizard, "Export", dataBlock);
this.detectionsExportWizard = detectionsExportWizard;
setLayout(new BorderLayout());
setBorder(new TitledBorder("Export data"));

View File

@ -51,7 +51,7 @@ public class GranularityCard extends ExportWizardCard {
private GranularityEnumType[] allowedGranularities;
public GranularityCard(DetectionsExportWizard detectionsExportWizard, TethysControl tethysControl, PamDataBlock dataBlock) {
super(tethysControl, "Granularity", dataBlock);
super(tethysControl, detectionsExportWizard, "Granularity", dataBlock);
this.detectionsExportWizard = detectionsExportWizard;
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));