package IBA_J.ConvertListFiles.ADC;
import java.util.ArrayList;
import ij.*;
import ij.process.ImageProcessor;
import java.io.*;
/**
* This class is used to describe ADC and associated methods
* ADC basically contains a list of events (an event : x,y,E)
*/
public class ADC{
//components declaration
private final ArrayList<int[]> eventList = new ArrayList<>();
private final ArrayList<ArrayList<Integer>> map = new ArrayList<>();
private final ArrayList<Integer> median = new ArrayList<>();
private final ArrayList<Integer> activationPeriods = new ArrayList<>();
private String path;
private final Integer sizeMapX=256;
private final Integer sizeMapY=256;
/**
* ADC constructor with initialization of empty eventList ans median energy for STIM map
*/
public ADC(){
eventList.add(new int[3]);
median.add(0);
}
/**
* ADC constructor with path initialization
* @param path path for the ADC
*/
public ADC(String path){
eventList.add(new int[3]);
median.add(0);
this.path=path;
}
//ADC destructor
@Override
public void finalize() throws Throwable{
super.finalize();
}
private void initializeMedianMap(){
for (int i=0;i<sizeMapX*sizeMapY+1;i++){
map.add(new ArrayList<Integer>());
map.get(i).add(0);
}
}
//getter
/**
* @return path for this ADC
*/
public String getPath(){
return this.path;
}
/**
* @param position in the eventList
* @return event for this postion
*/
public int[] getEvent(int position){
return eventList.get(position);
}
/**
* @return last event of the eventList (X, Y, E)
*/
public int[] getlastEvent(){
return eventList.get(getNEvents()-1);
}
/**
* @param position of event in the list
* remove event at the specified position
*/
public void removeEvent(int position){
eventList.remove(position);
}
/**
* @return size of evetn list as a number of events
*/
public int getNEvents(){
return eventList.size();
}
/**
* @param position of event in the event list
* @return number of periods at the event position ??
*/
public int getActivationPeriod(int position){
return activationPeriods.get(position);
}
/**
* @return total number of activation periods ??
*/
public int getNActivationPeriods(){
return activationPeriods.size();
}
/**
* adds the value of the activation state
*/
public void addPeriod(int state){
activationPeriods.add(state);
}
/**
* Calculates a 4096 channels spectra from an event list
* @return a Table containing 4096 values (double type)
*/
public double[] getSpectra(){
int size=4096;
double[] spectra=new double[size];
try{
for (int i=0;i<getNEvents();i++){
int [] evt;
evt = getEvent(i);
if (evt[2]<size) spectra[evt[2]]+=1;
}
}
catch (Exception e){
IJ.log("**Error** " + e.toString());
}
return spectra;
}
/**
* Calculates a spectra from an event list
* @param size size of spectra (number of channel) to be calculated
* @return spectra as a table containing the [size] values
*/
public double [] getSpectra(int size){
double[] spectra=new double[size];
try{
for (int i=0;i<getNEvents();i++){
int [] evt;
evt = getEvent(i);
if (evt[2]<size) spectra[evt[2]]+=1;
}
}
catch (Exception e){
IJ.log("**Error** " +e.toString());
}
return spectra;
}
/**
* Returns X-coordinate of event (X,Y,E)
* @param event Index in event list
* @return X-coordinate for this event
*/
public int getX(int event){
int [] XYE=getEvent(event);
return XYE[0];
}
/**
* Returns max X-coordinate of eventList
* @return max X-coordinate for this eventList
*/
public int getMaxX(){
int max=0;
for (int i=0;i<getNEvents();i++){
if (getX(i)>max) max=getX(i);
}
return max;
}
/**
* Returns max Y-coordinate of eventList
* @return max Y-coordinate for this eventList
*/
public int getMaxY(){
int max=0;
for (int i=0;i<getNEvents();i++){
if (getY(i)>max) max=getY(i);
}
return max;
}
/**
* Returns Y-coordinate of event (X,Y,E)
* @param event Index in event list
* @returns Y-coordinate for this event
*/
/**
* Returns max of Y-coordinate or Y of eventList
* @return max Y-or-X-coordinate for this eventList
*/
public int getMaxXY(){
int max=0;
for (int i=0;i<getNEvents();i++){
if (getY(i)>max) max=getY(i);
if (getX(i)>max) max=getX(i);
}
return max;
}
/**
* @param event
* return Y position for event
*/
public int getY(int event){
int [] XYE=getEvent(event);
return XYE[1];
}
/**
* Returns energy of event (X,Y,E)
* @param event Index in event list
* @return Energy for this event
*/
public int getE(int event){
int [] XYE=getEvent(event);
return XYE[2];
}
/**
* Gets the median value stored in median energy arraylist
* @param index index of arraylist
* @return median energy value
*/
public int getMedianValue(int index){
return median.get(index);
}
/**
* Gets the median energy value for the corresponding pixel on a 256-pixel-width map
* @param x x-coordinate for pixel
* @param y y-coordinate for pixel
* @return median energy corresponding to x,y coordinate
*/
public int getMedianValue(int x, int y){
return median.get(x+sizeMapX*y);
}
/**
* Gets the median energy value for the corresponding pixel
* @param x x-coordinate for pixel
* @param y y-coordinate for pixel
* @param sizeMapY Height of map in pixels
* @return median energy corresponding to x,y coordinate
*/
public int getMedianValue(int x, int y, int sizeMapY){
return median.get(x+sizeMapX*y);
}
//setter
/**
* Appends one event to the events list
* @param event (X,Y,E) to be added to the list
*/
public void addEvent(int[] event){
eventList.add(event);
}
//functions
/**
* Saves a spectra as a text file (1 column)
* @param path filename for the spectra to be saved
*/
public void saveCountsSpectra(String path){
try{
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(path)));
double [] tab = getSpectra();
for (int i=0;i<4096;i++) {
out.println(String.valueOf((int)tab[i]));
}
out.close();
}
catch (IOException e){
}
}
/**
* Saves a spectra in the Gupix format
* @param path filename for spectra to be saved
*/
public void saveGupixSpectra(String path){
try{
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(path)));
double [] tab = getSpectra();
out.println("4096 0");
for (int i=0;i<4096;i++) {
out.println(String.valueOf((int)tab[i]));
}
out.close();
}
catch (IOException e){
}
}
/**
* Saves spectra in 2 columns text file accounting for channel (1st) and counts
* @param path filename for text file
*/
public void saveChannelCountsSpectra(String path){
try{
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(path)));
double [] tab = getSpectra();
for (int i=0;i<4096;i++) {
out.println(String.valueOf(i)+"\t"+String.valueOf((int)tab[i]));
}
out.close();
}
catch (IOException e){
}
}
/**
* Saves the ADC in a binary format (short)X,(short)Y,(Integer)E
* The file can be open with IBA_J (but not with the old Supavisio)
* @param ops stream where data will be saved. At the end of process ops will be closed.
*/
public void saveXYEListFile(DataOutputStream ops){
try{
for (int i=0;i<getNEvents();i++){
ops.writeShort(getX(i)); // stores the X point coordinate
ops.writeShort(getY(i)); // stores the Y point coordinate
ops.writeInt(getE(i)); // stores the Energy value in point
}
ops.close(); // this closes the ops object
}
catch (IOException e){
}
}
/**
* Saves the ADC in a binary format (short)X,(short)Y,(Integer)E
* The file can be open with IBA_J (but not with the old Supavisio)
* @param path filename for the datafile to be saved
*/
public void saveXYEListFile(String path){
try{
DataOutputStream ops=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
for (int i=0;i<getNEvents();i++){
ops.writeShort(getX(i)); // stores the X point coordinate
ops.writeShort(getY(i)); // stores the Y point coordinate
ops.writeInt(getE(i)); // stores the Energy value in point
}
ops.close(); // this closes the ops object
}
catch (IOException e){
}
}
/**
* Saves the ADC in a file in the supavisio format (see below)
* The file can be open with the old Supavisio, not by IBA_J
* @param path filename for the datafile to be saved
* @param type type of data to be saved (see below)
* supavisio is little endian type
* (short)0:pixe;1(rbs);2:Stim;5:erda
* (short)X size of map
* (short)Y size of map
* events: (short)X,(short)Y, (short)E
*/
public void saveXYEListFile(String path, Short type){
try{
DataOutputStream ops=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
ops.writeShort(LittleEndian(type));
ops.writeShort(LittleEndian((short)255));
ops.writeShort(LittleEndian((short)255));
for (int i=1;i<getNEvents();i++){
ops.writeShort(LittleEndian((short)(getX(i)))); // stores the X point coordinate from ADC
ops.writeShort(LittleEndian((short)(getY(i)))); // stores the X point coordinate from ADC
ops.writeInt(LittleEndian((short)getE(i))); // stores the Energy value in point from ADC
}
ops.close(); // this closes the ops object
}
catch (IOException e){
}
}
/**
* Open a sorted events list
* @param ips stream to be read
*/
public void open(DataInputStream ips){
try{
while(true){
int[] evt = new int[3];
evt[0]=ips.readShort();
evt[1]=ips.readShort();
evt[2]=ips.readInt();
addEvent(evt);
}
}
catch (IOException e){}
}
/**
* Open a sorted events list
* @param ips stream to be read
*/
/* public void readSupaVisioTypeEventList(DataInputStream ips){
//for compatibility only
try{
ips.readShort();
ips.readShort();
ips.readShort();
while(ips.available()>0){
int[] evt = new int[3];
try {
evt[0]=LittleEndian((short)ips.readUnsignedShort());
evt[1]=LittleEndian((short)ips.readUnsignedShort());
evt[2]=LittleEndian((short)ips.readInt());
addEvent(evt);}
catch (Exception e){
}
}
}
catch (IOException e){}
java.lang.System.gc();
}*/
/**
* Converts short integer to little endian as required for Supavisio reading
* @param v integer to be converted
* @returns v as little endian
*/
private int LittleEndian (short v){
return ((v>>8)|(v<<8));
}
/**
* Sorts events according to X,Y and processes median energy map
* @return median, a list of integers corresponding to median energy in pixel
*/
public ArrayList<Integer> medianSort(){
try{
initializeMedianMap();
for (int i=1;i<getNEvents();i++){
int index=(int)getX(i)+sizeMapX*(int)getY(i)+1;
try{
map.get(index).add((int)getE(i));
}
catch(Exception e){
IJ.log("**Error** " +e.toString());
}
}
}
catch (Exception e){
IJ.log("**Error** " + e.toString());
}
for (int i=1;i<map.size();i++){
java.util.Collections.sort(map.get(i));
int size=map.get(i).size();
median.add(map.get(i).get((int)(size/2)));
}
return median;
}
/**
* Saves median map as a 2D text file using given path
* @param path filename for 2D text file
*/
public void saveMedianTextImage(String path){
try{
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(path)));
for (int x=2;x<sizeMapX;x++) {
String line="";
for (int y=1;y<sizeMapY;y++){
line+=String.valueOf(median.get(x+sizeMapX*y))+" ";
}
out.println(line);
}
out.close();
}
catch (IOException e){
}
}
/**
* Save median map as a TIFF file
* @param path for the saved file
*/
public void saveMedianImage(String path){
ImagePlus imp = new ImagePlus();
ImageProcessor ip = imp.getProcessor();
for (int x=2;x<sizeMapX;x++) {
for (int y=1;y<sizeMapY;y++){
ip.set(x,y,median.get(x+sizeMapX*y));
}
}
IJ.saveAs(imp, "TIFF",path);
}
}