Sleipnir
tools/BNServer/dot.cpp
00001 /*****************************************************************************
00002 * This file is provided under the Creative Commons Attribution 3.0 license.
00003 *
00004 * You are free to share, copy, distribute, transmit, or adapt this work
00005 * PROVIDED THAT you attribute the work to the authors listed below.
00006 * For more information, please see the following web page:
00007 * http://creativecommons.org/licenses/by/3.0/
00008 *
00009 * This file is a component of the Sleipnir library for functional genomics,
00010 * authored by:
00011 * Curtis Huttenhower (chuttenh@princeton.edu)
00012 * Mark Schroeder
00013 * Maria D. Chikina
00014 * Olga G. Troyanskaya (ogt@princeton.edu, primary contact)
00015 *
00016 * If you use this library, the included executable tools, or any related
00017 * code in your work, please cite the following publication:
00018 * Curtis Huttenhower, Mark Schroeder, Maria D. Chikina, and
00019 * Olga G. Troyanskaya.
00020 * "The Sleipnir library for computational functional genomics"
00021 *****************************************************************************/
00022 #include "stdafx.h"
00023 #include "dot.h"
00024 
00025 #define JAVASCRIPT_DIR  "../javascripts/"
00026 
00027 using namespace boost;
00028 
00029 const float CDot::c_dEdgeOpacity    = 0.13f;
00030 const float CDot::c_dScale          = 36;
00031 const char  CDot::c_szHeader00[]    =
00032     "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
00033     "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n"
00034     "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
00035     "   xmlns:a3=\"http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/\"\n"
00036     "   a3:scriptImplementation=\"Adobe\"\n"
00037     "   onload=\"init( )\"\n"
00038     "   viewBox=\"-20 -5 ";
00039 const char  CDot::c_szHeader01[]    = "\"\n"
00040     "   width=\"100%\" height=\"100%\"\n"
00041     "   >\n"
00042     "   <script a3:scriptImplementation=\"Adobe\" type=\"text/ecmascript\" xlink:href=\"" JAVASCRIPT_DIR "/helper_functions.js\" />\n"
00043     "   <script a3:scriptImplementation=\"Adobe\" type=\"text/ecmascript\" xlink:href=\"" JAVASCRIPT_DIR "/mapApp.js\" />\n"
00044     "   <script a3:scriptImplementation=\"Adobe\" type=\"text/ecmascript\" xlink:href=\"" JAVASCRIPT_DIR "/simple.js\" />\n"
00045     "   <g id=\"graph\" class=\"graph\" style=\"font-family:Times-Roman;font-size:12pt\" context=\"";
00046 const char  CDot::c_szHeader02[]    = "\">\n"
00047     "       <title>G</title>\n";
00048 const char  CDot::c_szCutoffBox[]   =
00049     "       <g id=\"cutoff_control_box\">\n"
00050     "           <g transform=\"scale(0.5)\">\n"
00051     "               <rect x=\"-10\" y=\"-10\" width=\"40\" height=\"32\"\n"
00052     "                   fill=\"white\" stroke=\"none\" />\n"
00053     "               <path id=\"cutoff_uparrow\"\n"
00054     "                   stroke-antialiasing=\"true\"\n"
00055     "                   stroke=\"black\" fill=\"cyan\"\n"
00056     "                   d=\"M -5 32 L 25 32 L 10 10 z\" />\n"
00057     "               <rect x=\"-10\" y=\"43\" width=\"40\" height=\"32\"\n"
00058     "                   fill=\"white\" stroke=\"none\" />\n"
00059     "               <path id=\"cutoff_downarrow\"\n"
00060     "                   stroke-antialiasing=\"true\"\n"
00061     "                   stroke=\"black\" fill=\"cyan\"\n"
00062     "                   d=\"M -5 48 L 25 48 L 10 70 z\" />\n"
00063     "               <rect x=\"-15\" y=\"0\" width=\"50\" height=\"80\"\n"
00064     "                   fill=\"none\" stroke-linejoin=\"round\"\n"
00065     "                   stroke-width=\"1\" stroke=\"black\" />\n"
00066     "           </g>\n"
00067     "           <text x=\"20\" y=\"15\"\n"
00068     "               font-family=\"Helvetica\" font-size=\"14\">\n"
00069     "               Cutoff value:\n"
00070     "           </text>\n"
00071     "           <g id=\"cutoff_value_text\" x=\"20\" y=\"35\" />\n"
00072     "       </g>\n";
00073 
00074 bool CDot::Open( const char* szDot ) {
00075     ifstream    ifsm;
00076     bool        fRet;
00077 
00078     m_pProperties->property( "node_id", get( vertex_name, m_Graph ) );
00079     m_pProperties->property( "pos", get( vertex_attribute, m_Graph ) );
00080     m_pProperties->property( "width", get( vertex_index1, m_Graph ) );
00081     m_pProperties->property( "height", get( vertex_index2, m_Graph ) );
00082     m_pProperties->property( "pos", get( edge_attribute, m_Graph ) );
00083     ifsm.open( szDot );
00084     if( !( fRet = ( ifsm.is_open( ) && read_graphviz( ifsm, m_Graph, *m_pProperties ) ) ) )
00085         cerr << "Could not open: " << szDot << endl;
00086 
00087     return fRet; }
00088 
00089 bool CDot::Save( ostream& ostm, const vector<bool>& vecfQuery, size_t iContext ) const {
00090     graph_traits<TGraph>::edge_iterator     iterEdge, iterEdgeEnd;
00091     graph_traits<TGraph>::vertex_iterator   iterVertex, iterVertexEnd;
00092     size_t                                  iMaxX, iMaxY, iCurX, iCurY;
00093 
00094     ostm << c_szHeader00;
00095     iMaxX = iMaxY = 0;
00096     for( tie( iterVertex, iterVertexEnd ) = vertices( m_Graph ); iterVertex != iterVertexEnd; ++iterVertex ) {
00097         string          strPos;
00098         float           dWidth, dHeight;
00099         vector<string>  vecstrPos;
00100 
00101         dWidth = (float)atof( get( "width", *m_pProperties, *iterVertex ).c_str( ) );
00102         dHeight = (float)atof( get( "height", *m_pProperties, *iterVertex ).c_str( ) );
00103         strPos = get( "pos", *m_pProperties, *iterVertex );
00104         CMeta::Tokenize( strPos.c_str( ), vecstrPos, "," );
00105         if( vecstrPos.size( ) != 2 )
00106             continue;
00107         iCurX = atoi( vecstrPos[ 0 ].c_str( ) ) + (size_t)( c_dScale * dWidth );
00108         iCurY = atoi( vecstrPos[ 1 ].c_str( ) ) + (size_t)( c_dScale * dHeight );
00109         if( iCurX > iMaxX )
00110             iMaxX = iCurX;
00111         if( iCurY > iMaxY )
00112             iMaxY = iCurY; }
00113     ostm << ( iMaxX + 5 ) << ' ' << ( iMaxY + 5 );
00114     ostm << c_szHeader01 << iContext << c_szHeader02;
00115 
00116     ostm << "       <g id=\"edges\" class=\"edgeList\">" << endl;
00117     for( tie( iterEdge, iterEdgeEnd ) = edges( m_Graph ); iterEdge != iterEdgeEnd; ++iterEdge )
00118         if( !SaveEdge( ostm, *iterEdge ) )
00119             return false;
00120     ostm << "       </g>" << endl;
00121 
00122     ostm << "       <g id=\"nodes\" class=\"nodeList\">" << endl;
00123     for( tie( iterVertex, iterVertexEnd ) = vertices( m_Graph ); iterVertex != iterVertexEnd; ++iterVertex )
00124         if( !SaveVertex( ostm, *iterVertex, vecfQuery ) )
00125             return false;
00126     ostm << "       </g>" << endl;
00127 
00128 //  ostm << c_szCutoffBox;
00129     ostm << "   </g>" << endl << "</svg>" << endl;
00130 
00131     return true; }
00132 
00133 bool CDot::SaveEdge( ostream& ostm, const TEdge& Edge ) const {
00134     static const char   c_acTabs[]  = "         ";
00135     static const size_t c_iBuffer   = 16;
00136     char            acBuffer[ c_iBuffer ];
00137     size_t          i, iHead, iTail;
00138     float           dWeight;
00139     string          strPath;
00140     vector<string>  vecstrPath;
00141 
00142     iHead = source( Edge, m_Graph );
00143     iTail = target( Edge, m_Graph );
00144     if( iTail < iHead ) {
00145         i = iHead;
00146         iHead = iTail;
00147         iTail = i; }
00148     if( CMeta::IsNaN( dWeight = m_Dat.Get( iHead, iTail ) ) ) {
00149         cerr << "CDot::SaveEdge( ) no edge found for: " << iHead << " (" << m_Dat.GetGene( iHead ) << "), " <<
00150             iTail << " (" << m_Dat.GetGene( iTail ) << ')' << endl;
00151         return false; }
00152     sprintf_s( acBuffer, "%d_%d", iHead, iTail );
00153 
00154     strPath = get( "pos", *m_pProperties, Edge );
00155     CMeta::Tokenize( strPath.c_str( ), vecstrPath, " " );
00156     if( vecstrPath.size( ) < 1 ) {
00157         cerr << "CDot::SaveEdge( ) no path found for: " << iHead << " (" << m_Dat.GetGene( iHead ) << "), " <<
00158             iTail << " (" << m_Dat.GetGene( iTail ) << ')' << endl;
00159         return false; }
00160     strPath = "M";
00161     strPath += vecstrPath[ 0 ];
00162     for( i = 1; i < vecstrPath.size( ); ++i )
00163         strPath += ( ( i == 1 ) ? "C" : " " ) + vecstrPath[ i ];
00164 
00165     ostm <<
00166         c_acTabs << "<g id=\"edge" << acBuffer << "\" class=\"edge\" stroke-opacity=\"" <<
00167             c_dEdgeOpacity << "\">" << endl <<
00168         c_acTabs << "   <title>" << iHead << "--" << iTail << "--" << dWeight << "</title>" << endl <<
00169         c_acTabs << "   <text display=\"none\" id=\"edge" << acBuffer << "_confidence\">" << dWeight <<
00170             "</text>" << endl <<
00171         c_acTabs << "   <g id=\"edge" << acBuffer << "_nodes\" display=\"none\">" << endl <<
00172         c_acTabs << "       <text>node" << iHead << "</text>" << endl <<
00173         c_acTabs << "       <text>node" << iTail << "</text>" << endl <<
00174         c_acTabs << "   </g>" << endl <<
00175         c_acTabs << "   <path style=\"fill:none;stroke:#" << CColor::Interpolate( dWeight, CColor::c_Green,
00176             CColor::c_Black, CColor::c_Red ).ToRGB( ) << ";stroke-width:3;\" d=\"" + strPath + "\" />" <<
00177             endl <<
00178         c_acTabs << "</g>" << endl;
00179 
00180     return true; }
00181 
00182 bool CDot::SaveVertex( ostream& ostm, const TVertex& Vertex, const vector<bool>& vecfQuery ) const {
00183     static const char   c_acTabs[]  = "         ";
00184     static const size_t c_iBuffer   = 16;
00185     char                                    acBuffer[ c_iBuffer ];
00186     graph_traits<TGraph>::out_edge_iterator iterEdge, iterEdgeEnd;
00187     string                                  strID, strPos, strCX, strCY, strRX, strRY;
00188     string                                  strForeground, strBackground;
00189     size_t                                  i;
00190     float                                   dWidth, dHeight;
00191     vector<string>                          vecstrPos;
00192 
00193     strID = get( "node_id", *m_pProperties, Vertex );
00194     dWidth = (float)atof( get( "width", *m_pProperties, Vertex ).c_str( ) );
00195     dHeight = (float)atof( get( "height", *m_pProperties, Vertex ).c_str( ) );
00196     strPos = get( "pos", *m_pProperties, Vertex );
00197     CMeta::Tokenize( strPos.c_str( ), vecstrPos, "," );
00198     if( vecstrPos.size( ) != 2 )
00199         return false;
00200     strCX = vecstrPos[ 0 ];
00201     strCY = vecstrPos[ 1 ];
00202     sprintf_s( acBuffer, "%d", (size_t)( c_dScale * dWidth ) );
00203     strRX = acBuffer;
00204     sprintf_s( acBuffer, "%d", (size_t)( c_dScale * dHeight ) );
00205     strRY = acBuffer;
00206 
00207     ostm <<
00208         c_acTabs << "<g id=\"node" << Vertex << "\" class=\"node\" gene=\"" << m_Dat.GetGene( Vertex ) <<
00209             "\">" << endl <<
00210         c_acTabs << "   <title>" << m_Dat.GetGene( Vertex ) << "</title>" << endl <<
00211         c_acTabs << "   <g id=\"node" << Vertex << "_edges\" display=\"none\">" << endl;
00212     for( tie( iterEdge, iterEdgeEnd ) = out_edges( Vertex, m_Graph ); iterEdge != iterEdgeEnd; ++iterEdge ) {
00213         size_t  iHead, iTail;
00214 
00215         iHead = source( *iterEdge, m_Graph );
00216         iTail = target( *iterEdge, m_Graph );
00217         if( iTail < iHead ) {
00218             i = iHead;
00219             iHead = iTail;
00220             iTail = i; }
00221         ostm << c_acTabs << "       <text>edge" << iHead << '_' << iTail << "</text>" << endl; }
00222     ostm << c_acTabs << "   </g>" << endl;
00223 
00224     strForeground = "black";
00225     strBackground = vecfQuery[ Vertex ] ? "lightgrey" : "white";
00226     ostm <<
00227         c_acTabs << "   <ellipse cx=\"" << strCX << "\" cy=\"" << strCY << "\" rx=\"" << strRX <<
00228             "\" ry=\"" << strRY << "\" style=\"fill:" << strBackground << ";stroke:black\" />" << endl <<
00229         c_acTabs << "   <text id=\"node" << Vertex << "_title\" text-anchor=\"middle\" style=\"fill:" <<
00230             strForeground << ";stroke:" << strForeground << "\" x=\"" << strCX << "\" y=\"" <<
00231             ( atof( strCY.c_str( ) ) + 5 ) << "\">" << m_Dat.GetGene( Vertex ) << "</text>" << endl <<
00232         c_acTabs << "</g>" << endl;
00233 
00234     return true; }