package cz.cuni.lf1.lge.ThunderSTORM.util;
import cz.cuni.lf1.lge.ThunderSTORM.estimators.PSF.Molecule;
import cz.cuni.lf1.lge.ThunderSTORM.estimators.PSF.PSFModel;
import cz.cuni.lf1.lge.ThunderSTORM.estimators.PSF.PSFModel.Params;
import ij.process.FloatProcessor;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import java.io.File;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
// Note: this file should be replaced by a newer version; some of the things used here are deprecated
/**
* Importing CSV files and translating them into internal plugin objects (FloatProcessor, PSFModel, Point).
*/
public class CSV {
private static List<String[]> readCsv(String fname) {
List<String[]> lines = new ArrayList<String[]>();
LineIterator it = null;
try {
it = FileUtils.lineIterator(new File(fname), "UTF-8");
while (it.hasNext()) lines.add(it.nextLine().split(","));
} catch (IOException ignored) {
} finally {
if (it != null) LineIterator.closeQuietly(it);
}
return lines;
}
/**
* Read an input CSV file and interpret the data as an image (FloatProcessor).
*
* @param fname path to an input CSV file
* @return a <strong>new instance</strong> of FloatProcessor that contains data from the input CSV file
*
* @throws IOException if the input file specified by {@fname was not found or cannot be opened for reading}
* @throws InvalidObjectException if the input file does not contain any data
*/
public static FloatProcessor csv2fp(String fname) throws IOException, InvalidObjectException {
List<String[]> lines = readCsv(fname);
if(lines.size() < 1) throw new InvalidObjectException("CSV data have to be in a full square/rectangle matrix!");
if(lines.get(0).length < 1) throw new InvalidObjectException("CSV data have to be in a full square/rectangle matrix!");
float [][] array = new float[lines.get(0).length][lines.size()];
for(int c = 0; c < array.length; c++) {
for(int r = 0; r < array[c].length; r++) {
array[c][r] = Float.parseFloat(lines.get(r)[c]);
}
}
return new FloatProcessor(array);
}
/**
* Read an input CSV file and interpret the data as a set of PSFs (Point Spread Functions).
*
* The input data are supposed to be in the following format:
* <pre>{@code x,y,sigma,Intensity}</pre>
* The background parameter is by default set to zero and it is not expected to be
* found in the input file.
*
* @param fname path to an input CSV file
* @param start_row row offset from which we want to read the data
* @param start_col column offset from which we want to read the data
* @return a Vector of PSFs initialized based on the data in CSV file
*
* @throws IOException if the input file specified by {@fname was not found or cannot be opened for reading}
* @throws InvalidObjectException if the input file does not contain any data
*
* @see PSFModel
*/
public static Vector<Molecule> csv2psf(String fname, int start_row, int start_col) throws IOException, InvalidObjectException, Exception {
List<String[]> lines = readCsv(fname);
if(lines.size() < 1) throw new InvalidObjectException("CSV data have to be in a full square/rectangle matrix!");
if(lines.get(0).length < 1) throw new InvalidObjectException("CSV data have to be in a full square/rectangle matrix!");
Vector<Molecule> loc = new Vector<Molecule>();
int[] params = new int[]{PSFModel.Params.X, PSFModel.Params.Y, PSFModel.Params.INTENSITY, PSFModel.Params.SIGMA, PSFModel.Params.BACKGROUND};
for(int r = start_row, rm = lines.size(); r < rm; r++) {
loc.add(new Molecule(new Params(params, new double[]{
Float.parseFloat(lines.get(r)[start_col+0]), // x
Float.parseFloat(lines.get(r)[start_col+1]), // y
Float.parseFloat(lines.get(r)[start_col+3]), // I
Float.parseFloat(lines.get(r)[start_col+2]), // s
0.0}, // b
false)));
}
return loc;
}
}