bool StateGraph::isValid(const IntPairSet& L, const StlBoolMatrix& LL, const SubDigraph& T, const StlIntMatrix& V) const { for (IntPairSetIt it = L.begin(); it != L.end(); ++it) { int x = it->first; int y = it->second; if (V[x][y] == 0) return false; } // check #2: all leaves are in L for (SubNodeIt v(T); v != lemon::INVALID; ++v) { bool leaf = SubOutArcIt(T, v) == lemon::INVALID; if (leaf && !LL[_x[v]][_y[v]]) { return false; } } return true; }
int StateGraph::enumerate(const IntPairSet& L, bool includeMutationEdge) { BoolNodeMap filterNodesT(_G, false); BoolArcMap filterArcsT(_G, false); SubDigraph T(_G, filterNodesT, filterArcsT); BoolNodeMap filterNodesG(_G, true); BoolArcMap filterArcsG(_G, true); SubDigraph subG(_G, filterNodesG, filterArcsG); ArcList F; init(includeMutationEdge, subG, T, F); Arc a = lemon::INVALID; StlIntMatrix V(_max_x+1, StlIntVector(_max_x+1, 0)); V[1][1] = 1; StlBoolMatrix LL(_max_x+1, StlBoolVector(_max_x+1, false)); for (IntPairSetIt it = L.begin(); it != L.end(); ++it) { int x = it->first; int y = it->second; LL[x][y] = true; } _result.clear(); grow(L, LL, includeMutationEdge, subG, T, F, V, a); return _result.size(); }
int main(int argc, char** argv) { int size = -1; std::string filterString; int verbosityLevel = 1; int cliqueLimit = -1; lemon::ArgParser ap(argc, argv); ap.boolOption("-version", "Show version number") .refOption("v", "Verbosity level (default: 1)", verbosityLevel) .refOption("s", "Maximal clique size (default: -1 (maximum))", size) .refOption("f", "Filter (default : \"\")", filterString) .refOption("l", "Clique limit (default : -1 (unlimited))", cliqueLimit) .other("input", "Input file"); ap.parse(); g_verbosity = static_cast<VerbosityLevel>(verbosityLevel); if (ap.given("-version")) { std::cout << "Version number: " << SPRUCE_VERSION << std::endl; return 0; } if (ap.files().size() == 0) { std::cerr << "Error: missing input file" << std::endl; return 1; } const std::string& inputFilename(ap.files()[0]); std::ifstream inFile(inputFilename.c_str()); if (!inFile.good()) { std::cerr << "Unable to open '" << inputFilename << "' for reading" << std::endl; return 1; } IntPairSet filter; IntSet whiteList; if (!filterString.empty()) { StringVector s; boost::split(s, filterString, boost::is_any_of(";")); for (const std::string& str : s) { StringVector ss; boost::split(ss, str, boost::is_any_of(",")); filter.insert(std::make_pair(boost::lexical_cast<int>(ss[0]), boost::lexical_cast<int>(ss[1]))); } } CharacterMatrix M; try { inFile >> M; } catch (std::runtime_error& e) { std::cerr << "File: '" << ap.files()[0].c_str() << "'. " << e.what() << std::endl; return 1; } M.init(); M.applyHeuristic(); CompatibilityGraph G(M); G.setCliqueLimit(cliqueLimit); G.init(filter, size); G.write(std::cout); return 0; }
void NoisyCnaEnumerate::collapse(const StlIntVector& mapNewCharToOldChar, const StlIntVector& mapOldCharToNewChar, RootedCladisticNoisyAncestryGraph& G) { typedef std::set<IntPair> IntPairSet; int k = _M.k(); const auto& intervals = _M.intervals(); for (const IntSet& interval : intervals) { IntSet remappedInterval; for (int c : interval) { int cc = mapOldCharToNewChar[c]; if (cc != -1) remappedInterval.insert(cc); } if (remappedInterval.size() > 1) { // get the copy states IntPairSet XY; const StateTree& S = G.S(*remappedInterval.begin()); for (int i = 0; i < k; ++i) { if (S.isPresent(i)) { const auto& xyz = _M.stateToTriple(i); // skip state 1,1 if (xyz._x != 1 || xyz._y != 1) { XY.insert(IntPair(xyz._x, xyz._y)); } } } for (const IntPair& xy : XY) { assert(xy.first != 1 || xy.second != 1); // collect all char-state pairs correspond to CNAs IntPairSet toCollapse; for (int c : remappedInterval) { const StateTree& S_c = G.S(c); for (int i = 0; i < k; ++i) { if (S_c.isPresent(i) && _M.stateToTriple(i)._x == xy.first && _M.stateToTriple(i)._y == xy.second) { int pi_i = S_c.parent(i); assert(0 <= pi_i && pi_i < k); if (_M.stateToTriple(pi_i)._x != xy.first || _M.stateToTriple(pi_i)._y != xy.second) { // we got a CNA state toCollapse.insert(IntPair(c, i)); } } } } G.collapse(toCollapse); } } } }
void NoisyCnaEnumerate::fixTrunk(const RealTensor& F_ub, const StateTreeVector& S, const StlIntVector& mapNewCharToOldChar, const StlIntVector& mapOldCharToNewChar, RootedCladisticNoisyAncestryGraph& G) { const int m = F_ub.m(); const int k = F_ub.k(); const int n = F_ub.n(); typedef std::set<IntPair> IntPairSet; IntPairSet truncalCharacters; for (int c = 0; c < n; ++c) { std::cerr << "Character " << _M(0, mapNewCharToOldChar[c]).characterLabel() << " (" << mapNewCharToOldChar[c] << ") : "; S[c].writeEdgeList(std::cerr); std::cerr << std::endl; bool truncal = true; int mutation_i = -1; for (int p = 0; p < m; ++p) { double ccf = 0; for (int i = 0; i < k; ++i) { if (!S[c].isPresent(i)) continue; const auto& xyz = _M.stateToTriple(i); if (xyz._z >= 1) { ccf += F_ub(i, p, c); const auto& pi_xyz = _M.stateToTriple(S[c].parent(i)); if (pi_xyz._z == 0 && xyz._z == 1) { mutation_i = i; } } } ccf /= _purityValues[p]; if (g_tol.less(ccf, 1)) { truncal = false; break; } } if (truncal) { assert(mutation_i != -1); const StateTree& S_c = S[c]; truncalCharacters.insert(IntPair(c, mutation_i)); while ((mutation_i = S_c.parent(mutation_i)) != 0) { truncalCharacters.insert(IntPair(c, mutation_i)); } } } std::cerr << "Truncal:" << std::endl; for (auto ci : truncalCharacters) { auto xyz = _M.stateToTriple(ci.second); std::cerr << _M(0, mapNewCharToOldChar[ci.first]).characterLabel() << " , (" << xyz._x << "," << xyz._y << "," << xyz._z << ")" << std::endl; } Digraph::Node monoClonalRoot = G.collapse(truncalCharacters); G.makeMonoclonal(monoClonalRoot); }