use of gdsc.smlm.tsf.TaggedSpotFile.LocationUnits in project GDSC-SMLM by aherbert.
the class TSFPeakResultsReader method read.
/**
* Read the results from the TSF file into memory
*
* @return The results set (or null if an error occurred)
*/
public MemoryPeakResults read() {
readHeader();
if (spotList == null)
return null;
MemoryPeakResults results = createResults();
// Read the messages that contain the spot data
FileInputStream fi = null;
try {
fi = new FileInputStream(filename);
// size of int + size of long
fi.skip(12);
} catch (Exception e) {
System.err.println("Failed to read open TSF file: " + filename);
e.printStackTrace();
if (fi != null) {
try {
fi.close();
} catch (IOException ex) {
}
}
return null;
}
LocationUnits locationUnits = spotList.getLocationUnits();
boolean locationUnitsWarning = false;
float locationConversion = 1;
switch(locationUnits) {
case PIXELS:
break;
case NM:
locationConversion = 1 / getNmPerPixel(results.getCalibration());
break;
case UM:
float nmPerPixel = getNmPerPixel(results.getCalibration());
if (nmPerPixel != 1) {
float umPerPixel = nmPerPixel / 1000;
locationConversion = 1 / umPerPixel;
}
break;
default:
System.err.println("Unsupported location units conversion: " + locationUnits);
}
IntensityUnits intensityUnits = spotList.getIntensityUnits();
boolean intensityUnitsWarning = false;
float intensityConversion = 1;
switch(intensityUnits) {
case COUNTS:
break;
case PHOTONS:
intensityConversion = getGain(results.getCalibration());
break;
default:
System.err.println("Unsupported intensity units conversion: " + intensityUnits);
}
final float bias = (results.getCalibration().hasBias()) ? (float) results.getCalibration().getBias() : 0f;
ThetaUnits thetaUnits = spotList.getThetaUnits();
float thetaConversion = 1;
switch(thetaUnits) {
case DEGREES:
break;
case RADIANS:
thetaConversion = (float) (180.0 / Math.PI);
break;
default:
System.err.println("Unsupported theta units conversion: " + thetaUnits);
}
FitMode fitMode = FitMode.ONEAXIS;
if (spotList.hasFitMode())
fitMode = spotList.getFitMode();
final boolean filterPosition = position > 0;
final boolean filterSlice = slice > 0;
long expectedSpots = getExpectedSpots();
try {
long totalSpots = 0;
while (fi.available() > 0 && (totalSpots < expectedSpots || expectedSpots == 0)) {
totalSpots++;
Spot spot = Spot.parseDelimitedFrom(fi);
// Only read the specified channel, position, slice and fluorophore type
if (spot.getChannel() != channel)
continue;
if (filterPosition && spot.hasPos() && spot.getPos() != position)
continue;
if (filterSlice && spot.hasSlice() && spot.getSlice() != slice)
continue;
if (spot.hasFluorophoreType() && spot.getFluorophoreType() != fluorophoreType)
continue;
if (spot.hasLocationUnits() && !locationUnitsWarning && spot.getLocationUnits() != locationUnits) {
System.err.println("Spot message has different location units, the units will be ignored: " + spot.getLocationUnits());
locationUnitsWarning = true;
}
if (spot.hasIntensityUnits() && !intensityUnitsWarning && spot.getIntensityUnits() != intensityUnits) {
System.err.println("Spot message has different intensity units, the units will be ignored: " + spot.getIntensityUnits());
intensityUnitsWarning = true;
}
// Required fields
int frame = spot.getFrame();
float[] params = new float[7];
params[Gaussian2DFunction.X_POSITION] = spot.getX() * locationConversion;
params[Gaussian2DFunction.Y_POSITION] = spot.getY() * locationConversion;
params[Gaussian2DFunction.SIGNAL] = spot.getIntensity() * intensityConversion;
if (spot.hasBackground()) {
// The writer of the TSF file should have removed the bias (as documented in the format).
// We can add it back for GSDC results
params[Gaussian2DFunction.BACKGROUND] = spot.getBackground() * intensityConversion + bias;
}
// Support different Gaussian shapes
if (fitMode == FitMode.ONEAXIS) {
params[Gaussian2DFunction.X_SD] = params[Gaussian2DFunction.Y_SD] = spot.getWidth() / TSFPeakResultsWriter.SD_TO_FWHM_FACTOR;
} else {
if (!spot.hasA()) {
params[Gaussian2DFunction.X_SD] = params[Gaussian2DFunction.Y_SD] = spot.getWidth() / TSFPeakResultsWriter.SD_TO_FWHM_FACTOR;
} else {
double a = Math.sqrt(spot.getA());
double sd = spot.getWidth() / TSFPeakResultsWriter.SD_TO_FWHM_FACTOR;
params[Gaussian2DFunction.X_SD] = (float) (sd * a);
params[Gaussian2DFunction.Y_SD] = (float) (sd / a);
}
if (fitMode == FitMode.TWOAXISANDTHETA && spot.hasTheta()) {
params[Gaussian2DFunction.SHAPE] = spot.getTheta() * thetaConversion;
}
}
// We can use the original position in pixels used for fitting
int origX = (spot.hasXPosition()) ? spot.getXPosition() : 0;
int origY = (spot.hasYPosition()) ? spot.getYPosition() : 0;
// Q. Should we use the required field 'molecule'?
float origValue = 0;
double error = 0;
float noise = 0;
float[] paramsStdDev = null;
int id = 0;
int endFrame = frame;
if (isGDSC) {
error = spot.getError();
noise = spot.getNoise();
id = spot.getCluster();
origValue = spot.getOriginalValue();
endFrame = spot.getEndFrame();
if (spot.getParamsStdDevCount() != 0) {
paramsStdDev = new float[spot.getParamsStdDevCount()];
for (int i = 0; i < paramsStdDev.length; i++) paramsStdDev[i] = spot.getParamsStdDev(i);
}
} else // Use the standard cluster field for the ID
if (spot.hasCluster()) {
id = spot.getCluster();
}
// Allow storing any of the optional attributes
AttributePeakResult peakResult = new AttributePeakResult(frame, origX, origY, origValue, error, noise, params, paramsStdDev);
peakResult.setEndFrame(endFrame);
peakResult.setId(id);
if (spot.hasXPrecision() || spot.hasYPrecision()) {
// Use the average. Note this is not the Euclidean distance since we divide by n!
double p = 0;
int n = 0;
if (spot.hasXPrecision()) {
p = spot.getXPrecision() * spot.getXPrecision();
n++;
}
if (spot.hasYPrecision()) {
p += spot.getYPrecision() * spot.getYPrecision();
n++;
}
peakResult.setPrecision(Math.sqrt(p / n));
}
results.add(peakResult);
}
} catch (IOException e) {
System.err.println("Failed to read Spot message");
e.printStackTrace();
// Only fail if there is a number of expected spots.
if (expectedSpots != 0) {
System.err.println("Unexpected error in reading Spot messages, no results will be returned");
return null;
}
} finally {
if (fi != null) {
try {
fi.close();
} catch (IOException e) {
}
}
}
return results;
}
Aggregations