@@ -2101,6 +2101,26 @@ void InfomapBase::writeResult()
21012101 }
21022102
21032103
2104+ if (printNewick) {
2105+ std::string filename = outDirectory + outName + " .tre" ;
2106+
2107+ if (!haveMemory ()) {
2108+ Log () << " Write Newick tree to " << filename << " ... " ;
2109+ writeNewickTree (filename);
2110+ Log () << " done!\n " ;
2111+ } else {
2112+ // Write both physical and state level
2113+ Log () << " Write physical Newick tree to " << filename << " ... " ;
2114+ writeNewickTree (filename, false );
2115+ Log () << " done!\n " ;
2116+ std::string filenameStates = outDirectory + outName + " _states.tre" ;
2117+ Log () << " Write state Newick tree to " << filenameStates << " ... " ;
2118+ writeNewickTree (filenameStates, true );
2119+ Log () << " done!\n " ;
2120+ }
2121+ }
2122+
2123+
21042124 if (printClu) {
21052125 std::string filename = outDirectory + outName + " .clu" ;
21062126 if (!haveMemory ()) {
@@ -2153,6 +2173,16 @@ std::string InfomapBase::writeFlowTree(std::string filename, bool states)
21532173 return outputFilename;
21542174}
21552175
2176+ std::string InfomapBase::writeNewickTree (std::string filename, bool states)
2177+ {
2178+ std::string outputFilename = filename.empty () ? outDirectory + outName + (haveMemory () && states ? " _states.tre" : " .tre" ) : filename;
2179+
2180+ SafeOutFile outFile (outputFilename);
2181+ writeNewickTree (outFile, states);
2182+
2183+ return outputFilename;
2184+ }
2185+
21562186std::string InfomapBase::writeClu (std::string filename, bool states, int moduleIndexLevel)
21572187{
21582188 // unsigned int maxModuleLevel = maxTreeDepth();
@@ -2400,6 +2430,60 @@ void InfomapBase::writeTreeLinks(std::ostream& outStream, bool states)
24002430}
24012431
24022432
2433+ void InfomapBase::writeNewickTree (std::ostream& outStream, bool states)
2434+ {
2435+ auto oldPrecision = outStream.precision ();
2436+ // outStream << std::setprecision(9);
2437+ // outStream << getOutputFileHeader() << "\n";
2438+ outStream << std::setprecision (6 );
2439+
2440+ auto isRoot = true ;
2441+ unsigned int lastDepth = 0 ;
2442+ std::vector<double > flowStack;
2443+
2444+ auto writeNewickNode = [&](std::ostream& o, const InfoNode& node, unsigned int depth) {
2445+ if (depth > lastDepth || isRoot) {
2446+ outStream << " (" ;
2447+ flowStack.push_back (node.data .flow );
2448+ if (node.isLeaf ())
2449+ outStream << (states ? node.stateId : node.physicalId ) << " :" << node.data .flow ;
2450+ } else if (depth == lastDepth) {
2451+ outStream << " ," ;
2452+ flowStack[flowStack.size ()-1 ] = node.data .flow ;
2453+ if (node.isLeaf ()) {
2454+ outStream << (states ? node.stateId : node.physicalId ) << " :" << node.data .flow ;
2455+ }
2456+ } else {
2457+ // depth < lastDepth
2458+ while (flowStack.size () > depth + 1 ) {
2459+ flowStack.pop_back ();
2460+ outStream << " ):" << flowStack.back ();
2461+ }
2462+ flowStack[flowStack.size ()-1 ] = node.data .flow ;
2463+ outStream << " ," ;
2464+ }
2465+ lastDepth = depth;
2466+ isRoot = false ;
2467+ };
2468+
2469+ // TODO: Make a general iterator where merging physical nodes depend on a parameter rather than type to be able to DRY here
2470+ if (haveMemory () && !states) {
2471+ for (auto it (iterTreePhysical ()); !it.isEnd (); ++it) {
2472+ writeNewickNode (outStream, *it, it.depth ());
2473+ }
2474+ } else {
2475+ for (auto it (iterTree ()); !it.isEnd (); ++it) {
2476+ writeNewickNode (outStream, *it, it.depth ());
2477+ }
2478+ }
2479+ while (flowStack.size () > 1 ) {
2480+ flowStack.pop_back ();
2481+ outStream << " ):" << flowStack.back ();
2482+ }
2483+ outStream << " );\n " ;
2484+ outStream << std::setprecision (oldPrecision);
2485+ }
2486+
24032487unsigned int InfomapBase::printPerLevelCodelength (std::ostream& out)
24042488{
24052489 std::vector<PerLevelStat> perLevelStats;
0 commit comments