use of gdsc.smlm.tsf.TaggedSpotFile.SpotList in project GDSC-SMLM by aherbert.
the class ResultsManagerTest method writeTSFMatchesRead.
private void writeTSFMatchesRead(int channels, int slices, int positions, int types) {
String filename = createFile();
FileOutputStream out = null;
try {
out = new FileOutputStream(filename);
} catch (Exception e) {
closeOutput(out);
e.printStackTrace();
Assert.fail(e.getMessage());
}
// Write the offsets used in the TSF format
try {
DataOutputStream dos = new DataOutputStream(out);
dos.writeInt(0);
dos.writeLong(0);
} catch (IOException e) {
closeOutput(out);
e.printStackTrace();
Assert.fail(e.getMessage());
}
// Generate random spots
int size = 1000;
Spot[] spots = new Spot[size];
for (int i = 1; i <= size; i++) {
Spot.Builder builder = Spot.newBuilder();
builder.setChannel(1 + rand.nextInt(channels));
builder.setSlice(1 + rand.nextInt(slices));
builder.setPos(1 + rand.nextInt(positions));
builder.setFluorophoreType(rand.nextInt(1, types));
// This is a required field but is ignored when reading
builder.setMolecule(i);
builder.setCluster(rand.nextInt(10));
builder.setFrame(rand.nextInt(1, 100));
builder.setXPosition(rand.nextInt(50));
builder.setYPosition(rand.nextInt(50));
builder.setBackground(rand.next());
builder.setIntensity(rand.next());
builder.setX(rand.next());
builder.setY(rand.next());
builder.setWidth(TSFPeakResultsWriter.SD_TO_FWHM_FACTOR * rand.next());
Spot spot = builder.build();
spots[i - 1] = spot;
try {
spot.writeDelimitedTo(out);
} catch (IOException e) {
closeOutput(out);
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
// Write the header
// Get the offset to the SpotList message
long offset = 0;
try {
// The offset is the amount to skip forward after reading the int
// magic number (4 bytes) and long offset (8 bytes)
//out.flush();
offset = out.getChannel().position() - 12;
} catch (IOException e) {
closeOutput(out);
e.printStackTrace();
Assert.fail(e.getMessage());
}
// Record the SpotList message
SpotList.Builder builder = SpotList.newBuilder();
builder.setApplicationId(1);
builder.setNrSpots(size);
builder.setLocationUnits(LocationUnits.PIXELS);
builder.setIntensityUnits(IntensityUnits.COUNTS);
builder.setFitMode(FitMode.ONEAXIS);
builder.setNrChannels(channels);
builder.setNrSlices(slices);
builder.setNrPos(positions);
for (int type = 1; type <= types; type++) {
FluorophoreType.Builder typeBuilder = FluorophoreType.newBuilder();
typeBuilder.setId(type);
typeBuilder.setDescription("Type " + type);
typeBuilder.setIsFiducial(rand.next() < 0.5f);
builder.addFluorophoreTypes(typeBuilder.build());
}
SpotList spotList = builder.build();
try {
spotList.writeDelimitedTo(out);
} catch (IOException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
} finally {
closeOutput(out);
}
// Write the offset to the SpotList message into the offset position
RandomAccessFile f = null;
try {
f = new RandomAccessFile(new File(filename), "rw");
f.seek(4);
f.writeLong(offset);
} catch (Exception e) {
e.printStackTrace();
Assert.fail(e.getMessage());
} finally {
if (f != null) {
try {
f.close();
} catch (IOException e) {
}
}
}
// Read each combination
for (int channel = 1; channel <= channels; channel++) for (int slice = 1; slice <= slices; slice++) for (int position = 1; position <= positions; position++) for (int type = 1; type <= types; type++) {
StringBuilder sb = new StringBuilder();
sb.append(" channel=").append(channel);
sb.append(" slice=").append(slice);
sb.append(" position=").append(position);
sb.append(" fluorophore_type=[").append(type).append(":Type ").append(type).append(":fiducial=").append(builder.getFluorophoreTypes(type - 1).getIsFiducial()).append(']');
// This is needed to trick the Macro class into returning the options
// for the thread to the GenericDialog used in the ResultsManager
Thread.currentThread().setName("Run$_");
Macro.setOptions(sb.toString());
ResultsManager.setInputFilename(filename);
MemoryPeakResults in = ResultsManager.loadInputResults(ResultsManager.INPUT_FILE, false);
checkEqual(spots, channel, slice, position, type, in);
}
}
use of gdsc.smlm.tsf.TaggedSpotFile.SpotList in project GDSC-SMLM by aherbert.
the class TSFPeakResultsReader method isTSF.
/**
* Checks if is a binary TSF file by attempting to read the SpotList header.
*
* @param filename
* the filename
* @return true, if is a TSF file
*/
public static boolean isTSF(String filename) {
FileInputStream fi = null;
try {
fi = new FileInputStream(filename);
DataInputStream di = new DataInputStream(fi);
// the file has an initial 0, then the offset (as long)
// to the position of spotList
int magic = di.readInt();
if (magic != 0) {
// Magic number should be zero
return false;
}
if (fi.available() == 0) {
// No more contents
return false;
}
long offset = di.readLong();
if (offset == 0) {
// No offset record
return false;
}
fi.skip(offset);
SpotList spotList = SpotList.parseDelimitedFrom(fi);
if (spotList != null)
return true;
} catch (Exception e) {
// Fail
} finally {
if (fi != null) {
try {
fi.close();
} catch (IOException e) {
}
}
}
return false;
}
use of gdsc.smlm.tsf.TaggedSpotFile.SpotList in project GDSC-SMLM by aherbert.
the class TSFPeakResultsWriter method end.
/*
* (non-Javadoc)
*
* @see gdsc.utils.fitting.PeakResults#end()
*/
public void end() {
// Get the offset to the SpotList message
long offset = 0;
try {
// The offset is the amount to skip forward after reading the int
// magic number (4 bytes) and long offset (8 bytes)
//out.flush();
offset = out.getChannel().position() - 12;
} catch (IOException e) {
// This is bad.
System.err.println("Failed to determine offset for SpotList message");
e.printStackTrace();
closeOutput();
return;
}
// Record the SpotList message
SpotList.Builder builder = SpotList.newBuilder();
builder.setApplicationId(APPLICATION_ID);
builder.setNrSpots(size);
// Add the standard details the TSF supports. We use extensions to add GDSC SMLM data.
if (name != null) {
builder.setName(name);
}
if (source != null) {
builder.setNrPixelsX(source.width);
builder.setNrPixelsY(source.height);
builder.setNrFrames(source.frames);
builder.setSource(singleLine(source.toXML()));
}
if (bounds != null) {
ROI.Builder roiBuilder = builder.getRoiBuilder();
roiBuilder.setX(bounds.x);
roiBuilder.setY(bounds.y);
roiBuilder.setXWidth(bounds.width);
roiBuilder.setYWidth(bounds.height);
builder.setRoi(roiBuilder.build());
}
if (calibration != null) {
if (calibration.hasNmPerPixel())
builder.setPixelSize((float) calibration.getNmPerPixel());
if (calibration.hasExposureTime())
builder.setExposureTime(calibration.getExposureTime());
if (calibration.hasReadNoise())
builder.setReadNoise(calibration.getReadNoise());
if (calibration.hasBias())
builder.setBias(calibration.getBias());
if (calibration.hasEMCCD())
builder.setEmCCD(calibration.isEmCCD());
if (calibration.hasAmplification())
builder.setAmplification(calibration.getAmplification());
if (calibration.hasGain()) {
builder.setGain(calibration.getGain());
// Use amplification if present (as this is the correct electrons/count value), otherwise use gain
if (calibration.hasAmplification()) {
double ecf = calibration.getAmplification();
double qe = calibration.getGain() / ecf;
builder.addEcf(ecf);
builder.addQe(qe);
} else {
builder.addEcf(calibration.getGain());
builder.addQe(1);
}
}
}
if (configuration != null && configuration.length() > 0) {
builder.setConfiguration(singleLine(configuration));
}
// Have a property so the boxSize can be set
if (boxSize > 0)
builder.setBoxSize(boxSize);
builder.setLocationUnits(LocationUnits.PIXELS);
builder.setIntensityUnits(IntensityUnits.COUNTS);
builder.setThetaUnits(ThetaUnits.DEGREES);
builder.setFitMode(fitMode);
FluorophoreType.Builder typeBuilder = FluorophoreType.newBuilder();
typeBuilder.setId(1);
typeBuilder.setDescription("Default fluorophore");
typeBuilder.setIsFiducial(false);
builder.addFluorophoreTypes(typeBuilder.build());
SpotList spotList = builder.build();
try {
spotList.writeDelimitedTo(out);
} catch (IOException e) {
System.err.println("Failed to write SpotList message");
e.printStackTrace();
return;
} finally {
closeOutput();
}
// Note: it would be good to be able to use the ability to write to any output stream. However
// the TSF format requires a seek at the end of writing to record the offset. seek() is not
// supported by OutputStream. It is supported by: RandomAccessFile, RandomAccessStream (for input).
// Write the offset to the SpotList message into the offset position
RandomAccessFile f = null;
try {
f = new RandomAccessFile(new File(filename), "rw");
f.seek(4);
f.writeLong(offset);
} catch (Exception e) {
System.err.println("Failed to record offset for SpotList message");
e.printStackTrace();
} finally {
if (f != null) {
try {
f.close();
} catch (IOException e) {
}
}
}
}
Aggregations