/*************************************************************************
* *
* This file is part of the 20n/act project. *
* 20n/act enables DNA prediction for synthetic biology/bioengineering. *
* Copyright (C) 2017 20n Labs, Inc. *
* *
* Please direct all queries to act@20n.com. *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
*************************************************************************/
package com.act.reachables;
import org.apache.commons.lang3.tuple.Pair;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
public class ActData implements Serializable {
private static final long serialVersionUID = -1016179639411233872L;
ConditionalReachable _LastReachabilityComputation = null;
Network Act;
Network ActTree;
List<Long> allrxnids; // sorted list of all reaction uuids (from db.actfamilies)
Set<Long> chemsReferencedInRxns; // every chemid referenced in cofactors, natives, or any reaction in DB
Set<Long> cofactors; // chemicals with isCofactor : true in DB
Set<Long> natives; // chemicals marked as isNative : true in DB
Set<Long> metaCycBigMolsOrRgrp; // chemicals whose inchi matches db.chemicals.find({InChI:/FAKE/})
HashMap<String, List<Long>> chemicalsWithUserField; // if a user asks us to output an artificial
// subset of chemicals that have certain fields,
// e.g., xref.CHEBI, xref.DEA etc.
Set<Long> chemicalsWithUserField_treeOrganic; // in the final tree; these nodeMapping were reachable organically
Set<Long> chemicalsWithUserField_treeArtificial; // in the final tree; these nodeMapping were added artificially as
// they were not organically reachable
HashMap<Long, Boolean> chemIdIsAbstraction; // the chemicals that have R in inchis and therefore abstractions
HashMap<Long, String> chemId2Inchis; // map chemid -> inchi
HashMap<Long, String> chemId2ReadableName; // map chemid -> name
HashMap<String, Long> chemInchis; // reverse index of inchi -> chemid
HashMap<Long, Set<Integer>> chemToxicity; // If the chemical has xref.DRUGBANK.metadata.toxicity with LD50 [1]
HashMap<Long, Node> chemsInAct; // map of chemicals seen in any rxn -> its node object in network
HashMap<Pair<Long, Long>, Edge> rxnsInAct; // map of rxns (exploded to all pairs bw sub x prod) to edge in network
HashMap<Long, Set<Long>> rxnSubstrates; // rxnid -> non-cofactor substrates
HashMap<Long, Set<Long>> rxnSubstratesCofactors; // rxnid -> cofactor substrates
HashMap<Long, Set<Long>> rxnProducts; // rxnid -> non-cofactor products
HashMap<Long, Set<Long>> rxnProductsCofactors; // rxnid -> cofactor products
HashMap<Long, Set<Long>> rxnOrganisms; // rxnid -> set of organism ids associated with rxn
HashMap<Long, Set<Long>> rxnsThatConsumeChem; // non-cofactor chemicals -> rxns that have them as substrates
HashMap<Long, Set<Long>> rxnsThatProduceChem; // non-cofactor chemicals -> rxns that have them as products
HashMap<Long, Boolean> rxnHasSeq; // do we know an enzyme catalyzing this rxn?
// The raw dataset comes in with multiple reactions
// with the same chemistry, i.e., the same substrates
// and products. Since reactions with the same chemistry
// will be semantically equivalent in the reachables computation
// i.e., they will lead to the same expansion, we call them
// a class, where a class is defined as P(substrate_set, product_set)
// (see LoadAct.addToNw where we create and use this "class id")
//
// The expansion code picks between raw rxns or classes
// on the basis of the parameter GlobalParams.USE_RXN_CLASSES
//
// Expansion in WavefrontExpansion.{computeRxnNeeds, productsOf},
// picks either the classes or the raw rxns to expand over.
//
// The first three below are used in LoadAct and WavefrontExpansion
// and the remaining two are for when we are dumping out cascade
// metadata in scala/reachables.scala
HashMap<Long, Set<Long>> rxnClassesSubstrates; // rxnid -> non-cofactor substrates (representative rxns that form classes)
HashMap<Long, Set<Long>> rxnClassesProducts; // rxnid -> non-cofactor products (representative rxns that form classes)
Set<Pair<Set<Long>, Set<Long>>> rxnClasses; // set for classes (substrates, products)
HashMap<Long, Set<Long>> rxnClassesThatConsumeChem; // non-cofactor chemicals -> rxns that have them as substrates
HashMap<Long, Set<Long>> rxnClassesThatProduceChem; // non-cofactor chemicals -> rxns that have them as products
HashMap<Long, List<Long>> noSubstrateRxnsToProducts; // product rxns that only depend on cofactors
/* Hack to work around the fact that static fields don't get serialized. Edge and Node both now call
* ActData.instance() a lot, which is gross but hopefully functional. */
HashMap<Long, List<Node>> nodeCache = new HashMap<>();
HashMap<Long, HashMap<String, Serializable>> nodeAttributes = new HashMap<>();
HashMap<Edge, Edge> edgeCache = new HashMap<>();
HashMap<Edge, HashMap<String, Serializable>> edgeAttributes = new HashMap<>();
private static ActData _instance = null;
public static ActData instance() {
if (ActData._instance == null)
ActData._instance = new ActData();
return ActData._instance;
}
public void serialize(String toFile) {
try {
OutputStream file = new FileOutputStream(toFile);
OutputStream buffer = new BufferedOutputStream(file);
ObjectOutput output = new ObjectOutputStream(buffer);
try {
output.writeObject(_instance);
} finally {
output.close();
}
} catch(IOException ex) {
throw new RuntimeException("ActData serialize failed: " + ex);
}
}
public void deserialize(String fromFile) {
try {
InputStream file = new FileInputStream(fromFile);
InputStream buffer = new BufferedInputStream(file);
ObjectInput input = new ObjectInputStream (buffer);
try {
ActData._instance = (ActData)input.readObject();
} finally {
input.close();
}
} catch(ClassNotFoundException ex) {
throw new RuntimeException("ActData deserialize failed: Class not found: " + ex);
} catch(IOException ex) {
throw new RuntimeException("ActData deserialize failed: IO problem: " + ex);
}
}
public Network getActTree() {
return this.ActTree;
}
public String mapChemId2Inchis(Long id) {
return this.chemId2Inchis.get(id);
}
public String mapChemId2ReadableName(Long id) {
return this.chemId2ReadableName.get(id);
}
}