uk.ac.ebi.mdk.io.ReactionMatrixIO.java Source code

Java tutorial

Introduction

Here is the source code for uk.ac.ebi.mdk.io.ReactionMatrixIO.java

Source

/*
 * Copyright (c) 2013. EMBL, European Bioinformatics Institute
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 *     This file is part of Metabolic Network Builder
 *
 *     Metabolic Network Builder is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     Foobar is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
 */
package uk.ac.ebi.mdk.io;

import au.com.bytecode.opencsv.CSVReader;
import au.com.bytecode.opencsv.CSVWriter;
import org.apache.commons.lang.mutable.MutableInt;
import uk.ac.ebi.mdk.domain.identifier.InChI;
import uk.ac.ebi.mdk.domain.matrix.StoichiometricMatrix;

import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * <h3>ReactionMatrixIO.java  MetabolicDevelopmentKit  Jun 28, 2011</h3> A
 * Reader/Writer class for Reaction Matrices. The class uses the OpenCSV library
 * for the reading/writing to streams. <br> <h4>Example:</h4>
 * <pre>
 * {@code
 * File tmp = File.createTempFile( "smatrix" , "tsv" );
 * BasicStoichiometricMatrix sout = new BasicStoichiometricMatrix();
 * sout.addReaction( "A => B" );
 * sout.addReaction( "B => C" );
 * sout.addReaction( "C => A" );
 * ReactionMatrixIO.writeBasicStoichiometricMatrix( sout , new FileWriter( tmp ) , '\t' );
 * BasicStoichiometricMatrix sin = ReactionMatrixIO.readBasicStoichiometricMatrix( new FileReader( tmp ) , '\t' );
 * sin.display( System.out );
 * }
 * </pre>
 *
 * @author johnmay
 */
public class ReactionMatrixIO {

    private static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(ReactionMatrixIO.class);

    private static char separator = '\t';

    private static char quoteCharacter = '\0';

    private static boolean convertDoubles = true;

    /**
     * Invoking method informers writer methods to convert double value to
     * integers
     *
     * @param convert
     */
    public static void setConvertDoubleToInChI(boolean convert) {
        ReactionMatrixIO.convertDoubles = convert;
    }

    /**
     * @param separator
     *
     * @brief Sets the separator character used to delimit fields (default:
     * '\t')
     */
    public static void setSeparator(char separator) {
        ReactionMatrixIO.separator = separator;
    }

    /**
     * @brief Sets the quote character for writing (default: '\0')
     */
    public static void setQuoteCharacter(char quoteCharacter) {
        ReactionMatrixIO.quoteCharacter = quoteCharacter;
    }

    /**
     * Reads a matrix from a file, stream et al.
     *
     * @param reader Reader object to read from
     *
     * @return
     */
    public static StoichiometricMatrix readBasicStoichiometricMatrix(Reader reader, StoichiometricMatrix s) {
        CSVReader csv = new CSVReader(reader, separator, quoteCharacter);
        try {

            // grab the whole matrix
            List<String[]> matrix = csv.readAll();
            // we know the size so can specify this
            s.ensure(matrix.size() - 1, matrix.get(0).length - 1);

            String[] molNames = new String[matrix.size() - 1];
            // get the molecule names
            for (int i = 1; i < matrix.size(); i++) {
                molNames[i - 1] = matrix.get(i)[0];
            }

            String[] reactionNames = new String[matrix.get(0).length - 1];
            // get the molecule names
            for (int j = 1; j < matrix.get(0).length; j++) {
                reactionNames[j - 1] = matrix.get(0)[j];
            }

            // add the reactions
            for (int j = 0; j < reactionNames.length; j++) {
                HashMap<String, Double> molValueMap = new HashMap<String, Double>();
                for (int i = 0; i < molNames.length; i++) {
                    String value = matrix.get(i + 1)[j + 1];
                    // if the value isn't empty
                    if (value.isEmpty() == false) {
                        molValueMap.put(molNames[i], Double.parseDouble(value));
                    }
                }
                s.addReaction(reactionNames[j], molValueMap.keySet().toArray(new String[0]),
                        molValueMap.values().toArray(new Double[0]));
            }

        } catch (IOException ex) {
            logger.error("Unable to read from the CSV: " + reader);
        } finally {
            try {
                csv.close();
            } catch (IOException ex) {
                logger.error("Could not close CSVReader");
            }
        }

        return s;
    }

    public static StoichiometricMatrix readCompressedBasicStoichiometricMatrix(InputStream stream,
            StoichiometricMatrix s) throws IOException {

        DataInputStream in = new DataInputStream(stream);

        int n = in.readInt();
        int m = in.readInt();

        s.ensure(n, m);

        for (int j = 0; j < m; j++) {
            s.setReaction(j, in.readUTF());
        }

        for (int i = 0; i < n; i++) {
            s.setMolecule(i, in.readUTF());
        }

        boolean convert = in.readBoolean();
        int size = in.readInt();

        while (--size >= 0) {

            int i = in.readInt();
            int j = in.readInt();
            Object value = convert ? in.readInt() : in.readDouble();
            Double dValue = value instanceof Double ? (Double) value : ((Integer) value).doubleValue();
            s.setValue(i, j, dValue);
        }

        in.close();

        return s;

    }

    //    public static InChIStoichiometricMatrix readInChIStoichiometricMatrix(Reader reader) {
    //        CSVReader csv = new CSVReader(reader, separator, quoteCharacter);
    //        InChIStoichiometricMatrix s = null;
    //        try {
    //
    //            // grab the whole matrix
    //            List<String[]> matrix = csv.readAll();
    //            // we know the size so can specify this
    //            s = InChIStoichiometricMatrix.create(matrix.size() - 1,
    //                                                 matrix.get(0).length - 1);
    //
    //            InChI[] molNames = new InChI[matrix.size() - 1];
    //            // get the molecule names
    //            for (int i = 1; i < matrix.size(); i++) {
    //                molNames[i - 1] = new InChI(matrix.get(i)[0]);
    //            }
    //
    //            ECNumber[] reactionNames = new ECNumber[matrix.get(0).length - 1];
    //            // get the molecule names
    //            for (int j = 1; j < matrix.get(0).length; j++) {
    //                reactionNames[j - 1] = new ECNumber(matrix.get(0)[j]);
    //            }
    //
    //            // add the reactions
    //            for (int j = 0; j < reactionNames.length; j++) {
    //                HashMap<InChI, Double> molValueMap = new HashMap<InChI, Double>();
    //                for (int i = 0; i < molNames.length; i++) {
    //                    String value = matrix.get(i + 1)[j + 1];
    //                    // if the value isn't empty
    //                    if (value.isEmpty() == false) {
    //                        molValueMap.put(molNames[i], Double.parseDouble(value));
    //                    }
    //                }
    //                s.addReaction(reactionNames[j],
    //                              molValueMap.keySet().toArray(new InChI[0]),
    //                              molValueMap.values().toArray(new Double[0]));
    //            }
    //
    //
    //        } catch (IOException ex) {
    //            logger.error("Unable to read from the CSV: " + reader);
    //        } finally {
    //            try {
    //                csv.close();
    //            } catch (IOException ex) {
    //                logger.error("Could not close CSVReader");
    //            }
    //        }
    //
    //        return s;
    //    }

    /**
     * @param s       Class extending Stoichiometric matrix to write
     * @param writer - Where to write the matrix too
     *
     * @brief Writes a Stoichiometric Matrix (s) using the {@code toString()}
     * method of the molecule object to print the row name. Invoking {
     * <p/>
     * doubles as integers. Note: the writer is not closed on completion
     */
    public static void writeBasicStoichiometricMatrix(StoichiometricMatrix<?, ?> s, Writer writer)
            throws IOException {
        CSVWriter csv = new CSVWriter(new BufferedWriter(writer), separator, quoteCharacter);

        int n = s.getMoleculeCount();
        int m = s.getReactionCount();

        String[] reactionName = new String[s.getReactionCount() + 1];
        for (int j = 0; j < s.getReactionCount(); j++) {
            reactionName[j + 1] = s.getReaction(j).toString();
        }
        csv.writeNext(reactionName);

        for (int i = 0; i < n; i++) {
            String[] copy = new String[m + 1];
            copy[0] = s.getMolecule(i).toString();
            for (int j = 0; j < m; j++) {
                // if the value is null
                copy[j + 1] = convertDoubles ? Integer.toString(s.get(i, j).intValue()) : s.get(i, j).toString();
            }
            csv.writeNext(copy);
        }

        csv.close();

    }

    public static void writeCompressedBasicStoichiometricMatrix(StoichiometricMatrix<?, ?> s, OutputStream writer)
            throws IOException {

        DataOutputStream out = new DataOutputStream(new BufferedOutputStream(writer, 2048));

        int n = s.getMoleculeCount();
        int m = s.getReactionCount();

        out.writeInt(n);
        out.writeInt(m);

        for (int j = 0; j < m; j++) {
            out.writeUTF(s.getReaction(j).toString());
        }

        for (int i = 0; i < n; i++) {
            out.writeUTF(s.getMolecule(i).toString());
        }

        out.writeBoolean(convertDoubles);
        out.writeInt(s.getNonNullCount());

        for (int i = 0; i < n; i++) {

            for (int j = 0; j < m; j++) {

                // if the value is null
                if (convertDoubles) {
                    int value = s.get(i, j).intValue();
                    if (value != 0) {
                        out.writeInt(i);
                        out.writeInt(j);
                        out.writeInt(value);
                    }
                } else {
                    double value = s.get(i, j);
                    if (value != 0d) {
                        out.writeInt(i);
                        out.writeInt(j);
                        out.writeDouble(value);
                    }
                }

            }
        }

        out.close();
    }

    /**
     * Writes a sif file (openable with Cytoscape)
     *
     * @param s
     * @param writer
     * @param connectionThreshold
     * @param <R>
     * @param <M>
     *
     * @throws IOException
     */
    public static <R, M> void writeSIF(StoichiometricMatrix<M, R> s, Writer writer, Integer connectionThreshold)
            throws IOException {

        Set<M> highlyConnected = s.getHighlyConnectedMolecules(connectionThreshold);
        Map<M, MutableInt> suffixValue = new HashMap<M, MutableInt>();

        for (M molecule : s.getMolecules()) {

            Map<Integer, Double> reactionMap = s.getReactions(molecule);
            for (Integer i : reactionMap.keySet()) {

                String nodeName = molecule.toString();

                if (highlyConnected.contains(molecule)) {

                    if (!suffixValue.containsKey(molecule)) {
                        suffixValue.put(molecule, new MutableInt(0));
                    }

                    suffixValue.get(molecule).increment();

                    nodeName = nodeName + " " + suffixValue.get(molecule).toString();
                }

                nodeName = nodeName.replaceAll("\\s+", " ");
                nodeName = nodeName.replaceAll("\\s", "_");
                writer.write(s.getReaction(i) + "\t" + "r" + "\t" + nodeName + "\n");

            }

        }

    }

    /**
     * @param s      - A stoichiometric matrix
     * @param writer
     *
     * @brief Writes the InChI additional info, molecule index, inchi, inchikey
     * and auxinfo
     */
    public static void writeInChIAdditionalInfo(StoichiometricMatrix s, Writer writer) {

        CSVWriter csv = new CSVWriter(new BufferedWriter(writer), separator, quoteCharacter);

        int n = s.getMoleculeCount();

        for (Integer i = 0; i < n; i++) {
            Object obj = s.getMolecule(i);
            if (obj instanceof InChI) {
                InChI inchi = (InChI) obj;
                csv.writeNext(
                        new String[] { i.toString(), inchi.getInchi(), inchi.getInchiKey(), inchi.getAuxInfo() });
            } else {
                logger.error("Object is not of type and does not inherit from InChI in matrix array");
            }
        }

    }
}