--- a
+++ b/src/utils/utils.java
@@ -0,0 +1,318 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package utils;
+
+import biodiscml.Main;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.channels.FileChannel;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.TreeMap;
+import org.apache.commons.math3.stat.descriptive.moment.Mean;
+import org.apache.commons.math3.stat.descriptive.moment.StandardDeviation;
+
+/**
+ *
+ * @author Administrator
+ */
+public class utils {
+
+    public static HashMap<String, ArrayList<String>> convertDataColumnsToHashMap(ArrayList<String[]> altable) {
+        HashMap<String, ArrayList<String>> hmData = new HashMap<>();
+        for (int i = 1; i < altable.get(0).length; i++) { //for column
+            String header = altable.get(0)[i]; //get column header
+            ArrayList<String> al = new ArrayList<>(); //data list of the column
+            for (int j = 1; j < altable.size(); j++) { //for each value in the column
+                try {
+                    al.add(altable.get(j)[i]);
+                } catch (Exception e) {
+                    al.add("");
+                }
+            }
+            hmData.put(header, al);
+        }
+        return hmData;
+    }
+
+    public static ArrayList<String[]> readTable(String file, String separator) {
+        if (separator.isEmpty()) {
+            separator = detectSeparator(file);
+        }
+        ArrayList<String[]> altable = new ArrayList<>();
+        int cpt = 1;
+        try {
+            BufferedReader br = new BufferedReader(new FileReader(file));
+            while (br.ready()) {
+                if (Main.debug2) {
+                    System.out.println("Reading line " + cpt++);
+                }
+                altable.add(br.readLine().split(separator));
+            }
+            br.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return altable;
+    }
+
+    public static ArrayList<String[]> readTable(String file) {
+        String separator = detectSeparator(file);
+        if (Main.debug) {
+            System.out.println("reading table " + file);
+        }
+        ArrayList<String[]> altable = new ArrayList<>();
+        try {
+            BufferedReader br = new BufferedReader(new FileReader(file));
+            while (br.ready()) {
+                altable.add(br.readLine().split(separator));
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return altable;
+    }
+
+    public static String[][] transposeMatrix(String[][] m) {
+        String[][] temp = new String[m[0].length][m.length];
+        for (int i = 0; i < m.length; i++) {
+            for (int j = 0; j < m[0].length; j++) {
+                temp[j][i] = m[i][j];
+            }
+        }
+        return temp;
+    }
+
+    /**
+     *
+     * @param doubles
+     * @return
+     */
+    public static double[] convertStringListToDoubles(ArrayList<String> doubles) {
+        double[] ret = new double[doubles.size()];
+        Iterator<String> iterator = doubles.iterator();
+        int i = 0;
+        while (iterator.hasNext()) {
+            ret[i] = Double.valueOf(iterator.next());
+            i++;
+        }
+        return ret;
+    }
+
+    /**
+     * auto detection of the delimiter
+     *
+     * @param infile
+     * @return
+     */
+    public static String detectSeparator(String infile) {
+        if (Main.debug) {
+            //System.out.println("Delimiter not specified, auto-detection 10 first lines among these delimiters: \"\\t\" \" \" \";\" \",\" \"~\" \":\" \"/\" \"\\|\"");
+            System.out.print("Delimiter not specified, auto-detection in the 10 first lines...");
+        }
+        String delimiter = "";
+        String potentialDelimiters[] = {"\\t", " ", ";", ",", "~", ":", "/", "\\|"};
+        for (String potentialDelimiter : potentialDelimiters) {
+            try {
+                BufferedReader br = new BufferedReader(new FileReader(infile));
+                boolean sameNumberAsPreviousLine = true;
+                String line = br.readLine();
+                int init = line.split(potentialDelimiter).length;
+                if (init > 1) {
+                    int cpt = 0;
+                    while (br.ready() & sameNumberAsPreviousLine && cpt < 10) {
+                        cpt++;
+                        line = br.readLine();
+                        if (!line.trim().isEmpty()) {
+                            int split = line.split(potentialDelimiter).length;
+                            if (split == init) {
+                                init = split;
+                            } else {
+                                sameNumberAsPreviousLine = false;
+                            }
+                        }
+                    }
+                    if (sameNumberAsPreviousLine) {
+                        delimiter = potentialDelimiter;
+                        break;
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        if (delimiter.isEmpty()) {
+            System.err.print("[error] CSV separator not detected. Guessing there is just one column. "
+                    + "If not, change your CSV separator to a standard one (ex: tabulation or comma), or check the file consistency");
+            delimiter = " ";
+        }
+        if (Main.debug) {
+            System.out.println("Delimiter found:" + delimiter);
+        }
+        return delimiter;
+    }
+
+    public static void copyFileUsingStream(File source, File dest) throws IOException {
+        InputStream is = null;
+        OutputStream os = null;
+        try {
+            is = new FileInputStream(source);
+            os = new FileOutputStream(dest);
+            byte[] buffer = new byte[1024];
+            int length;
+            while ((length = is.read(buffer)) > 0) {
+                os.write(buffer, 0, length);
+            }
+        } finally {
+            is.close();
+            os.close();
+        }
+    }
+
+    public static void copyFileUsingChannel(File source, File dest) throws IOException {
+        FileChannel sourceChannel = null;
+        FileChannel destChannel = null;
+        try {
+            sourceChannel = new FileInputStream(source).getChannel();
+            destChannel = new FileOutputStream(dest).getChannel();
+            destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
+        } finally {
+            sourceChannel.close();
+            destChannel.close();
+        }
+    }
+
+    public static String arrayToString(String[] array, String separator) {
+        String s = "";
+        for (int i = 0; i < array.length; i++) {
+            if (array[i] != null) {
+                s += array[i] + separator;
+            }
+        }
+        return s.substring(0, s.length() - 1);
+    }
+
+    public static String arrayToString(ArrayList<Integer> array, String separator) {
+        String s = "";
+        for (int i = 0; i < array.size(); i++) {
+            s += array.get(i) + separator;
+        }
+        return s.substring(0, s.length() - 1);
+    }
+
+    public static double[] arrayToDouble(ArrayList<Double> al) {
+        return al.stream().mapToDouble(Double::doubleValue).toArray();
+    }
+
+    public static String getStandardDeviation(ArrayList<Double> al) {
+        DecimalFormat df = new DecimalFormat();
+        df.setMaximumFractionDigits(3);
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols();
+        dfs.setDecimalSeparator('.');
+        df.setDecimalFormatSymbols(dfs);
+
+        StandardDeviation s = new StandardDeviation();
+        s.setData(utils.arrayToDouble(al));
+
+        return df.format(s.evaluate());
+    }
+
+    /**
+     * Table Object to manipulate table
+     */
+    public static class TableObject {
+
+        public HashMap<String, ArrayList<String>> hmData = new HashMap<>();//<ColName,Values>
+        public HashMap<String, Integer> hmIDsList = new HashMap<>(); //<ID,index>
+
+        public TableObject(ArrayList<String[]> altable) {
+            if (Main.debug) {
+                System.out.println("converting table");
+            }
+            hmData = convertDataColumnsToHashMap(altable);
+            int ID_index = getIdIndex(altable);
+            for (int i = 1; i < altable.size(); i++) { //for each ID
+                //hmIDsList.put(altable.get(i)[ID_index].toLowerCase(), i - 1);
+                Integer j = hmIDsList.put(altable.get(i)[ID_index], i - 1);
+                if (j != null) {
+                    System.err.println("DUPLICATED ID DETECTED: " + altable.get(i)[ID_index]);
+                    System.err.println("All IDs must be unique");
+                    System.exit(0);
+                }
+            }
+        }
+
+        public ArrayList<String> getTheClass(String theclass) {
+            ArrayList<String> toreturn = hmData.get(theclass);
+            hmData.remove(theclass);
+            return toreturn;
+        }
+
+        public boolean containsClass(String theClass) {
+            return hmData.containsKey(theClass);
+        }
+
+        public int getIdIndex(ArrayList<String[]> altable) {
+            int cpt = 0;
+            for (String s : altable.get(0)) {
+                if (s.equals(Main.mergingID)) {
+                    return cpt;
+                } else {
+                    cpt++;
+                }
+            }
+            return 0;
+        }
+
+        public ArrayList<String> getSortedHmDataKeyset() {
+            ArrayList<String> al = new ArrayList<>();
+            TreeMap<String, ArrayList<String>> tm = new TreeMap<>();
+            tm.putAll(hmData);
+            for (String key : tm.keySet()) {
+                al.add(key);
+            }
+            return al;
+        }
+    }
+
+    /**
+     * calculate mean of an array of doubles
+     *
+     * @param al
+     * @return
+     */
+    public static String getMean(ArrayList<Double> al) {
+
+        if (!al.isEmpty()) {
+            double d[] = new double[al.size()];
+            for (int i = 0; i < al.size(); i++) {
+                if (!al.get(i).isNaN()) {
+                    d[i] = (double) al.get(i);
+                }
+            }
+
+            Mean m = new Mean();
+            DecimalFormat df = new DecimalFormat();
+            df.setMaximumFractionDigits(3);
+            DecimalFormatSymbols dfs = new DecimalFormatSymbols();
+            dfs.setDecimalSeparator('.');
+            df.setDecimalFormatSymbols(dfs);
+            return df.format(m.evaluate(d));
+        } else {
+            return "";
+        }
+    }
+
+}