up[dated exporter

This commit is contained in:
Douglas Gillespie 2023-03-14 21:13:48 +00:00
parent 0fad7c6cfa
commit 3991a87102

View File

@ -1,12 +1,10 @@
package tethys.output; package tethys.output;
import java.util.ArrayList;
import java.util.List;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.attribute.FileAttribute; import java.util.ArrayList;
import java.io.StringWriter;
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException; import javax.xml.bind.JAXBException;
@ -15,9 +13,7 @@ import javax.xml.bind.Marshaller;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import Acquisition.AcquisitionControl; import Acquisition.AcquisitionControl;
import Acquisition.AcquisitionParameters;
import Acquisition.AcquisitionProcess; import Acquisition.AcquisitionProcess;
import Acquisition.DaqStatusDataUnit;
import Array.ArrayManager; import Array.ArrayManager;
import Array.Hydrophone; import Array.Hydrophone;
import Array.PamArray; import Array.PamArray;
@ -30,26 +26,17 @@ import PamUtils.PamCalendar;
import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit; import PamguardMVC.PamDataUnit;
import PamguardMVC.dataSelector.DataSelector; import PamguardMVC.dataSelector.DataSelector;
import dataMap.OfflineDataMap; import dbxml.uploader.Importer;
import dataMap.OfflineDataMapPoint;
import generalDatabase.DBControlUnit;
import generalDatabase.DBSchemaWriter;
import generalDatabase.SQLLogging;
import metadata.MetaDataContol; import metadata.MetaDataContol;
import metadata.deployment.DeploymentData; import metadata.deployment.DeploymentData;
import nilus.Deployment; import nilus.Deployment;
import nilus.DeploymentRecoveryDetails;
import tethys.TethysControl; import tethys.TethysControl;
import tethys.TethysLocationFuncs;
import tethys.TethysTimeFuncs;
import tethys.dbxml.DBXMLConnect; import tethys.dbxml.DBXMLConnect;
import tethys.deployment.DeploymentHandler;
import tethys.deployment.DeploymentRecoveryPair;
import tethys.pamdata.TethysDataProvider; import tethys.pamdata.TethysDataProvider;
import tethys.pamdata.TethysSchema; import tethys.pamdata.TethysSchema;
import dbxml.uploader.Importer;
import nilus.Deployment;
import nilus.MarshalXML;
/** /**
* Class sitting at the centre of all operations. It will talk to PAMGuard * Class sitting at the centre of all operations. It will talk to PAMGuard
* objects to get schemas and data and talk to the database connection to move * objects to get schemas and data and talk to the database connection to move
@ -58,7 +45,7 @@ import nilus.MarshalXML;
* dialogs alive, show progress for big export jobs, etc. For now though, it's a * dialogs alive, show progress for big export jobs, etc. For now though, it's a
* relatively simple set of function which we can use to a) open the database, * relatively simple set of function which we can use to a) open the database,
* b) check everything such as schemas, etc. c) export data and d) clean up. * b) check everything such as schemas, etc. c) export data and d) clean up.
* *
* @author dg50 * @author dg50
* *
*/ */
@ -79,7 +66,7 @@ public class TethysExporter {
* Does the work. In reality this will need an awful lot of changing, for * Does the work. In reality this will need an awful lot of changing, for
* instance to provide feedback to an observer class to show progress on the * instance to provide feedback to an observer class to show progress on the
* display. * display.
* *
* @return OK if success. * @return OK if success.
*/ */
public boolean doExport() { public boolean doExport() {
@ -98,7 +85,7 @@ public class TethysExporter {
Path tempFile = null; Path tempFile = null;
try { try {
JAXBContext jaxB = JAXBContext.newInstance(Deployment.class); JAXBContext jaxB = JAXBContext.newInstance(Deployment.class);
Marshaller marshall = jaxB.createMarshaller(); Marshaller marshall = jaxB.createMarshaller();
marshall.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshall.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
@ -106,12 +93,12 @@ public class TethysExporter {
marshall.marshal(deployment1, sw); marshall.marshal(deployment1, sw);
tempFile = Files.createTempFile("pamGuardToTethys", ".xml"); tempFile = Files.createTempFile("pamGuardToTethys", ".xml");
Files.write(tempFile, sw.toString().getBytes()); Files.write(tempFile, sw.toString().getBytes());
String fileText = Importer.ImportFiles("http://localhost:9779", "Deployment", String fileText = Importer.ImportFiles("http://localhost:9779", "Deployment",
new String[] { tempFile.toString() }, "", "", false); new String[] { tempFile.toString() }, "", "", false);
tempFile.toFile().deleteOnExit(); tempFile.toFile().deleteOnExit();
} catch(IllegalArgumentException e) { } catch(IllegalArgumentException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
@ -122,7 +109,7 @@ public class TethysExporter {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
SnapshotGeometry arrayGeometry = findArrayGeometrey(); SnapshotGeometry arrayGeometry = findArrayGeometrey();
/** /**
@ -152,12 +139,12 @@ public class TethysExporter {
//1. grab DeploymentRecoveryPair that has deployment details and recovery details //1. grab DeploymentRecoveryPair that has deployment details and recovery details
//a. this is based on start and end times //a. this is based on start and end times
//Douglas calculates out dutycycles to only grab the //Douglas calculates out dutycycles to only grab the
//2. loop through the pairs to populate the extra information //2. loop through the pairs to populate the extra information
//one pair is one deployment //one pair is one deployment
//see below for matching //see below for matching
//id => unique //id => unique
//project => project in pamguard //project => project in pamguard
//deploymentId == id //deploymentId == id
@ -171,14 +158,14 @@ public class TethysExporter {
//Instrument/Id => UI, array manager details //Instrument/Id => UI, array manager details
//Instrument/Geometry => in pamguard array manager //Instrument/Geometry => in pamguard array manager
//SamplingDetails/Channel //SamplingDetails/Channel
//ChannelNumber => in pamguard, hyrdrophone array //ChannelNumber => in pamguard, hyrdrophone array
//SensorNumber => in pamguard, //SensorNumber => in pamguard,
//Start => same as timestamp deployment detail //Start => same as timestamp deployment detail
//End => same as timestamp recovery detail //End => same as timestamp recovery detail
//Sampling/Regimen (change sample rate, pamgauard doesnt handle, only on, get channel info in that loop) //Sampling/Regimen (change sample rate, pamgauard doesnt handle, only on, get channel info in that loop)
//TimeStamp => start time //TimeStamp => start time
//SampleRate_kHz => //SampleRate_kHz =>
//SampleBits => //SampleBits =>
//Gain (another func call to get gain info) //Gain (another func call to get gain info)
//DutyCycles => needs to be calculated, not fields in pamguard, have fun Douglas //DutyCycles => needs to be calculated, not fields in pamguard, have fun Douglas
//QualityAssurance => not in pamguard, UI, maybe deployment notes, optional //QualityAssurance => not in pamguard, UI, maybe deployment notes, optional
@ -186,7 +173,7 @@ public class TethysExporter {
//URI => folder where audio is saved //URI => folder where audio is saved
//Data/Tracks //Data/Tracks
//Track => GPS datatable (granularity filter) //Track => GPS datatable (granularity filter)
//TrackId => not unique between deployments, //TrackId => not unique between deployments,
//TrackEffort //TrackEffort
//OnPath => scattered throughout pamguard //OnPath => scattered throughout pamguard
//URI => option, check with Shannon on how they are doing deployments //URI => option, check with Shannon on how they are doing deployments
@ -194,42 +181,43 @@ public class TethysExporter {
//pamguard hydrophone data //pamguard hydrophone data
//number => hydrophoneId //number => hydrophoneId
//sensorId => sensor serial number //sensorId => sensor serial number
//Geometry => array geometry field goes to //Geometry => array geometry field goes to
//Sensors/Depth //Sensors/Depth
//optional //optional
//Sensors/Sensor //Sensors/Sensor
//Number => hydrophoneId in pamguard //Number => hydrophoneId in pamguard
//SensorId => addition to UI //SensorId => addition to UI
//Geometry => array geometry fields //Geometry => array geometry fields
//Type => Hydrophone Type //Type => Hydrophone Type
//get list of deployment recovery details (start, stop times and lat/long) //get list of deployment recovery details (start, stop times and lat/long)
//deployment details and recovery details are same structure //deployment details and recovery details are same structure
//per pair, go through a loop to fill in each deployment //per pair, go through a loop to fill in each deployment
ArrayList<DeploymentRecoveryPair> deployRecover = getSamplingDetails(); DeploymentHandler deploymentHandler = new DeploymentHandler();
ArrayList<DeploymentRecoveryPair> deployRecover = deploymentHandler.getDeployments();
if (deployRecover == null) { if (deployRecover == null) {
return false; return false;
} }
/* /*
* This will become the main loop over deployment documents * This will become the main loop over deployment documents
*/ */
int i = 0; int i = 0;
for (DeploymentRecoveryPair drd : deployRecover) { for (DeploymentRecoveryPair drd : deployRecover) {
Deployment deployment = createDeploymentDocument(i++, drd); Deployment deployment = deploymentHandler.createDeploymentDocument(i++, drd);
// System.out.println(deployment.toString());
} }
/*
* Call some general export function
*/
exportGeneralData(tethysExportParams);
/* /*
* go through the export params and call something for every data block that's * go through the export params and call something for every data block that's
* enabled. * enabled.
@ -237,7 +225,7 @@ public class TethysExporter {
ArrayList<PamDataBlock> allDataBlocks = PamController.getInstance().getDataBlocks(); ArrayList<PamDataBlock> allDataBlocks = PamController.getInstance().getDataBlocks();
for (PamDataBlock aDataBlock : allDataBlocks) { for (PamDataBlock aDataBlock : allDataBlocks) {
StreamExportParams streamExportParams = tethysExportParams.getStreamParams(aDataBlock); StreamExportParams streamExportParams = tethysExportParams.getStreamParams(aDataBlock);
if (streamExportParams == null || streamExportParams.selected == false) { if (streamExportParams == null || !streamExportParams.selected) {
continue; // not interested in this one. continue; // not interested in this one.
} }
exportDataStream(aDataBlock, tethysExportParams, streamExportParams); exportDataStream(aDataBlock, tethysExportParams, streamExportParams);
@ -250,23 +238,11 @@ public class TethysExporter {
return true; return true;
} }
private Deployment createDeploymentDocument(int i, DeploymentRecoveryPair drd) {
Deployment deployment = new Deployment();
deployment.setDeploymentDetails(drd.deploymentDetails);
deployment.setRecoveryDetails(drd.recoveryDetails);
TethysLocationFuncs.getTrackAndPositionData(deployment);
return deployment;
}
/** /**
* find Deployment data. This is stored in a separate PAMGuard module, which may * find Deployment data. This is stored in a separate PAMGuard module, which may
* not be present. * not be present.
* *
* @return * @return
*/ */
public DeploymentData findDeploymentData() { public DeploymentData findDeploymentData() {
@ -332,119 +308,11 @@ public class TethysExporter {
return currentGeometry; return currentGeometry;
} }
// in each channel
private ArrayList<DeploymentRecoveryPair> getSamplingDetails() {
// first find an acquisition module.
PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
if (aModule instanceof AcquisitionControl == false) {
// will return if it's null. Impossible for it to be the wrong type.
// but it's good practice to check anyway before casting.
return null;
}
// cast it to the right type.
AcquisitionControl daqControl = (AcquisitionControl) aModule;
AcquisitionParameters daqParams = daqControl.getAcquisitionParameters();
/**
* The daqParams class has most of what we need about the set up in terms of
* sample rate, number of channels, instrument type, ADC input range (part of
* calibration), etc. It also has a hydrophone list, which maps the input
* channel numbers to the hydrophon numbers. Realistically, this list is always
* 0,1,2,etc or it goes horribly wrong !
*/
// so write functions here to get information from the daqParams.
System.out.printf("Sample regime: %s input with rate %3.1fHz, %d channels, gain %3.1fdB, ADCp-p %3.1fV\n",
daqParams.getDaqSystemType(), daqParams.getSampleRate(), daqParams.getNChannels(),
daqParams.preamplifier.getGain(), daqParams.voltsPeak2Peak);
/**
* then there is the actual sampling. This is a bit harder to find. I thought it
* would be in the data map but the datamap is a simple count of what's in the
* databasase which is not quite what we want. we're going to have to query the
* database to get more detailed informatoin I think. I'll do that here for now,
* but we may want to move this when we better organise the code. It also seems
* that there are 'bad' dates in the database when it starts new files, which
* are the date data were analysed at. So we really need to check the start and
* stop records only.
*/
PamDataBlock<DaqStatusDataUnit> daqInfoDataBlock = daqControl.getAcquisitionProcess().getDaqStatusDataBlock();
// just load everything. Probably OK for the acqusition, but will bring down
daqInfoDataBlock.loadViewerData(0, Long.MAX_VALUE, null);
ArrayList<DaqStatusDataUnit> allStatusData = daqInfoDataBlock.getDataCopy();
long dataStart = Long.MAX_VALUE;
long dataEnd = Long.MIN_VALUE;
if (allStatusData != null && allStatusData.size() > 0) {
// find the number of times it started and stopped ....
int nStart = 0, nStop = 0, nFile = 0;
for (DaqStatusDataUnit daqStatus : allStatusData) {
switch (daqStatus.getStatus()) {
case "Start":
nStart++;
dataStart = Math.min(dataStart, daqStatus.getTimeMilliseconds());
break;
case "Stop":
nStop++;
dataEnd = Math.max(dataEnd, daqStatus.getEndTimeInMilliseconds());
break;
case "NextFile":
nFile++;
break;
}
}
System.out.printf(
"Input map of sound data indicates data from %s to %s with %d starts and %d stops over %d files\n",
PamCalendar.formatDateTime(dataStart), PamCalendar.formatDateTime(dataEnd), nStart, nStop,
nFile + 1);
}
// // and we find the datamap within that ...
// OfflineDataMap daqMap = daqInfoDataBlock.getOfflineDataMap(DBControlUnit.findDatabaseControl());
// if (daqMap != null) {
// // iterate through it.
// long dataStart = daqMap.getFirstDataTime();
// long dataEnd = daqMap.getLastDataTime();
// List<OfflineDataMapPoint> mapPoints = daqMap.getMapPoints();
// System.out.printf("Input map of sound data indicates data from %s to %s with %d individual files\n",
// PamCalendar.formatDateTime(dataStart), PamCalendar.formatDateTime(dataEnd), mapPoints.size());
// /*
// * clearly in the first database I've been looking at of Tinas data, this is NOT getting sensible start and
// * end times. Print them out to see what's going on.
// */
//// for ()
// }
DeploymentRecoveryPair pair = new DeploymentRecoveryPair();
DeploymentRecoveryDetails deployment = new DeploymentRecoveryDetails();
DeploymentRecoveryDetails recovery = new DeploymentRecoveryDetails();
pair.deploymentDetails = deployment;
pair.recoveryDetails = recovery;
deployment.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataStart));
deployment.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataStart));
recovery.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataEnd));
recovery.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataEnd));
ArrayList<DeploymentRecoveryPair> drPairs = new ArrayList<>();
drPairs.add(pair);
return drPairs;
}
/**
* No idea if we need this or not. May want to return something different to
* void, e.g. a reference to the main object for a tethys export. I've no idea !
*
* @param tethysExportParams2
*/
private void exportGeneralData(TethysExportParams tethysExportParams) {
// TODO Auto-generated method stub
}
/** /**
* Here is where we export data for a specific data stream to Tethys. * Here is where we export data for a specific data stream to Tethys.
* *
* @param aDataBlock * @param aDataBlock
* @param tethysExportParams * @param tethysExportParams
* @param streamExportParams * @param streamExportParams