/*-
* Copyright 2016 Diamond Light Source Ltd.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
// Package declaration
package uk.ac.diamond.scisoft.analysis.processing.operations.export;
// Imports from Java
import java.io.File;
import java.util.Date;
import java.util.Calendar;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.DateFormat;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
// Imports from org.eclipse.january
import org.eclipse.january.IMonitor;
import org.eclipse.january.dataset.IDataset;
import org.eclipse.january.dataset.Slice;
// Imports from org.eclipse.dawnsci
import org.eclipse.dawnsci.analysis.api.processing.OperationData;
import org.eclipse.dawnsci.analysis.api.processing.OperationRank;
import org.eclipse.dawnsci.analysis.api.processing.IExportOperation;
import org.eclipse.dawnsci.analysis.api.processing.OperationException;
import org.eclipse.dawnsci.analysis.dataset.operations.AbstractOperation;
import org.eclipse.dawnsci.analysis.dataset.slicer.SliceFromSeriesMetadata;
// Imports from uk.ac.diamond.scisoft
import uk.ac.diamond.scisoft.analysis.processing.operations.utils.ProcessingUtils;
//The operation file for exporting a BSL folder
//@author Tim Snow
//Let's save this file.
public class Export2DBSLOperation extends AbstractOperation<Export2DBSLModel, OperationData> implements IExportOperation {
@Override
public String getId() {
return "uk.ac.diamond.scisoft.analysis.processing.operations.export.Export2DBSLOperation";
}
@Override
public OperationRank getInputRank() {
return OperationRank.TWO;
}
@Override
public OperationRank getOutputRank() {
return OperationRank.TWO;
}
@Override
protected OperationData process(IDataset input, IMonitor monitor) throws OperationException {
// Get the frame's metadata so that we know the filename etc.
SliceFromSeriesMetadata sliceSeriesMetadata = getSliceSeriesMetadata(input);
String sampleName = input.getName();
int frameNumber = sliceSeriesMetadata.getSliceInfo().getSliceFromInput()[1].getStart();
// Get the file's name
String filePath = sliceSeriesMetadata.getFilePath();
//String fileName = sliceSeriesMetadata.getFilePath();
String folderPath = filePath.substring(0, filePath.lastIndexOf(File.separator));
String fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1, filePath.lastIndexOf("."));
String bslFolderPath = "";
// Create a save path
if (model.getOutputDirectoryPath() != "") {
bslFolderPath = model.getOutputDirectoryPath() + File.separator + fileName;
}
else {
bslFolderPath = folderPath + File.separator + fileName;
}
// Get the data so that it's a nice array for outputting
IDataset scalersData = (ProcessingUtils.getDataset(this, filePath, model.getScalersFilePath())).squeeze();
IDataset countTimes = (ProcessingUtils.getDataset(this, filePath, model.getCountTimeFilePath())).squeeze();
IDataset waitTimes = (ProcessingUtils.getDataset(this, filePath, model.getWaitTimeFilePath())).squeeze();
// Then generate the different file names that will be generated for the BSL directory
String[] bslFileNames = BSLFileNames(fileName);
// Make the BSL header file
BSLHeaderWriter(bslFolderPath, bslFileNames, sampleName, input.getShape(), sliceSeriesMetadata.getTotalSlices(), scalersData.getShape()[1]);
// Output the detector images
BSLDetectorImageWriter(bslFolderPath, bslFileNames, input, input.getShape());
// Output the scalers, focussing on the scaler values for this frame
BSLScalersWriter(bslFolderPath, bslFileNames, scalersData.getSlice(new Slice(frameNumber, frameNumber + 1)).squeeze());
// Output the secondary detector information (blank for now)
BSLNullWriter(bslFolderPath, bslFileNames);
// Output the scan times, focussing on the time values for this frame
BSLTimesWriter(bslFolderPath, bslFileNames, countTimes.getFloat(frameNumber), waitTimes.getFloat(frameNumber));
// Return the data as it arrived
OperationData output = new OperationData();
output.setData(input);
// And return the input data
return output;
}
protected String[] BSLFileNames (String fileName) {
// First we need the current date
Date currentDate = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(currentDate);
// Now we can format the month as required for the BSL standard
// Months are zero based
String month = Integer.toHexString(cal.get(Calendar.MONTH) + 1);
// then get the day
String day = String.format("%02d", cal.get(Calendar.DAY_OF_MONTH));
// and the last 3 digits of the run number
String runNumber = fileName.substring(fileName.length() - 3);
// Now we can crete a placeholder for the file titles
String[] bslFileNames = new String[5];
// And 'string' them all together
// 000 is the header
bslFileNames[0] = runNumber + "000." + month + day;
// 001 is the primary scattering data
bslFileNames[1] = runNumber + "001." + month + day;
// 002 is the scalers data
bslFileNames[2] = runNumber + "002." + month + day;
// 003 is the secondary scattering data
bslFileNames[3] = runNumber + "003." + month + day;
// 004 is the scan times
bslFileNames[4] = runNumber + "004." + month + day;
// Return the file names
return bslFileNames;
}
protected void BSLHeaderWriter (String folderPath, String[] fileNames, String sampleName, int [] detectorDimensions, int numberOfFrames, int scalersLength) {
// First, where's the data going?
new File(folderPath).mkdirs();
// Create the path for the header file
String filePath = folderPath + File.separator + fileNames[0];
if (new File(filePath).exists() == false) {
// Get a formatted timestamp
DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date currentDate = new Date();
// Format all the variables required as fixed length strings
String xLength = String.format("%1$"+8+ "s", detectorDimensions[1]);
String yLength = String.format("%1$"+8+ "s", detectorDimensions[0]);
String numberOfFramesString = String.format("%1$"+8+ "s", numberOfFrames);
String scalersLengthString = String.format("%1$"+8+ "s", scalersLength);
String zero = String.format("%1$"+8+ "s", 0);
String one = String.format("%1$"+8+ "s", 1);
String two = String.format("%1$"+8+ "s", 2);
String midsection = one + zero + zero + zero + zero + zero;
// There's a few variables in here just for the BSL format, such as zero and one...
// Create the strings for outputting
String fileHeader = "Created by DAWN on " + dateFormatter.format(currentDate) + "\n" + sampleName + "\n";
String detectorLine = xLength + yLength + numberOfFramesString + midsection + one + "\n" + fileNames[1] + "\n";
String scalersLine = scalersLengthString + numberOfFramesString + one + midsection + one + "\n" + fileNames[2] + "\n";
String secondaryDetectorLine = zero + zero + zero + zero + zero + zero + zero + zero + zero + one + "\n" + fileNames[3] + "\n";
String timesLine = two + numberOfFramesString + one + midsection + zero + "\n" + fileNames[4] + "\n";
// Create a fileWriter
BufferedWriter fileWriter = null;
try {
// Set up the reference to the file and write the header information
fileWriter = new BufferedWriter(new FileWriter(filePath));
fileWriter.write(fileHeader + detectorLine + scalersLine + secondaryDetectorLine + timesLine);
} catch (IOException fileError) {
// Print out if we have any errors
System.out.println("There was a problem creating the BSL header file: " + fileError.toString());
} finally {
try {
// Close the file regardless
fileWriter.close();
} catch (IOException fileError) {
// Unless there's an error!
System.out.println("There was a problem closing the BSL header file: " + fileError.toString());
}
}
}
}
protected void BSLDetectorImageWriter (String folderPath, String[] fileNames, IDataset dataForOutput, int[] dataShape) {
// First, where's the data going?
String filePath = folderPath + File.separator + fileNames[1];
// Get the size of the image
int[] dataSize = dataForOutput.getShape();
// Calculate how many bytes of data that is and create a byte array, for output
byte[] bytesToWrite = new byte[(dataSize[0] * dataSize[1] * 4)];
// Looping through each pixel
for (int yLoopIter = 0; yLoopIter < dataSize[0]; yLoopIter ++) {
for (int xLoopIter = 0; xLoopIter < dataSize[1]; xLoopIter ++) {
int loopIter = ((yLoopIter * dataSize[1]) + xLoopIter) * 4;
// Extract out the value as bytes
byte[] tempBytes = ByteBuffer.allocate(4).putFloat(dataForOutput.getFloat(yLoopIter, xLoopIter)).array();
// And place these in the byte array
bytesToWrite[loopIter] = tempBytes[0];
bytesToWrite[loopIter + 1] = tempBytes[1];
bytesToWrite[loopIter + 2] = tempBytes[2];
bytesToWrite[loopIter + 3] = tempBytes[3];
}
}
// Create a fileWriter
DataOutputStream fileWriter = null;
try {
// Set up the reference to the file and save the detector information as 32-bit real
fileWriter = new DataOutputStream(new FileOutputStream(filePath, true));
fileWriter.write(bytesToWrite);
} catch (IOException fileError) {
// Print out if we have any errors
System.out.println("There was a problem creating the BSL detector image file: " + fileError.toString());
} finally {
try {
// Close the file regardless
fileWriter.close();
} catch (IOException fileError) {
// Unless there's an error!
System.out.println("There was a problem closing the BSL detector image file: " + fileError.toString());
}
}
}
protected void BSLScalersWriter (String folderPath, String[] fileNames, IDataset scalerValues) {
// First, where's the data going?
String filePath = folderPath + File.separator + fileNames[2];
// Find out how many scalers there are
int scalerLength = scalerValues.getSize();
// Calculate how many bytes of data that is and create a byte array, for output
byte[] bytesToWrite = new byte[(scalerLength * 4)];
// Looping through each value
for (int scalerLoopIter = 0; scalerLoopIter < scalerLength; scalerLoopIter ++) {
// Extract out the value as bytes
byte[] tempBytes = ByteBuffer.allocate(4).putFloat(scalerValues.getFloat(scalerLoopIter)).array();
// And place these in the byte array
bytesToWrite[0] = tempBytes[0];
bytesToWrite[1] = tempBytes[1];
bytesToWrite[2] = tempBytes[2];
bytesToWrite[3] = tempBytes[3];
}
// Create a fileWriter
DataOutputStream fileWriter = null;
try {
// Set up the reference to the file and save the scalers information as 32-bit real
fileWriter = new DataOutputStream(new FileOutputStream(filePath, true));
fileWriter.write(bytesToWrite);
} catch (IOException fileError) {
// Print out if we have any errors
System.out.println("There was a problem creating the BSL detector image file: " + fileError.toString());
} finally {
try {
// Close the file regardless
fileWriter.close();
} catch (IOException fileError) {
// Unless there's an error!
System.out.println("There was a problem closing the BSL detector image file: " + fileError.toString());
}
}
}
protected void BSLNullWriter (String folderPath, String[] fileNames) {
// First, where's the data going?
String filePath = folderPath + File.separator + fileNames[3];
// So, we need a file (so we can save the times) but that doesn't mean it needs any information...
BufferedWriter fileWriter = null;
try {
// Set up the reference to the file and save nothing!
fileWriter = new BufferedWriter(new FileWriter(filePath));
fileWriter.write("");
} catch (IOException fileError) {
// Print out if we have any errors
System.out.println("There was a problem creating the BSL detector image file: " + fileError.toString());
} finally {
try {
// Close the file regardless
fileWriter.close();
} catch (IOException fileError) {
// Unless there's an error!
System.out.println("There was a problem closing the BSL detector image file: " + fileError.toString());
}
}
}
protected void BSLTimesWriter (String folderPath, String[] fileNames, float countTime, float waitTime) {
// First, where's the data going?
String filePath = folderPath + File.separator + fileNames[4];
// Find out how many timepoints there are
// Calculate how many bytes of data that is and create a byte array, for output
byte[] bytesToWrite = new byte[8];
// Extract out the count time as bytes
byte[] tempBytes = ByteBuffer.allocate(4).putFloat(countTime).array();
bytesToWrite[0] = tempBytes[0];
bytesToWrite[1] = tempBytes[1];
bytesToWrite[2] = tempBytes[2];
bytesToWrite[3] = tempBytes[3];
// Extract out the wait time as bytes
tempBytes = ByteBuffer.allocate(4).putFloat(waitTime).array();
bytesToWrite[4] = tempBytes[0];
bytesToWrite[5] = tempBytes[1];
bytesToWrite[6] = tempBytes[2];
bytesToWrite[7] = tempBytes[3];
// Create a fileWriter
DataOutputStream fileWriter = null;
try {
// Set up the reference to the file and save the scalers information as 32-bit real
fileWriter = new DataOutputStream(new FileOutputStream(filePath, true));
fileWriter.write(bytesToWrite);
} catch (IOException fileError) {
// Print out if we have any errors
System.out.println("There was a problem creating the BSL detector image file: " + fileError.toString());
} finally {
try {
// Close the file regardless
fileWriter.close();
} catch (IOException fileError) {
// Unless there's an error!
System.out.println("There was a problem closing the BSL detector image file: " + fileError.toString());
}
}
}
}