ITIS Codes GUI

Basic system in place for handling ITIS species codes.
This commit is contained in:
Douglas Gillespie 2023-07-20 19:06:42 +01:00
parent 5c969d8889
commit 9018176899
11 changed files with 385 additions and 32 deletions

View File

@ -50,6 +50,7 @@ import tethys.output.DatablockSynchInfo;
import tethys.output.TethysExportParams;
import tethys.output.TethysExporter;
import tethys.output.swing.TethysExportDialog;
import tethys.species.ITISFunctions;
import tethys.swing.ProjectDeploymentsDialog;
import tethys.swing.TethysTabPanel;
import tethys.swing.XMLStringView;
@ -85,6 +86,8 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
private DeploymentHandler deploymentHandler;
private DetectionsHandler detectionsHandler;
private ITISFunctions itisFunctions;
public TethysControl(String unitName) {
super(unitType, unitName);
@ -615,4 +618,14 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
}
}
/**
* @return the itisFunctions
*/
public ITISFunctions getItisFunctions() {
if (itisFunctions == null) {
itisFunctions = new ITISFunctions(this);
}
return itisFunctions;
}
}

View File

@ -61,7 +61,7 @@ public class DBXMLQueries {
* @return query result
* @throws TethysQueryException
*/
private DBQueryResult executeQuery(String jsonQueryString) throws TethysQueryException {
public DBQueryResult executeQuery(String jsonQueryString) throws TethysQueryException {
long t1 = System.currentTimeMillis();
DBQueryResult result = null;
TethysQueryException tException = null;
@ -636,7 +636,7 @@ public class DBXMLQueries {
return blockCounts;
}
private String getElementData(Element root, String elName) {
public String getElementData(Element root, String elName) {
String[] tree = elName.split("\\.");
for (String element : tree) {
NodeList nodeList = root.getElementsByTagName(element);
@ -647,12 +647,13 @@ public class DBXMLQueries {
Node firstNode = nodeList.item(0);
if (firstNode instanceof Element) {
root = (Element) firstNode;
break;
}
}
return root.getTextContent();
}
private Document convertStringToXMLDocument(String xmlString) {
public Document convertStringToXMLDocument(String xmlString) {
//Parser that produces DOM object trees from XML content
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

View File

@ -23,6 +23,7 @@ abstract public class DataBlockSpeciesManager<T extends PamDataUnit> {
public DataBlockSpeciesManager(PamDataBlock<T> dataBlock) {
super();
this.dataBlock = dataBlock;
datablockSpeciesMap = SpeciesMapManager.getInstance().getSpeciesMap(dataBlock);
}
public SpeciesMapItem getSpeciesItem(T dataUnit) {
@ -38,6 +39,9 @@ abstract public class DataBlockSpeciesManager<T extends PamDataUnit> {
}
public DataBlockSpeciesMap getDatablockSpeciesMap() {
if (datablockSpeciesMap == null) {
datablockSpeciesMap = new DataBlockSpeciesMap();
}
return datablockSpeciesMap;
}

View File

@ -0,0 +1,32 @@
package tethys.species;
import java.io.Serializable;
import java.util.HashMap;
import PamguardMVC.PamDataBlock;
public class GlobalSpeciesMap implements Serializable {
public static final long serialVersionUID = 1L;
private HashMap<String, DataBlockSpeciesMap> datablockMaps;
/**
* @return the datablockMaps
*/
private synchronized HashMap<String, DataBlockSpeciesMap> getDatablockMaps() {
if (datablockMaps == null) {
datablockMaps = new HashMap<>();
}
return datablockMaps;
}
public void put(PamDataBlock pamDataBlock, DataBlockSpeciesMap dataBlockSpeciesMap) {
getDatablockMaps().put(pamDataBlock.getLongDataName(), dataBlockSpeciesMap);
}
public DataBlockSpeciesMap get(PamDataBlock pamDataBlock) {
return getDatablockMaps().get(pamDataBlock.getLongDataName());
}
}

View File

@ -0,0 +1,84 @@
package tethys.species;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import PamController.settings.output.xml.PAMGuardXMLPreview;
import PamController.settings.output.xml.PamguardXMLWriter;
import tethys.TethysControl;
import tethys.dbxml.DBQueryResult;
import tethys.dbxml.DBXMLQueries;
import tethys.dbxml.TethysQueryException;
/**
* Functions associated with pulling ITIS information from the databsae.
* @author dg50
*
*/
public class ITISFunctions {
private TethysControl tethysControl;
public ITISFunctions(TethysControl tethysControl) {
super();
this.tethysControl = tethysControl;
}
public TethysITISResult getITISInformation(int itisCode) {
/*
* hope to get back something like
*
<?xml version="1.0" encoding="ISO-8859-1"?><Result xmlns="http://tethys.sdsu.edu/schema/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<rank>
<tsn>180488</tsn>
<taxon_unit>Species</taxon_unit>
<completename>Physeter macrocephalus</completename>
<vernacular>
<name language="English">Sperm Whale</name>
<name language="English">cachalot</name>
</vernacular>
</rank>
</Result>
*/
String jQ = "{\"return\":[\"ranks/rank\"],\"select\":[{\"op\":\"=\",\"operands\":[\"ranks/rank/tsn\",\"SPECIESCODE\"],\"optype\":\"binary\"}],\"enclose\":1}";
jQ = jQ.replace("SPECIESCODE", String.format("%d", itisCode));
DBXMLQueries dbQueries = tethysControl.getDbxmlQueries();
DBQueryResult qResult = null;
try {
qResult = dbQueries.executeQuery(jQ);
} catch (TethysQueryException e) {
e.printStackTrace();
return null;
}
Document doc = dbQueries.convertStringToXMLDocument(qResult.queryResult);
Element docEl = doc.getDocumentElement();
// doc.
// PAMGuardXMLPreview xmlPreview = new PAMGuardXMLPreview(null, "returned", qResult.queryResult)
PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
String fDoc = pamXMLWriter.getAsString(doc, true);
System.out.println(fDoc);
String tsn = dbQueries.getElementData(docEl, "tsn");
if (tsn == null) {
return null;
}
String taxunit = dbQueries.getElementData(docEl, "taxon_unit");
String latin = dbQueries.getElementData(docEl, "completename");
// try to find a vernacular.
NodeList vEls = doc.getElementsByTagName("vernacular");
String vernacular = null;
if (vEls.getLength() > 0) {
Node f = vEls.item(0);
if (f instanceof Element) {
vernacular = dbQueries.getElementData((Element) f, "name");
}
}
return new TethysITISResult(itisCode, taxunit, latin, vernacular);
}
}

View File

@ -1,5 +1,104 @@
package tethys.species;
public class SpeciesMapManager {
import java.io.Serializable;
import java.util.ArrayList;
import PamController.PamControlledUnitSettings;
import PamController.PamController;
import PamController.PamSettingManager;
import PamController.PamSettings;
import PamguardMVC.PamDataBlock;
/**
* Master manager for species maps which will eventually allow for export and import from XML
* documents, databases and other things ...
* @author dg50
*
*/
public class SpeciesMapManager implements PamSettings {
private static SpeciesMapManager singleInstance = null;
private static Object synch = new Object();
private GlobalSpeciesMap globalSpeciesMap;
private SpeciesMapManager() {
PamSettingManager.getInstance().registerSettings(this);
}
/**
* Get an instance of the global species manager. This handles look up tables
* for each datablock to convert from internal PAMGuard names to ITIS species codes and
* usefully call types for output to Tethys.
* @return
*/
public static SpeciesMapManager getInstance() {
if (singleInstance == null) {
synchronized (synch) {
if (singleInstance == null) {
singleInstance = new SpeciesMapManager();
}
}
}
return singleInstance;
}
@Override
public String getUnitName() {
return "Global Species Codes";
}
@Override
public String getUnitType() {
return "Global Species Codes";
}
@Override
public Serializable getSettingsReference() {
gatherSpeciesMaps();
return globalSpeciesMap;
}
/**
* Get species maps from all PAMGuard datablocks which have such a map
*/
private void gatherSpeciesMaps() {
if (globalSpeciesMap == null) {
globalSpeciesMap = new GlobalSpeciesMap();
}
ArrayList<PamDataBlock> allDataBlocks = PamController.getInstance().getDataBlocks();
for (PamDataBlock aBlock : allDataBlocks) {
DataBlockSpeciesManager spManager = aBlock.getDatablockSpeciesManager();
if (spManager == null) {
continue;
}
DataBlockSpeciesMap speciesMap = spManager.getDatablockSpeciesMap();
globalSpeciesMap.put(aBlock, speciesMap);
}
}
public DataBlockSpeciesMap getSpeciesMap(PamDataBlock pamDataBlock) {
if (globalSpeciesMap == null) {
return null;
}
return globalSpeciesMap.get(pamDataBlock);
}
@Override
public long getSettingsVersion() {
return GlobalSpeciesMap.serialVersionUID;
}
@Override
public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
Object obj = pamControlledUnitSettings.getSettings();
if (obj instanceof GlobalSpeciesMap) {
this.globalSpeciesMap = (GlobalSpeciesMap) obj;
return true;
}
else {
return false;
}
}
}

View File

@ -40,7 +40,7 @@ public class SpeciesTest {
System.out.printf("Query time was %3.1fms\n" , (double) (t2-t1)/1e6);
System.out.println(queryResult);
TethysITISResult itisResult = new TethysITISResult(queryResult);
// TethysITISResult itisResult = new TethysITISResult(queryResult);
}
/*
*
@ -83,9 +83,9 @@ public class SpeciesTest {
}
private void runJson() {
// String jQ = "{\"return\":[\"Deployment\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Deployment/Project\",\"DCLDE2022\"],\"optype\":\"binary\"}],\"enclose\":1}";
// String jQ = "{\"return\":[\"ranks/rank\"],\"select\":[{\"op\":\"=\",\"operands\":[\"ranks/rank/tsn\",\"624908\"],\"optype\":\"binary\"}],\"enclose\":1}";
String jQ = "{\"return\":[\"ranks/rank\"],\"select\":[{\"op\":\"=\",\"operands\":[\"ranks/rank/tsn\",\"180488\"],\"optype\":\"binary\"}],\"enclose\":1}";
// String jQ = "{\"return\":[\"ranks/rank\"],\"select\":[{\"op\":\"=\",\"operands\":[\"ranks/rank/completename\",\"Mesoplodon\"],\"optype\":\"binary\"}],\"enclose\":1}";
String jQ = "{\"return\":[\"ranks/rank\"],\"select\":[{\"op\":\"dbxml:contains\",\"operands\":[\"ranks/rank/completename\",\"Mesoplodon\"],\"optype\":\"function\"}],\"enclose\":1}";
// String jQ = "{\"return\":[\"ranks/rank\"],\"select\":[{\"op\":\"dbxml:contains\",\"operands\":[\"ranks/rank/completename\",\"Mesoplodon\"],\"optype\":\"function\"}],\"enclose\":1}";
System.out.println(jQ);

View File

@ -1,12 +1,5 @@
package tethys.species;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
/**
* Class to hold and unpack a XML string returned from the ITIS_ranks document
@ -16,22 +9,52 @@ import org.xml.sax.InputSource;
*/
public class TethysITISResult {
private int itisCode;
private String taxon_unit;
private String latin;
private String vernacular;
/**
* Construct a ITIS object from XML data
* @param itisCode
* @param xmlData
* @param vernacular
* @param latin
*/
public TethysITISResult(String xmlData) {
public TethysITISResult(int itisCode, String taxon_unit, String latin, String vernacular) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//API to obtain DOM Document instance
DocumentBuilder builder = null;
// //Create DocumentBuilder with default configuration
// builder = factory.newDocumentBuilder();
//
// //Parse the content to Document object
// Document doc = builder.parse(new InputSource(new StringReader(xmlData)));
this.itisCode = itisCode;
this.taxon_unit = taxon_unit;
this.latin = latin;
this.vernacular = vernacular;
}
/**
* @return the itisCode
*/
public int getItisCode() {
return itisCode;
}
/**
* @return the taxon_unit
*/
public String getTaxon_unit() {
return taxon_unit;
}
/**
* @return the latin
*/
public String getLatin() {
return latin;
}
/**
* @return the vernacular
*/
public String getVernacular() {
return vernacular;
}
}

View File

@ -1,7 +1,15 @@
package tethys.species.swing;
import java.awt.BorderLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import PamController.PamController;
import PamView.PamGui;
import PamView.dialog.PamDialog;
import PamguardMVC.PamDataBlock;
@ -9,14 +17,28 @@ public class DataBlockSpeciesDialog extends PamDialog {
private static final long serialVersionUID = 1L;
DataBlockSpeciesPanel speciesPanel;
private DataBlockSpeciesPanel speciesPanel;
private DataBlockSpeciesDialog(Window parentFrame, PamDataBlock dataBlock) {
super(parentFrame, dataBlock.getDataName() + " species", false);
JPanel mainPanel = new JPanel(new BorderLayout());
speciesPanel = new DataBlockSpeciesPanel(dataBlock);
setDialogComponent(speciesPanel.getDialogComponent());
mainPanel.add(BorderLayout.CENTER, speciesPanel.getDialogComponent());
JButton itisButton = new JButton("Go to ITIS web site");
itisButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
gotoITIS();
}
});
mainPanel.add(BorderLayout.NORTH, itisButton);
setDialogComponent(mainPanel);
}
protected void gotoITIS() {
PamGui.openURL("https://www.itis.gov");
}
public static void showDialog(Window parentFrame, PamDataBlock dataBlock) {
DataBlockSpeciesDialog speciesDialog = new DataBlockSpeciesDialog(parentFrame, dataBlock);
speciesDialog.setParams();

View File

@ -22,6 +22,8 @@ public class DataBlockSpeciesPanel implements PamDialogPanel {
private PamDataBlock dataBlock;
private JPanel speciesPanel;
private ArrayList<SpeciesSubPanel> subPanels = new ArrayList<>();
public DataBlockSpeciesPanel(PamDataBlock dataBlock) {
super();
@ -41,6 +43,7 @@ public class DataBlockSpeciesPanel implements PamDialogPanel {
public void setParams() {
speciesPanel.removeAll();
speciesPanel.setLayout(new BoxLayout(speciesPanel, BoxLayout.Y_AXIS));
subPanels.clear();
DataBlockSpeciesManager speciesManager = dataBlock.getDatablockSpeciesManager();
DataBlockSpeciesTypes speciesTypes = speciesManager.getSpeciesTypes();
@ -48,6 +51,7 @@ public class DataBlockSpeciesPanel implements PamDialogPanel {
DataBlockSpeciesMap speciesMap = speciesManager.getDatablockSpeciesMap();
for (String aSpecies : speciesNames) {
SpeciesSubPanel subPanel = new SpeciesSubPanel(aSpecies);
subPanels.add(subPanel);
speciesPanel.add(subPanel.getDialogComponent());
if (speciesMap != null) {
SpeciesMapItem speciesInfo = speciesMap.getItem(aSpecies);
@ -58,8 +62,19 @@ public class DataBlockSpeciesPanel implements PamDialogPanel {
@Override
public boolean getParams() {
// TODO Auto-generated method stub
return false;
DataBlockSpeciesManager speciesManager = dataBlock.getDatablockSpeciesManager();
DataBlockSpeciesMap speciesMap = speciesManager.getDatablockSpeciesMap();
int errors = 0;
for (SpeciesSubPanel subPanel : subPanels) {
SpeciesMapItem mapItem = subPanel.getParams();
if (mapItem == null) {
errors++;
}
else {
speciesMap.putItem(mapItem.getPamguardName(), mapItem);
}
}
return errors == 0;
}
}

View File

@ -2,6 +2,8 @@ package tethys.species.swing;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
@ -10,8 +12,13 @@ import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.BevelBorder;
import PamController.PamController;
import PamView.dialog.PamDialog;
import PamView.dialog.PamGridBagContraints;
import tethys.TethysControl;
import tethys.species.ITISFunctions;
import tethys.species.SpeciesMapItem;
import tethys.species.TethysITISResult;
public class SpeciesSubPanel {
@ -31,7 +38,7 @@ public class SpeciesSubPanel {
c.gridx++;
mainPanel.add(new JLabel(" ITIS code ", JLabel.RIGHT), c);
c.gridx++;
mainPanel.add(itisCode = new JTextField(3), c);
mainPanel.add(itisCode = new JTextField(6), c);
c.gridx ++;
mainPanel.add(searchButton = new JButton("Find"));
@ -66,6 +73,43 @@ public class SpeciesSubPanel {
latinName.setToolTipText("Scientific name");
commonName.setToolTipText("Common name");
searchButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
searchSpecies(e);
}
});
}
/**
* Action when 'Find' button is pressed.
* @param e
*/
protected void searchSpecies(ActionEvent e) {
TethysControl tethysControl = (TethysControl) PamController.getInstance().findControlledUnit(TethysControl.unitType);
if (tethysControl == null) {
return;
}
ITISFunctions itisFunctions = tethysControl.getItisFunctions();
int itisCode = 0;
try {
itisCode = Integer.valueOf(this.itisCode.getText());
}
catch (NumberFormatException ex) {
PamDialog.showWarning(PamController.getMainFrame(), "No Code", "Enter avalid ITIS code");
return;
}
TethysITISResult itisInfo = itisFunctions.getITISInformation(itisCode);
if (itisInfo != null) {
if (itisInfo.getLatin() != null) {
latinName.setText(itisInfo.getLatin());
}
if (itisInfo.getVernacular() != null) {
commonName.setText(itisInfo.getVernacular());
}
}
// System.out.println(itisInfo);
}
public JComponent getDialogComponent() {
@ -88,8 +132,24 @@ public class SpeciesSubPanel {
}
public SpeciesMapItem getParams() {
// TODO Auto-generated method stub
return null;
Integer tsn = null;
String vernacular = null;
String latin = null;
try {
tsn = Integer.valueOf(itisCode.getText());
}
catch (NumberFormatException e) {
PamDialog.showWarning(PamController.getMainFrame(), pamguardName.getText(), "You must specified an ITIS taxanomic code");
return null;
}
latin = latinName.getText();
vernacular = commonName.getText();
String callType = this.callType.getText();
if (callType == null || callType.length() == 0) {
PamDialog.showWarning(PamController.getMainFrame(), pamguardName.getText(), "You must specified a call type");
return null;
}
return new SpeciesMapItem(tsn, callType, pamguardName.getText(), latin, vernacular);
}
}