diff --git a/.classpath b/.classpath index 924124d8..576b210a 100644 --- a/.classpath +++ b/.classpath @@ -6,8 +6,9 @@ - + + diff --git a/.gitignore b/.gitignore index e14af36b..a379d5bb 100644 --- a/.gitignore +++ b/.gitignore @@ -108,3 +108,4 @@ settings.xml .classpath .classpath .classpath +.classpath diff --git a/pom.xml b/pom.xml index 286c839c..bc7315b0 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.pamguard Pamguard - 2.02.11b + 2.02.11c Pamguard Pamguard using Maven to control dependencies www.pamguard.org @@ -19,7 +19,7 @@ 21 11 11 - + 2.4.0-b180830.0438 2.4.0-b180830.0359 2.4.0-b180830.0438 @@ -74,59 +74,63 @@ - + org.openjfx javafx-maven-plugin 0.0.8 - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.1 - - - - - - - - package - - shade - - - - - - pamguard.Pamguard - . - Resources/pgBlankSplash.png - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.1 + + + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + package + + shade + + + + + + pamguard.Pamguard + . + Resources/pgBlankSplash.png + + + + + + + + - + + com.github.marschall jdeps-maven-plugin diff --git a/src/Acquisition/pamAudio/WavFileInputStream.java b/src/Acquisition/pamAudio/WavFileInputStream.java index 3033fa45..fbb2126a 100644 --- a/src/Acquisition/pamAudio/WavFileInputStream.java +++ b/src/Acquisition/pamAudio/WavFileInputStream.java @@ -59,7 +59,7 @@ public class WavFileInputStream extends AudioInputStream { //wav files (this is in fact tha standard emthod for calculated blockalign) int blockAlign = wavHeader.getNChannels() * (wavHeader.getBitsPerSample() / 8); - System.out.println("NFRAMES: " + nFrames + " "+ wavHeader.getDataSize() + " " + wavHeader.getBlockAlign() + " "+blockAlign ); +// System.out.println("NFRAMES: " + nFrames + " "+ wavHeader.getDataSize() + " " + wavHeader.getBlockAlign() + " "+blockAlign ); Encoding encoding = getEncoding(wavHeader.getFmtTag()); if (encoding == null) { diff --git a/src/rawDeepLearningClassifier/dlClassification/DLClassiferModel.java b/src/rawDeepLearningClassifier/dlClassification/DLClassiferModel.java index 38fd9e9c..ce76f2e7 100644 --- a/src/rawDeepLearningClassifier/dlClassification/DLClassiferModel.java +++ b/src/rawDeepLearningClassifier/dlClassification/DLClassiferModel.java @@ -9,10 +9,10 @@ import org.jamdev.jdl4pam.transforms.DLTransfromParams; import org.jamdev.jdl4pam.transforms.SimpleTransform; import org.jamdev.jdl4pam.transforms.SimpleTransformParams; +import PamguardMVC.PamDataUnit; import rawDeepLearningClassifier.DLControl; import rawDeepLearningClassifier.DLStatus; import rawDeepLearningClassifier.layoutFX.DLCLassiferModelUI; -import rawDeepLearningClassifier.segmenter.SegmenterProcess.GroupedRawData; import warnings.PamWarning; /** @@ -32,7 +32,7 @@ public interface DLClassiferModel { * * @return the deep learning model. */ - public ArrayList runModel(ArrayList rawDataUnit); + public ArrayList runModel(ArrayList rawDataUnit); /** * Prepare the model. This is called on PAMGuard start up. diff --git a/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java b/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java index ac331438..fe515cb1 100644 --- a/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java +++ b/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java @@ -18,8 +18,8 @@ import rawDeepLearningClassifier.layoutFX.DLDetectionGraphics; import rawDeepLearningClassifier.layoutFX.DLGraphics; import rawDeepLearningClassifier.logging.DLAnnotation; import rawDeepLearningClassifier.logging.DLAnnotationType; +import rawDeepLearningClassifier.segmenter.GroupedRawData; import rawDeepLearningClassifier.segmenter.SegmenterDataBlock; -import rawDeepLearningClassifier.segmenter.SegmenterProcess.GroupedRawData; /** * The deep learning classification process. This takes a segment of raw data from the segmenter. diff --git a/src/rawDeepLearningClassifier/dlClassification/DLTaskThread.java b/src/rawDeepLearningClassifier/dlClassification/DLTaskThread.java index 87ab2863..51d6c6e7 100644 --- a/src/rawDeepLearningClassifier/dlClassification/DLTaskThread.java +++ b/src/rawDeepLearningClassifier/dlClassification/DLTaskThread.java @@ -5,14 +5,14 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; -import rawDeepLearningClassifier.dlClassification.animalSpot.SoundSpotResult; +import PamguardMVC.PamDataUnit; import rawDeepLearningClassifier.dlClassification.genericModel.DLModelWorker; import rawDeepLearningClassifier.dlClassification.genericModel.GenericPrediction; -import rawDeepLearningClassifier.segmenter.SegmenterProcess.GroupedRawData; +import rawDeepLearningClassifier.segmenter.GroupedRawData; /** * Creates a que for grouped data units for classiifcation. - * @author au671271 + * @author Jamie Macaulay * */ public abstract class DLTaskThread extends Thread { @@ -28,7 +28,7 @@ public abstract class DLTaskThread extends Thread { /** * Holds a list of segmented raw data units which need to be classified. */ - private List> queue = Collections.synchronizedList(new ArrayList>()); + private List> queue = Collections.synchronizedList(new ArrayList>()); public DLTaskThread(DLModelWorker soundSpotWorker) { @@ -50,7 +50,7 @@ public abstract class DLTaskThread extends Thread { try { if (queue.size()>0) { System.out.println("DL TASK THREAD: " + "The queue size is " + queue.size()); - ArrayList groupedRawData = queue.remove(0); + ArrayList groupedRawData = queue.remove(0); ArrayList modelResult = dlModelWorker.runModel(groupedRawData, groupedRawData.get(0).getParentDataBlock().getSampleRate(), 0); //TODO channel? @@ -79,17 +79,17 @@ public abstract class DLTaskThread extends Thread { * @param soundSpotResult - the new result. * @param groupedRawData - the grouped data unit. */ - public abstract void newDLResult(GenericPrediction soundSpotResult, GroupedRawData groupedRawData); + public abstract void newDLResult(GenericPrediction soundSpotResult, PamDataUnit groupedRawData); /** * Get the grouped data queue * @return */ - public List> getQueue() { + public List> getQueue() { return queue; } - public void setQueue(List> queue) { + public void setQueue(List> queue) { this.queue = queue; } diff --git a/src/rawDeepLearningClassifier/dlClassification/StandardClassifierModel.java b/src/rawDeepLearningClassifier/dlClassification/StandardClassifierModel.java index 275df607..b8e89af8 100644 --- a/src/rawDeepLearningClassifier/dlClassification/StandardClassifierModel.java +++ b/src/rawDeepLearningClassifier/dlClassification/StandardClassifierModel.java @@ -12,6 +12,7 @@ import PamController.PamSettings; import PamDetection.RawDataUnit; import PamUtils.PamArrayUtils; import PamUtils.PamCalendar; +import PamguardMVC.PamDataUnit; import javafx.stage.FileChooser.ExtensionFilter; import rawDeepLearningClassifier.DLControl; import rawDeepLearningClassifier.DLStatus; @@ -20,13 +21,13 @@ import rawDeepLearningClassifier.dlClassification.genericModel.DLModelWorker; import rawDeepLearningClassifier.dlClassification.genericModel.GenericDLClassifier; import rawDeepLearningClassifier.dlClassification.genericModel.GenericPrediction; import rawDeepLearningClassifier.layoutFX.DLSettingsPane; -import rawDeepLearningClassifier.segmenter.SegmenterProcess.GroupedRawData; +import rawDeepLearningClassifier.segmenter.GroupedRawData; import warnings.PamWarning; import warnings.WarningSystem; /** * A useful abstract class for standard models which are a file or URL that is loaded, have a UI and - * utilise PAMSettings to save settings state. + * utilise PAMSettings to save settings state. These models only accept raw sound data segments. */ public abstract class StandardClassifierModel implements DLClassiferModel, PamSettings { @@ -56,12 +57,15 @@ public abstract class StandardClassifierModel implements DLClassiferModel, PamSe @Override - public ArrayList runModel(ArrayList groupedRawData) { + @SuppressWarnings("rawtypes") + public ArrayList runModel( ArrayList groupedRawData) { if (getDLWorker().isModelNull()) return null; // System.out.println("SoundSpotClassifier: PamCalendar.isSoundFile(): " // + PamCalendar.isSoundFile() + " " + (PamCalendar.isSoundFile() && !forceQueue)); + + /** * If a sound file is being analysed then Ketos can go as slow as it wants. if used in real time * then there is a buffer with a maximum queue size. @@ -165,7 +169,7 @@ public abstract class StandardClassifierModel implements DLClassiferModel, PamSe return DLStatus.NO_MODEL_LOADED; } - // if continous data is selected and all classes are false then this is a + // if continuous data is selected and all classes are false then this is a // potential mistake... if (dlControl.getSettingsPane().getSelectedParentDataBlock().getUnitClass() == RawDataUnit.class && (getDLParams().binaryClassification==null || PamArrayUtils.isAllFalse(getDLParams().binaryClassification))){ @@ -200,7 +204,7 @@ public abstract class StandardClassifierModel implements DLClassiferModel, PamSe } @Override - public void newDLResult(GenericPrediction soundSpotResult, GroupedRawData groupedRawData) { + public void newDLResult(GenericPrediction soundSpotResult, PamDataUnit groupedRawData) { soundSpotResult.setClassNameID(GenericDLClassifier.getClassNameIDs(getDLParams())); soundSpotResult.setBinaryClassification(GenericDLClassifier.isBinaryResult(soundSpotResult, getDLParams())); newResult(soundSpotResult, groupedRawData); @@ -220,8 +224,10 @@ public abstract class StandardClassifierModel implements DLClassiferModel, PamSe * @param modelResult - the model result; * @param groupedRawData - the grouped raw data. */ - protected void newResult(GenericPrediction modelResult, GroupedRawData groupedRawData) { - this.dlControl.getDLClassifyProcess().newModelResult(modelResult, groupedRawData); + protected void newResult(GenericPrediction modelResult, PamDataUnit groupedRawData) { + if (groupedRawData instanceof GroupedRawData) { + this.dlControl.getDLClassifyProcess().newModelResult(modelResult, (GroupedRawData) groupedRawData); + } } // // @Override diff --git a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDClassifier.java b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDClassifier.java index 55be07a0..50bb3baf 100644 --- a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDClassifier.java +++ b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDClassifier.java @@ -1,8 +1,24 @@ package rawDeepLearningClassifier.dlClassification.delphinID; +import java.io.Serializable; +import java.net.URI; +import java.util.ArrayList; + +import PamController.PamControlledUnitSettings; +import PamController.PamSettings; +import PamguardMVC.PamDataUnit; import rawDeepLearningClassifier.DLControl; +import rawDeepLearningClassifier.DLStatus; +import rawDeepLearningClassifier.dlClassification.DLClassName; +import rawDeepLearningClassifier.dlClassification.DLClassiferModel; +import rawDeepLearningClassifier.dlClassification.PredictionResult; +import rawDeepLearningClassifier.dlClassification.StandardClassifierModel; +import rawDeepLearningClassifier.dlClassification.animalSpot.StandardModelParams; import rawDeepLearningClassifier.dlClassification.archiveModel.ArchiveModelClassifier; import rawDeepLearningClassifier.dlClassification.archiveModel.ArchiveModelWorker; +import rawDeepLearningClassifier.dlClassification.genericModel.DLModelWorker; +import rawDeepLearningClassifier.dlClassification.genericModel.GenericPrediction; +import rawDeepLearningClassifier.layoutFX.DLCLassiferModelUI; /** * A classifier based on the delphinID method which uses whistle contours to predict @@ -11,31 +27,77 @@ import rawDeepLearningClassifier.dlClassification.archiveModel.ArchiveModelWorke * @author Jamie Macaulay * */ -public class DelphinIDClassifier extends ArchiveModelClassifier{ - - private static final String MODEL_NAME = "delphinID"; - - /** - * Reference to the worker - */ - private DelphinIDWorker delphinIDWorker; +public class DelphinIDClassifier extends StandardClassifierModel { public DelphinIDClassifier(DLControl dlControl) { super(dlControl); - } - - @Override - public String getName() { - return MODEL_NAME; - } - - @Override - public ArchiveModelWorker getModelWorker() { - if (delphinIDWorker==null) { - delphinIDWorker= new DelphinIDWorker(); - } - return delphinIDWorker; + // TODO Auto-generated constructor stub } + @Override + public boolean isModelType(URI model) { + // TODO Auto-generated method stub + return false; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public DLCLassiferModelUI getModelUI() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Serializable getDLModelSettings() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getUnitType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Serializable getSettingsReference() { + // TODO Auto-generated method stub + return null; + } + + @Override + public long getSettingsVersion() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) { + // TODO Auto-generated method stub + return false; + } + + @Override + public String getUnitName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public DLModelWorker getDLWorker() { + // TODO Auto-generated method stub + return null; + } + + @Override + public StandardModelParams getDLParams() { + // TODO Auto-generated method stub + return null; + } -} +} \ No newline at end of file diff --git a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDPrediction.java b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDPrediction.java new file mode 100644 index 00000000..b5140ee4 --- /dev/null +++ b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDPrediction.java @@ -0,0 +1,12 @@ +package rawDeepLearningClassifier.dlClassification.delphinID; + +import rawDeepLearningClassifier.dlClassification.genericModel.GenericPrediction; + +public class DelphinIDPrediction extends GenericPrediction{ + + public DelphinIDPrediction(float[] prob) { + super(prob); + // TODO Auto-generated constructor stub + } + +} diff --git a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java index 565035dd..1c7cf64c 100644 --- a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java +++ b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java @@ -1,8 +1,39 @@ package rawDeepLearningClassifier.dlClassification.delphinID; -import rawDeepLearningClassifier.dlClassification.archiveModel.ArchiveModelWorker; +import rawDeepLearningClassifier.DLControl; +import rawDeepLearningClassifier.dlClassification.animalSpot.StandardModelParams; +import rawDeepLearningClassifier.dlClassification.genericModel.DLModelWorker; -public class DelphinIDWorker extends ArchiveModelWorker{ +public class DelphinIDWorker extends DLModelWorker{ + + @Override + public float[] runModel(float[][][] transformedDataStack) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isModelNull() { + // TODO Auto-generated method stub + return false; + } + + @Override + public DelphinIDPrediction makeModelResult(float[] prob, double time) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void prepModel(StandardModelParams delphinIDParams, DLControl dlControl) { + // TODO Auto-generated method stub + } + + @Override + public void closeModel() { + // TODO Auto-generated method stub + + } diff --git a/src/rawDeepLearningClassifier/dlClassification/dummyClassifier/DummyClassifier.java b/src/rawDeepLearningClassifier/dlClassification/dummyClassifier/DummyClassifier.java index 25e98ac8..70fd732a 100644 --- a/src/rawDeepLearningClassifier/dlClassification/dummyClassifier/DummyClassifier.java +++ b/src/rawDeepLearningClassifier/dlClassification/dummyClassifier/DummyClassifier.java @@ -4,14 +4,14 @@ import java.io.Serializable; import java.net.URI; import java.util.ArrayList; +import PamguardMVC.PamDataUnit; import rawDeepLearningClassifier.DLControl; import rawDeepLearningClassifier.DLStatus; import rawDeepLearningClassifier.dlClassification.DLClassName; import rawDeepLearningClassifier.dlClassification.DLClassiferModel; import rawDeepLearningClassifier.dlClassification.PredictionResult; import rawDeepLearningClassifier.layoutFX.DLCLassiferModelUI; -import rawDeepLearningClassifier.segmenter.SegmenterProcess.GroupedRawData; -import warnings.PamWarning; +import rawDeepLearningClassifier.segmenter.GroupedRawData; /** * Classifier which returns a random results. Used for debugging and testing. @@ -62,8 +62,7 @@ public class DummyClassifier implements DLClassiferModel{ return null; } - @Override - public ArrayList runModel(ArrayList rawDataUnit) { + public ArrayList runModel(ArrayList rawDataUnit) { ArrayList modelResults = new ArrayList(); for (int i=0; i - * * * @author Jamie Macaulay * @@ -41,71 +41,83 @@ public abstract class DLModelWorker { * True to enable normalisation of results using softmax; */ private boolean enableSoftMax = true; + + + /** + * Convert a list of data units to a stack if images. + * @param dataUnits - the data units. + * @param sampleRate - the sample rate + * @param iChan - the channels + * @return a stack of images for input into a deep learning model. + */ + public float[][][] dataUnits2ModelInput(ArrayList dataUnits, float sampleRate, int iChan){ + + @SuppressWarnings("unchecked") + ArrayList rawDataUnits = ( ArrayList) dataUnits; + + //the number of chunks. + int numChunks = rawDataUnits.size(); + + //data input into the model - a stack of spectrogram images. + float[][][] transformedDataStack = new float[numChunks][][]; + + //generate the spectrogram stack. + AudioData soundData; + double[][] transformedData2; //spec data + double[] transformedData1; //waveform data + for (int j=0; j runModel(ArrayList rawDataUnits, float sampleRate, int iChan) { + public synchronized ArrayList runModel(ArrayList dataUnits, float sampleRate, int iChan) { try { - //the number of chunks. - int numChunks = rawDataUnits.size(); - //PamCalendar.isSoundFile(); //create an audio data object from the raw data chunk long timeStart = System.nanoTime(); - - //data input into the model - a stack of spectrogram images. - float[][][] transformedDataStack = new float[numChunks][][]; - - //generate the spectrogram stack. - AudioData soundData; - double[][] transformedData2; //spec data - double[] transformedData1; //waveform data - for (int j=0; j runModel(ArrayList rawDataUnits) { + public ArrayList runModel(ArrayList rawDataUnits) { - for (GroupedRawData groupedRawData: rawDataUnits){ - if (queue.size()>MAX_QUEUE_SIZE) { - //we are not doing well - clear the buffer - queue.clear(); - } - queue.add(groupedRawData); - - - } - this.orcaSpotUI.notifyUpdate(-1); +// for (PamDataUnit groupedRawData: rawDataUnits){ +// if (queue.size()>MAX_QUEUE_SIZE) { +// //we are not doing well - clear the buffer +// queue.clear(); +// } +// queue.add(groupedRawData); +// +// +// } +// this.orcaSpotUI.notifyUpdate(-1); return null; } @@ -363,4 +364,6 @@ public class OrcaSpotClassifier implements DLClassiferModel, PamSettings { return null; } + + } diff --git a/src/rawDeepLearningClassifier/segmenter/GroupedRawData.java b/src/rawDeepLearningClassifier/segmenter/GroupedRawData.java new file mode 100644 index 00000000..e969e552 --- /dev/null +++ b/src/rawDeepLearningClassifier/segmenter/GroupedRawData.java @@ -0,0 +1,145 @@ +package rawDeepLearningClassifier.segmenter; + +import java.util.Arrays; + +import PamDetection.PamDetection; +import PamUtils.PamUtils; +import PamguardMVC.PamDataUnit; + +/** + * + * Temporary holder for raw data with a pre defined size. This holds one channel group of raw + * sound data. + * + * @author Jamie Macaulay + * + */ +public class GroupedRawData extends PamDataUnit implements PamDetection, Cloneable { + + + /* + * Raw data holder + */ + protected double[][] rawData; + + + /** + * Current position in the rawData; + */ + protected int[] rawDataPointer; + + /** + * The data unit associated with this raw data chunk. + */ + private PamDataUnit rawDataUnit; + + + /** + * Create a grouped raw data unit. This contains a segment of sound data. + * @param timeMilliseconds - the time in milliseconds. + * @param channelBitmap - the channel bitmap of the raw data. + * @param startSample - the start sample of the raw data. + * @param duration - the duration of the raw data in samples. + * @param samplesize - the total sample size of the raw data unit chunk in samples. + */ + public GroupedRawData(long timeMilliseconds, int channelBitmap, long startSample, long duration, int samplesize) { + super(timeMilliseconds, channelBitmap, startSample, duration); + rawData = new double[PamUtils.getNumChannels(channelBitmap)][]; + rawDataPointer = new int[PamUtils.getNumChannels(channelBitmap)]; + // rawDataStartMillis = new long[PamUtils.getNumChannels(channelBitmap)]; + + for (int i =0; i=rawData[groupChan].length) { + arrayCopyLen=copyLen-(lastPos-rawData[groupChan].length)-1; + dataOverflow = copyLen - arrayCopyLen; + } + else { + arrayCopyLen= copyLen; + } + + arrayCopyLen = Math.max(arrayCopyLen, 0); + + //update the current grouped raw data unit with new raw data. + System.arraycopy(src, srcPos, rawData[groupChan], rawDataPointer[groupChan], arrayCopyLen); + + rawDataPointer[groupChan]=rawDataPointer[groupChan] + arrayCopyLen; + + return dataOverflow; + } + + /** + * Get the raw data grouped by channel. + * @return the raw acoustic data. + */ + public double[][] getRawData() { + return rawData; + } + + /** + * Get the current pointer for rawData. + * @return the data pointer per channel. + */ + public int[] getRawDataPointer() { + return rawDataPointer; + } + + + @Override + protected GroupedRawData clone() { + try { + GroupedRawData groupedRawData = (GroupedRawData) super.clone(); + + //hard clone the acoustic data + groupedRawData.rawData = new double[this.rawData.length][]; + for (int i=0; i=rawData[groupChan].length) { - arrayCopyLen=copyLen-(lastPos-rawData[groupChan].length)-1; - dataOverflow = copyLen - arrayCopyLen; - } - else { - arrayCopyLen= copyLen; - } - - arrayCopyLen = Math.max(arrayCopyLen, 0); - - //update the current grouped raw data unit with new raw data. - System.arraycopy(src, srcPos, rawData[groupChan], rawDataPointer[groupChan], arrayCopyLen); - - rawDataPointer[groupChan]=rawDataPointer[groupChan] + arrayCopyLen; - - return dataOverflow; - } - - /** - * Get the raw data grouped by channel. - * @return the raw acoustic data. - */ - public double[][] getRawData() { - return rawData; - } - - /** - * Get the current pointer for rawData. - * @return the data pointer per channel. - */ - public int[] getRawDataPointer() { - return rawDataPointer; - } - - - @Override - protected GroupedRawData clone() { - try { - GroupedRawData groupedRawData = (GroupedRawData) super.clone(); - - //hard clone the acoustic data - groupedRawData.rawData = new double[this.rawData.length][]; - for (int i=0; i