Species info

Sort out of species info which hopefully now deals with all
eventualities.
This commit is contained in:
Douglas Gillespie 2023-08-29 11:53:40 +01:00
parent 74deebe446
commit 07ced6ae6d
11 changed files with 150 additions and 45 deletions

View File

@ -3,7 +3,8 @@ package RightWhaleEdgeDetector.species;
import PamguardMVC.PamDataBlock;
import RightWhaleEdgeDetector.RWEDataUnit;
import tethys.species.DataBlockSpeciesManager;
import tethys.species.DataBlockSpeciesTypes;
import tethys.species.DataBlockSpeciesCodes;
import tethys.species.SpeciesMapItem;
public class RWSpeciesManager extends DataBlockSpeciesManager<RWEDataUnit> {
@ -11,15 +12,16 @@ public class RWSpeciesManager extends DataBlockSpeciesManager<RWEDataUnit> {
public RWSpeciesManager(PamDataBlock<RWEDataUnit> dataBlock) {
super(dataBlock);
setDefaultDefaultSpecies(new SpeciesMapItem(RWSpeciesTypes.eubalaena, RWSpeciesTypes.onlyType, RWSpeciesTypes.defaultName));
}
@Override
public DataBlockSpeciesTypes getSpeciesTypes() {
return rwSpeciesTypes;
public DataBlockSpeciesCodes getSpeciesCodes() {
return null;
}
@Override
public String getSpeciesString(RWEDataUnit dataUnit) {
public String getSpeciesCode(RWEDataUnit dataUnit) {
return RWSpeciesTypes.onlyType;
}

View File

@ -1,15 +1,17 @@
package RightWhaleEdgeDetector.species;
import tethys.species.DataBlockSpeciesTypes;
import tethys.species.DataBlockSpeciesCodes;
public class RWSpeciesTypes extends DataBlockSpeciesTypes {
public class RWSpeciesTypes extends DataBlockSpeciesCodes {
public static final String onlyType = "Up call";
private static final int glacialis = 180536;
public static final int eubalaena = 180536;
public static final String defaultName = "Right Whale";
public RWSpeciesTypes() {
super(glacialis, onlyType);
super(eubalaena, defaultName, onlyType);
}
}

View File

@ -4,7 +4,7 @@ import clickDetector.ClickControl;
import clickDetector.ClickDataBlock;
import clickDetector.ClickDetection;
import tethys.species.DataBlockSpeciesManager;
import tethys.species.DataBlockSpeciesTypes;
import tethys.species.DataBlockSpeciesCodes;
import tethys.species.ITISTypes;
import tethys.species.SpeciesMapItem;
@ -16,11 +16,11 @@ public class ClickBlockSpeciesManager extends DataBlockSpeciesManager<ClickDetec
super(clickDataBlock);
this.clickControl = clickControl;
setDefaultDefaultSpecies(new SpeciesMapItem(ITISTypes.UNKNOWN, "Unknown", "Unknown"));
setDefaultName("Unknown");
setDefaultSpeciesCode("Unknown");
}
@Override
public DataBlockSpeciesTypes getSpeciesTypes() {
public DataBlockSpeciesCodes getSpeciesCodes() {
ClickTypeMasterManager masterManager = clickControl.getClickTypeMasterManager();
if (masterManager == null) {
return null;
@ -28,16 +28,16 @@ public class ClickBlockSpeciesManager extends DataBlockSpeciesManager<ClickDetec
String[] speciesList = masterManager.getSpeciesList();
// add the default
String[] fullList = new String[speciesList.length+1];
fullList[0] = getDefaultName();
fullList[0] = getDefaultSpeciesCode();
for (int i = 0; i < speciesList.length; i++) {
fullList[i+1] = speciesList[i];
}
return new DataBlockSpeciesTypes("Click", fullList);
return new DataBlockSpeciesCodes("Click", fullList);
}
@Override
public String getSpeciesString(ClickDetection dataUnit) {
public String getSpeciesCode(ClickDetection dataUnit) {
ClickTypeMasterManager masterManager = clickControl.getClickTypeMasterManager();
if (masterManager == null) {
return null;

View File

@ -382,7 +382,7 @@ public class PamVector implements Serializable, Cloneable, PamCoordinate, Manage
* @return magnitude of those dimensions only.
*/
public double norm(int nDim) {
return Math.sqrt(normSquared(2));
return Math.sqrt(normSquared(nDim));
}
/**
*

View File

@ -9,11 +9,12 @@ import java.util.ArrayList;
* @author dg50
*
*/
public class DataBlockSpeciesTypes {
public class DataBlockSpeciesCodes {
/**
* List of species names / codes associated with this data block. These can be translated,
* via a HashMap to more detailed objects which include an ITIS code.
* These are the internal codes of each detector - whatever it uses.
*/
private ArrayList<String> speciesNames;
@ -31,7 +32,7 @@ public class DataBlockSpeciesTypes {
/**
* @param defaultType
*/
public DataBlockSpeciesTypes(String defaultType) {
public DataBlockSpeciesCodes(String defaultType) {
this.defaultType = defaultType;
}
@ -39,8 +40,10 @@ public class DataBlockSpeciesTypes {
* @param itisDefault
* @param defaultType
*/
public DataBlockSpeciesTypes(int itisDefault, String defaultType) {
public DataBlockSpeciesCodes(int itisDefault, String defaultName, String defaultType) {
this.itisDefault = itisDefault;
speciesNames = new ArrayList<>();
speciesNames.add(defaultName);
this.defaultType = defaultType;
}
@ -48,7 +51,7 @@ public class DataBlockSpeciesTypes {
* constructor to use with a array of String names.
* @param speciesList
*/
public DataBlockSpeciesTypes(String defaultType, String[] speciesList) {
public DataBlockSpeciesCodes(String defaultType, String[] speciesList) {
this.defaultType = defaultType;
if (speciesList == null) {
speciesNames = new ArrayList<>();

View File

@ -1,5 +1,7 @@
package tethys.species;
import java.util.ArrayList;
import PamController.PamController;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
@ -7,31 +9,86 @@ import tethys.species.swing.DataBlockSpeciesDialog;
/**
* Manage species conversion for a single datablock.
*
* there seem to be three types of manager:<br>
* 1. Datablocks which have a totally free list of species codes, such as the click detector, or whistle classifier <br>
* 1a. A slight variation on this is blocks which have a list and also a default for data units which aren't classified.<br>
* 2. Datablocks which have a single type which may be unknown or partially known, but we want the possibility of overriding it.
* e.g. the whistle detector may default to odontocete, but may be overridden to a mystecete species.<br>
* 3. Datablocks with no information, or where the list from (1.) is empty. <p>
* In all cases, we need to handle this reasonably sensibly. The code list is always the start of this and must
* always return something, even if it's 'unknown'.
*
* @author dg50
*
*/
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.
*/
private DataBlockSpeciesMap datablockSpeciesMap;
private PamDataBlock<T> dataBlock;
private String defaultName = null;
/*
* Below are three ways of getting species codes. At least ONE of these
* must return something.
*/
/**
* Object that contains a list of species codes. This may be fluid
* between configurations and may change during a session, e.g. through
* the addition of a new click type or changes to the whistle classifier settings.
* @return object containing a list of species types.
*/
public abstract DataBlockSpeciesCodes getSpeciesCodes();
/**
* A default species code. Can be null, in which case it won't be used or
* can be set to something like 'Unknown'
*/
private String defaultSpeciesCode = null;
/**
* For use in detectors that have a strong default species, but no
* real list of different species codes. Can be left null.
*/
private SpeciesMapItem defaultDefaultSpecies = null;
public abstract DataBlockSpeciesTypes getSpeciesTypes();
public abstract String getSpeciesString(T dataUnit);
/**
* Gets a species string for a specific data unit, This is abstracted
* since different detectors store this in non standard ways. The result of
* this should be within the set provided by getSpeciesCodes() which can then
* be used in the DataBlockSpeciesMap to look up an itis code.
* @param dataUnit
* @return A species code for a specific data unit. May be null (e.g. for an unclassified click)
*/
public abstract String getSpeciesCode(T dataUnit);
public DataBlockSpeciesManager(PamDataBlock<T> dataBlock) {
super();
this.dataBlock = dataBlock;
datablockSpeciesMap = SpeciesMapManager.getInstance().getSpeciesMap(dataBlock);
// datablockSpeciesMap.clearMap();
clearMapNulls();
checkMapDefault();
}
/**
* Clear up some old maps which have got a null null default.
*/
private void clearMapNulls() {
SpeciesMapItem nullVal = datablockSpeciesMap.getItem(null);
if (nullVal == null) {
datablockSpeciesMap.removeItem(null);
}
}
public SpeciesMapItem getSpeciesItem(T dataUnit) {
String speciesString = getSpeciesString(dataUnit);
String speciesString = getSpeciesCode(dataUnit);
if (speciesString == null) {
return getDefaultDefaultSpecies();
}
@ -42,6 +99,30 @@ abstract public class DataBlockSpeciesManager<T extends PamDataUnit> {
return speciesMap.getItem(speciesString);
}
/**
* Get all PAMGuard species codes, which may come from the DataBlockSpeciesCodes
* object, or the defaultSpeciesCode, or the defaultDefaultSpecies name. Ideally,
* at least one of these should have something, or we'll stick in an "Unknown"
* @return
*/
public ArrayList<String> getAllSpeciesCodes() {
ArrayList<String> allCodes = new ArrayList<String>();
if (defaultSpeciesCode != null) {
allCodes.add(defaultSpeciesCode);
}
if (defaultDefaultSpecies != null) {
allCodes.add(defaultDefaultSpecies.getPamguardName());
}
DataBlockSpeciesCodes codeList = getSpeciesCodes();
if (codeList != null) {
allCodes.addAll(codeList.getSpeciesNames());
}
if (allCodes.size() == 0) {
allCodes.add("Unknown");
}
return allCodes;
}
public DataBlockSpeciesMap getDatablockSpeciesMap() {
if (datablockSpeciesMap == null) {
datablockSpeciesMap = new DataBlockSpeciesMap();
@ -51,9 +132,16 @@ abstract public class DataBlockSpeciesManager<T extends PamDataUnit> {
}
private void checkMapDefault() {
SpeciesMapItem defaultItem = datablockSpeciesMap.getItem(getDefaultName());
// SpeciesMapItem defaultItem = datablockSpeciesMap.getItem(getDefaultSpeciesCode());
// if (defaultItem == null) {
// datablockSpeciesMap.putItem(getDefaultSpeciesCode(), getDefaultDefaultSpecies());
// }
if (defaultDefaultSpecies == null) {
return;
}
SpeciesMapItem defaultItem = datablockSpeciesMap.getItem(defaultDefaultSpecies.getPamguardName());
if (defaultItem == null) {
datablockSpeciesMap.putItem(getDefaultName(), getDefaultDefaultSpecies());
datablockSpeciesMap.putItem(defaultDefaultSpecies.getPamguardName(), defaultDefaultSpecies);
}
}
@ -84,19 +172,20 @@ abstract public class DataBlockSpeciesManager<T extends PamDataUnit> {
*/
public void setDefaultDefaultSpecies(SpeciesMapItem defaultDefaultSpecies) {
this.defaultDefaultSpecies = defaultDefaultSpecies;
checkMapDefault();
}
/**
* @return the defaultName
*/
public String getDefaultName() {
return defaultName;
public String getDefaultSpeciesCode() {
return defaultSpeciesCode;
}
/**
* @param defaultName the defaultName to set
*/
public void setDefaultName(String defaultName) {
this.defaultName = defaultName;
public void setDefaultSpeciesCode(String defaultName) {
this.defaultSpeciesCode = defaultName;
}
}

View File

@ -4,7 +4,10 @@ import java.io.Serializable;
import java.util.HashMap;
/**
* Species map for a specified data block
* Species map for a specified data block <p>
* This is the bit that can be serialised, and is primarily (only) a hash table of
* SpeciesMapItems which relate String species codes for a detector to more
* details itis and scientific name information.
* @author dg50
*
*/
@ -33,5 +36,9 @@ public class DataBlockSpeciesMap implements Serializable {
public void removeItem(String key) {
speciesTable.remove(key);
}
public void clearMap() {
speciesTable.clear();
}
}

View File

@ -129,9 +129,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\",\"180488\"],\"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/tsn\",\"180488\"],\"optype\":\"binary\"}],\"enclose\":1}";
// String jQ = "{\"return\":[\"ranks/rank\"],\"select\":[{\"op\":\"=\",\"operands\":[\"ranks/rank/completename\",\"Physeter macrocephalus\"],\"optype\":\"binary\"}],\"enclose\":1}";
// String jQ = "{\"return\":[\"ranks/rank\"],\"select\":[{\"op\":\"dbxml:contains\",\"operands\":[\"ranks/rank/completename\",\"Sperm\"],\"optype\":\"function\"}],\"enclose\":1}";
String jQ = "{\"return\":[\"ranks/rank\"],\"select\":[{\"op\":\"dbxml:contains\",\"operands\":[\"ranks/rank/completename\",\"Sperm\"],\"optype\":\"function\"}],\"enclose\":1}";
System.out.println(jQ);

View File

@ -12,7 +12,7 @@ import PamView.dialog.PamDialogPanel;
import PamguardMVC.PamDataBlock;
import tethys.species.DataBlockSpeciesManager;
import tethys.species.DataBlockSpeciesMap;
import tethys.species.DataBlockSpeciesTypes;
import tethys.species.DataBlockSpeciesCodes;
import tethys.species.SpeciesMapItem;
public class DataBlockSpeciesPanel implements PamDialogPanel {
@ -46,8 +46,8 @@ public class DataBlockSpeciesPanel implements PamDialogPanel {
subPanels.clear();
DataBlockSpeciesManager speciesManager = dataBlock.getDatablockSpeciesManager();
DataBlockSpeciesTypes speciesTypes = speciesManager.getSpeciesTypes();
ArrayList<String> speciesNames = speciesTypes.getSpeciesNames();
// DataBlockSpeciesCodes speciesTypes = speciesManager.getSpeciesCodes();
ArrayList<String> speciesNames = speciesManager.getAllSpeciesCodes();
DataBlockSpeciesMap speciesMap = speciesManager.getDatablockSpeciesMap();
for (String aSpecies : speciesNames) {
SpeciesSubPanel subPanel = new SpeciesSubPanel(aSpecies);

View File

@ -139,7 +139,7 @@ public class SpeciesSubPanel {
tsn = Integer.valueOf(itisCode.getText());
}
catch (NumberFormatException e) {
PamDialog.showWarning(PamController.getMainFrame(), pamguardName.getText(), "You must specified an ITIS taxanomic code");
PamDialog.showWarning(PamController.getMainFrame(), pamguardName.getText(), "You must specify an ITIS taxanomic code");
return null;
}
latin = latinName.getText();
@ -149,7 +149,8 @@ public class SpeciesSubPanel {
PamDialog.showWarning(PamController.getMainFrame(), pamguardName.getText(), "You must specified a call type");
return null;
}
return new SpeciesMapItem(tsn, callType, pamguardName.getText(), latin, vernacular);
String pamName = pamguardName.getText().replace("\"", "");
return new SpeciesMapItem(tsn, callType, pamName, latin, vernacular);
}
}

View File

@ -3,7 +3,7 @@ package whistlesAndMoans.species;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
import tethys.species.DataBlockSpeciesManager;
import tethys.species.DataBlockSpeciesTypes;
import tethys.species.DataBlockSpeciesCodes;
import tethys.species.ITISTypes;
import tethys.species.SpeciesMapItem;
import whistlesAndMoans.ConnectedRegionDataUnit;
@ -15,19 +15,20 @@ public class WhistleSpeciesManager extends DataBlockSpeciesManager<ConnectedRegi
public WhistleSpeciesManager(PamDataBlock<ConnectedRegionDataUnit> dataBlock) {
super(dataBlock);
setDefaultDefaultSpecies(new SpeciesMapItem(180404, "Tonal", "Odontocete"));
setDefaultDefaultSpecies(new SpeciesMapItem(180404, "Tonal", "Tonal"));
}
@Override
public DataBlockSpeciesTypes getSpeciesTypes() {
String spList[] = {"Unknown"};
DataBlockSpeciesTypes whistleSpeciesTypes = new DataBlockSpeciesTypes("Tonal", spList);
return whistleSpeciesTypes;
public DataBlockSpeciesCodes getSpeciesCodes() {
// String spList[] = {"Unknown"};
//
// DataBlockSpeciesCodes whistleSpeciesTypes = new DataBlockSpeciesCodes("Tonal", spList);
// return whistleSpeciesTypes;
return null;
}
@Override
public String getSpeciesString(ConnectedRegionDataUnit dataUnit) {
public String getSpeciesCode(ConnectedRegionDataUnit dataUnit) {
return defaultName;
}