Species map i/o

This commit is contained in:
Douglas Gillespie 2023-09-24 21:59:15 +01:00
parent 8257122d14
commit 773f1f542b
8 changed files with 230 additions and 2 deletions

View File

@ -51,6 +51,7 @@ import tethys.output.TethysExportParams;
import tethys.output.TethysExporter;
import tethys.output.swing.TethysExportDialog;
import tethys.species.ITISFunctions;
import tethys.species.SpeciesMapManager;
import tethys.swing.ProjectDeploymentsDialog;
import tethys.swing.TethysTabPanel;
import tethys.swing.XMLStringView;
@ -200,6 +201,18 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
}
});
tethysMenu.add(showDeps);
tethysMenu.addSeparator();
JMenuItem mapItem = new JMenuItem("Export species maps ...");
mapItem.setToolTipText("Export all species maps (PAMGuard codes to ITIS codes to file for import into other configurations");
mapItem.addActionListener(SpeciesMapManager.getInstance().getExportAction(parentFrame));
tethysMenu.add(mapItem);
mapItem = new JMenuItem("Import species maps ...");
mapItem.setToolTipText("Import species maps (PAMGuard codes to ITIS codes to file for import into other configurations");
mapItem.addActionListener(SpeciesMapManager.getInstance().getImportAction(parentFrame));
tethysMenu.add(mapItem);
return tethysMenu;
}

View File

@ -6,9 +6,11 @@ import java.util.List;
import javax.swing.SwingWorker;
import PamController.PamControlledUnit;
import PamController.PamController;
import PamController.PamguardVersionInfo;
import PamModel.PamPluginInterface;
import PamUtils.PamCalendar;
import PamView.dialog.PamDialog;
import PamView.dialog.warn.WarnOnce;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
@ -40,6 +42,7 @@ import tethys.niluswraps.TethysCollections;
import tethys.output.StreamExportParams;
import tethys.output.TethysExportParams;
import tethys.pamdata.TethysDataProvider;
import tethys.species.DataBlockSpeciesManager;
/**
* Functions for handling output of Detections documents.
@ -203,6 +206,7 @@ public class DetectionsHandler {
* @param exportWorkerCard
*/
public void startExportThread(PamDataBlock pamDataBlock, StreamExportParams streamExportParams, DetectionExportObserver exportObserver) {
checkGranularity(pamDataBlock, streamExportParams);
tethysControl.getTethysExportParams().setStreamParams(pamDataBlock, streamExportParams);
activeExport = true;

View File

@ -247,6 +247,9 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
Detection detection = new Detection();
detection.setStart(TethysTimeFuncs.xmlGregCalFromMillis(dataUnit.getTimeMilliseconds()));
detection.setEnd(TethysTimeFuncs.xmlGregCalFromMillis(dataUnit.getEndTimeInMilliseconds()));
if (dataUnit.getEndTimeInMilliseconds() < dataUnit.getTimeMilliseconds()) {
System.out.printf("Error UID %d, end %s before start %s\n", dataUnit.getUID(), detection.getEnd(), detection.getStart());
}
DataBlockSpeciesManager speciesManager = pamDataBlock.getDatablockSpeciesManager();
SpeciesMapItem speciesItem = null;

View File

@ -27,6 +27,7 @@ abstract public class DataBlockSpeciesManager<T extends PamDataUnit> {
/**
* The serialised bit. Always exists (or should be created) even if there
* are no real species, via a defaultdefaultSpecies.
* Don't keep a local copy though since it may have been
*/
private DataBlockSpeciesMap datablockSpeciesMap;
@ -194,4 +195,28 @@ abstract public class DataBlockSpeciesManager<T extends PamDataUnit> {
public void setDefaultSpeciesCode(String defaultName) {
this.defaultSpeciesCode = defaultName;
}
/**
* Check the species map. Only return true if every species code
* has a map item. Otherwise it's not safe to export.
* @return null if all codes have a lookup, otherwise some sort of useful error information
*/
public String checkSpeciesMapError() {
ArrayList<String> codes = getAllSpeciesCodes();
if (codes == null || codes.size() == 0) {
return "No defined species codes"; // I guess that's OK ?
}
DataBlockSpeciesMap spMap = getDatablockSpeciesMap();
if (spMap == null) {
return "No species map";
}
for (String aCode : codes) {
SpeciesMapItem item = spMap.getItem(aCode);
if (item == null) {
return "No Species item for species code " + aCode;
}
}
return null;
}
}

View File

@ -1,17 +1,32 @@
package tethys.species;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import javax.swing.JFileChooser;
import PamController.PamControlledUnitSettings;
import PamController.PamController;
import PamController.PamFolders;
import PamController.PamSettingManager;
import PamController.PamSettings;
import PamUtils.PamFileFilter;
import PamView.dialog.warn.WarnOnce;
import PamguardMVC.PamDataBlock;
/**
* Master manager for species maps which will eventually allow for export and import from XML
* documents, databases and other things ...
* documents, databases and other things ...<br>
* (Perhaps not as XML, will simply output the serialized map - easier.
* @author dg50
*
*/
@ -19,10 +34,23 @@ public class SpeciesMapManager implements PamSettings {
private static SpeciesMapManager singleInstance = null;
/**
* Synch object to survive multithreading.
*/
private static Object synch = new Object();
/**
* Map of all species maps.
*/
private GlobalSpeciesMap globalSpeciesMap;
private JFileChooser ioFileChooser;
/**
* file end type for map files
*/
public static final String mapFileEnd = ".spmap";
private SpeciesMapManager() {
PamSettingManager.getInstance().registerSettings(this);
}
@ -101,4 +129,124 @@ public class SpeciesMapManager implements PamSettings {
return false;
}
}
public ActionListener getExportAction(Window parentFrame) {
return new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
exportSpeciesMaps(parentFrame);
}
};
}
public ActionListener getImportAction(Window parentFrame) {
return new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
importSpeciesMaps(parentFrame);
}
};
}
/**
* Export all species maps to a serialized object file.
* @param parentFrame
* @return
*/
public boolean exportSpeciesMaps(Window parentFrame) {
JFileChooser chooser = getFileChooser();
int ans = chooser.showSaveDialog(parentFrame);
if (ans != JFileChooser.APPROVE_OPTION) {
return false;
}
File opFile = chooser.getSelectedFile();
opFile = PamFileFilter.checkFileEnd(opFile, mapFileEnd, true);
// write it.
try {
ObjectOutputStream op = new ObjectOutputStream(new FileOutputStream(opFile));
op.writeObject(getSettingsReference());
op.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* Get a file chooser, which will remember folders, etc. while PAMGuard is open
* @return file chooser.
*/
private JFileChooser getFileChooser() {
if (ioFileChooser != null) {
return ioFileChooser;
}
PamFileFilter fileFilter = new PamFileFilter("Species map files", mapFileEnd);
ioFileChooser = new JFileChooser();
ioFileChooser.setFileFilter(fileFilter);
ioFileChooser.setCurrentDirectory(new File(PamFolders.getDefaultProjectFolder()));
return ioFileChooser;
}
/**
* Import global species maps from selected file.
* @param parentFrame
* @return
*/
public boolean importSpeciesMaps(Window parentFrame) {
JFileChooser chooser = getFileChooser();
int ans = chooser.showOpenDialog(parentFrame);
if (ans != JFileChooser.APPROVE_OPTION) {
return false;
}
File ipFile = chooser.getSelectedFile();
ipFile = PamFileFilter.checkFileEnd(ipFile, mapFileEnd, true);
GlobalSpeciesMap readSpeciesMap = null;
// read it.
try {
ObjectInputStream ip = new ObjectInputStream(new FileInputStream(ipFile));
readSpeciesMap = (GlobalSpeciesMap) ip.readObject();
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
return handleNewSpeciesMap(readSpeciesMap);
}
private boolean handleNewSpeciesMap(GlobalSpeciesMap readSpeciesMap) {
if (readSpeciesMap == null) {
return false;
}
// could put in a dialog to only select parts of the map if we wanted to ?
int ans = WarnOnce.showWarning("Global Species Map",
"Do you want to overwrite ALL PAMGaurd species maps with the imported data ?",
WarnOnce.YES_NO_OPTION);
if (ans == WarnOnce.CANCEL_OPTION) {
return false;
}
globalSpeciesMap = readSpeciesMap;
// no wupdate all datablock maps since they keep their own copies.
ArrayList<PamDataBlock> allDatablocks = PamController.getInstance().getDataBlocks();
for (PamDataBlock aBlock : allDatablocks) {
DataBlockSpeciesManager spManager = aBlock.getDatablockSpeciesManager();
if (spManager == null) {
continue;
}
DataBlockSpeciesMap blockMap = globalSpeciesMap.get(aBlock);
if (blockMap != null) {
spManager.setDatablockSpeciesMap(blockMap);
}
}
return true;
}
}

View File

@ -1,17 +1,20 @@
package tethys.species.swing;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
import PamController.PamController;
import PamView.PamGui;
import PamView.dialog.PamDialog;
import PamguardMVC.PamDataBlock;
import tethys.species.SpeciesMapManager;
public class DataBlockSpeciesDialog extends PamDialog {
@ -24,6 +27,7 @@ public class DataBlockSpeciesDialog extends PamDialog {
JPanel mainPanel = new JPanel(new BorderLayout());
speciesPanel = new DataBlockSpeciesPanel(dataBlock);
mainPanel.add(BorderLayout.CENTER, speciesPanel.getDialogComponent());
JButton itisButton = new JButton("Go to ITIS web site");
itisButton.setToolTipText("Go to ITIS website to search for species codes");
itisButton.addActionListener(new ActionListener() {
@ -33,9 +37,21 @@ public class DataBlockSpeciesDialog extends PamDialog {
}
});
JPanel nPanel = new JPanel(new BorderLayout());
nPanel.setBorder(new TitledBorder("Code management"));
nPanel.add(BorderLayout.EAST, itisButton);
// JPanel nwBit = new JPanel(new FlowLayout());
// JButton exportButton = new JButton("Export");
// exportButton.addActionListener(SpeciesMapManager.getInstance().getExportAction(parentFrame));
// nwBit.add(exportButton);
// JButton importButton = new JButton("Import");
// importButton.addActionListener(SpeciesMapManager.getInstance().getImportAction(parentFrame));
// nwBit.add(importButton);
// nPanel.add(BorderLayout.WEST, nwBit);
mainPanel.add(BorderLayout.NORTH, nPanel);
setDialogComponent(mainPanel);
setResizable(true);
}
protected void gotoITIS() {

View File

@ -6,6 +6,7 @@ import java.util.ArrayList;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.TitledBorder;
import PamView.dialog.PamDialogPanel;
@ -30,7 +31,8 @@ public class DataBlockSpeciesPanel implements PamDialogPanel {
this.dataBlock = dataBlock;
mainPanel = new JPanel(new BorderLayout());
speciesPanel = new JPanel();
mainPanel.add(speciesPanel, BorderLayout.CENTER);
JScrollPane scrollPane = new JScrollPane(speciesPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
mainPanel.add(scrollPane, BorderLayout.CENTER);
mainPanel.setBorder(new TitledBorder(dataBlock.getDataName()));
}

View File

@ -11,10 +11,13 @@ import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
import PamController.PamController;
import PamView.dialog.PamDialog;
import PamView.dialog.PamGridBagContraints;
import PamView.panel.PamAlignmentPanel;
import PamguardMVC.PamDataBlock;
import tethys.TethysControl;
import tethys.species.DataBlockSpeciesManager;
import tethys.swing.export.DetectionsExportWizard;
public class DetectionsExportPanel extends TethysGUIPanel implements StreamTableObserver {
@ -53,6 +56,20 @@ public class DetectionsExportPanel extends TethysGUIPanel implements StreamTable
if (selectedDataBlock == null) {
return;
}
/**
* Check the species map is OK before doing anything.
*/
DataBlockSpeciesManager spManager = selectedDataBlock.getDatablockSpeciesManager();
if (spManager != null) {
String error = spManager.checkSpeciesMapError();
if (error != null) {
PamDialog.showWarning(PamController.getMainFrame(), "Datablock species manager error", error);
spManager.showSpeciesDialog();
return;
}
}
DetectionsExportWizard.showDialog(getTethysControl().getGuiFrame(), getTethysControl(), selectedDataBlock);
}