Commit 627eed8df6c5094b4678fc129722edd37c0999b5

Authored by David Mayerich
1 parent 18fad6bc

added a GUI for displaying networks

Showing 3 changed files with 387 additions and 28 deletions   Show diff stats
CMakeLists.txt
... ... @@ -21,6 +21,10 @@ endif(NOT STIM_INCLUDE_DIRS)
21 21 #find BOOST
22 22 find_package(Boost REQUIRED)
23 23  
  24 +#find the GLUT library for visualization
  25 +find_package(OpenGL REQUIRED)
  26 +find_package(GLUT REQUIRED)
  27 +
24 28 #find the pthreads package
25 29 find_package(Threads)
26 30  
... ... @@ -37,8 +41,10 @@ if ( MSVC )
37 41 endif ( MSVC )
38 42  
39 43 include_directories(
  44 + ${OpenGL_INCLUDE_DIRS}
  45 + ${GLUT_INCLUDE_DIR}
40 46 ${STIM_INCLUDE_DIRS}
41   - ${ANN_INCLUDE_DIR}
  47 + ${ANN_INCLUDE_DIR}
42 48 ${Boost_INCLUDE_DIR}
43 49 )
44 50  
... ... @@ -54,8 +60,10 @@ add_executable(netmets
54 60  
55 61 #set the link libraries
56 62 target_link_libraries(netmets
  63 + ${OpenGL_LIBRARIES}
  64 + ${GLUT_LIBRARIES}
57 65 ${CMAKE_THREAD_LIBS_INIT}
58   - ${ANN_LIBRARY}
  66 + ${ANN_LIBRARY}
59 67 ${X11_LIBRARIES}
60 68 )
61 69  
... ...
FindGLUT.cmake 0 → 100644
  1 +#.rst:
  2 +# FindGLUT
  3 +# --------
  4 +#
  5 +# try to find glut library and include files.
  6 +#
  7 +# IMPORTED Targets
  8 +# ^^^^^^^^^^^^^^^^
  9 +#
  10 +# This module defines the :prop_tgt:`IMPORTED` targets:
  11 +#
  12 +# ``GLUT::GLUT``
  13 +# Defined if the system has GLUT.
  14 +#
  15 +# Result Variables
  16 +# ^^^^^^^^^^^^^^^^
  17 +#
  18 +# This module sets the following variables:
  19 +#
  20 +# ::
  21 +#
  22 +# GLUT_INCLUDE_DIR, where to find GL/glut.h, etc.
  23 +# GLUT_LIBRARIES, the libraries to link against
  24 +# GLUT_FOUND, If false, do not try to use GLUT.
  25 +#
  26 +# Also defined, but not for general use are:
  27 +#
  28 +# ::
  29 +#
  30 +# GLUT_glut_LIBRARY = the full path to the glut library.
  31 +# GLUT_Xmu_LIBRARY = the full path to the Xmu library.
  32 +# GLUT_Xi_LIBRARY = the full path to the Xi Library.
  33 +
  34 +#=============================================================================
  35 +# Copyright 2001-2009 Kitware, Inc.
  36 +#
  37 +# Distributed under the OSI-approved BSD License (the "License");
  38 +# see accompanying file Copyright.txt for details.
  39 +#
  40 +# This software is distributed WITHOUT ANY WARRANTY; without even the
  41 +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  42 +# See the License for more information.
  43 +#=============================================================================
  44 +# (To distribute this file outside of CMake, substitute the full
  45 +# License text for the above reference.)
  46 +
  47 +if (WIN32)
  48 + find_path( GLUT_INCLUDE_DIR NAMES GL/glut.h
  49 + PATHS $ENV{GLUT_ROOT_PATH}/include )
  50 + find_library( GLUT_glut_LIBRARY NAMES glut glut32 freeglut
  51 + PATHS
  52 + ${OPENGL_LIBRARY_DIR}
  53 + $ENV{GLUT_ROOT_PATH}/lib
  54 + )
  55 +else ()
  56 +
  57 + if (APPLE)
  58 + find_path(GLUT_INCLUDE_DIR glut.h ${OPENGL_LIBRARY_DIR})
  59 + find_library(GLUT_glut_LIBRARY GLUT DOC "GLUT library for OSX")
  60 + find_library(GLUT_cocoa_LIBRARY Cocoa DOC "Cocoa framework for OSX")
  61 +
  62 + if(GLUT_cocoa_LIBRARY AND NOT TARGET GLUT::Cocoa)
  63 + add_library(GLUT::Cocoa UNKNOWN IMPORTED)
  64 + # Cocoa should always be a Framework, but we check to make sure.
  65 + if(GLUT_cocoa_LIBRARY MATCHES "/([^/]+)\\.framework$")
  66 + set_target_properties(GLUT::Cocoa PROPERTIES
  67 + IMPORTED_LOCATION "${GLUT_cocoa_LIBRARY}/${CMAKE_MATCH_1}")
  68 + else()
  69 + set_target_properties(GLUT::Cocoa PROPERTIES
  70 + IMPORTED_LOCATION "${GLUT_cocoa_LIBRARY}")
  71 + endif()
  72 + endif()
  73 + else ()
  74 +
  75 + if (BEOS)
  76 +
  77 + set(_GLUT_INC_DIR /boot/develop/headers/os/opengl)
  78 + set(_GLUT_glut_LIB_DIR /boot/develop/lib/x86)
  79 +
  80 + else()
  81 +
  82 + find_library( GLUT_Xi_LIBRARY Xi
  83 + /usr/openwin/lib
  84 + )
  85 +
  86 + find_library( GLUT_Xmu_LIBRARY Xmu
  87 + /usr/openwin/lib
  88 + )
  89 +
  90 + if(GLUT_Xi_LIBRARY AND NOT TARGET GLUT::Xi)
  91 + add_library(GLUT::Xi UNKNOWN IMPORTED)
  92 + set_target_properties(GLUT::Xi PROPERTIES
  93 + IMPORTED_LOCATION "${GLUT_Xi_LIBRARY}")
  94 + endif()
  95 +
  96 + if(GLUT_Xmu_LIBRARY AND NOT TARGET GLUT::Xmu)
  97 + add_library(GLUT::Xmu UNKNOWN IMPORTED)
  98 + set_target_properties(GLUT::Xmu PROPERTIES
  99 + IMPORTED_LOCATION "${GLUT_Xmu_LIBRARY}")
  100 + endif()
  101 +
  102 + endif ()
  103 +
  104 + find_path( GLUT_INCLUDE_DIR GL/glut.h
  105 + /usr/include/GL
  106 + /usr/openwin/share/include
  107 + /usr/openwin/include
  108 + /opt/graphics/OpenGL/include
  109 + /opt/graphics/OpenGL/contrib/libglut
  110 + ${_GLUT_INC_DIR}
  111 + )
  112 +
  113 + find_library( GLUT_glut_LIBRARY glut
  114 + /usr/openwin/lib
  115 + ${_GLUT_glut_LIB_DIR}
  116 + )
  117 +
  118 + unset(_GLUT_INC_DIR)
  119 + unset(_GLUT_glut_LIB_DIR)
  120 +
  121 + endif ()
  122 +
  123 +endif ()
  124 +
  125 +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLUT REQUIRED_VARS GLUT_glut_LIBRARY GLUT_INCLUDE_DIR)
  126 +
  127 +if (GLUT_FOUND)
  128 + # Is -lXi and -lXmu required on all platforms that have it?
  129 + # If not, we need some way to figure out what platform we are on.
  130 + set( GLUT_LIBRARIES
  131 + ${GLUT_glut_LIBRARY}
  132 + ${GLUT_Xmu_LIBRARY}
  133 + ${GLUT_Xi_LIBRARY}
  134 + ${GLUT_cocoa_LIBRARY}
  135 + )
  136 +
  137 + if(NOT TARGET GLUT::GLUT)
  138 + add_library(GLUT::GLUT UNKNOWN IMPORTED)
  139 + set_target_properties(GLUT::GLUT PROPERTIES
  140 + INTERFACE_INCLUDE_DIRECTORIES "${GLUT_INCLUDE_DIR}")
  141 + if(GLUT_glut_LIBRARY MATCHES "/([^/]+)\\.framework$")
  142 + set_target_properties(GLUT::GLUT PROPERTIES
  143 + IMPORTED_LOCATION "${GLUT_glut_LIBRARY}/${CMAKE_MATCH_1}")
  144 + else()
  145 + set_target_properties(GLUT::GLUT PROPERTIES
  146 + IMPORTED_LOCATION "${GLUT_glut_LIBRARY}")
  147 + endif()
  148 +
  149 + if(TARGET GLUT::Xmu)
  150 + set_property(TARGET GLUT::GLUT APPEND
  151 + PROPERTY INTERFACE_LINK_LIBRARIES GLUT::Xmu)
  152 + endif()
  153 +
  154 + if(TARGET GLUT::Xi)
  155 + set_property(TARGET GLUT::GLUT APPEND
  156 + PROPERTY INTERFACE_LINK_LIBRARIES GLUT::Xi)
  157 + endif()
  158 +
  159 + if(TARGET GLUT::Cocoa)
  160 + set_property(TARGET GLUT::GLUT APPEND
  161 + PROPERTY INTERFACE_LINK_LIBRARIES GLUT::Cocoa)
  162 + endif()
  163 + endif()
  164 +
  165 + #The following deprecated settings are for backwards compatibility with CMake1.4
  166 + set (GLUT_LIBRARY ${GLUT_LIBRARIES})
  167 + set (GLUT_INCLUDE_PATH ${GLUT_INCLUDE_DIR})
  168 +endif()
  169 +
  170 +mark_as_advanced(
  171 + GLUT_INCLUDE_DIR
  172 + GLUT_glut_LIBRARY
  173 + GLUT_Xmu_LIBRARY
  174 + GLUT_Xi_LIBRARY
  175 + )
... ...
main.cpp
... ... @@ -2,44 +2,220 @@
2 2 #include <string>
3 3 #include <fstream>
4 4 #include <algorithm>
5   -#include <stim/biomodels/network.h>
6 5  
  6 +//OpenGL includes
  7 +#include <GL/glut.h>
  8 +
  9 +//STIM includes
  10 +#include <stim/visualization/gl_network.h>
  11 +#include <stim/visualization/gl_aabb.h>
  12 +#include <stim/parser/arguments.h>
  13 +#include <stim/visualization/camera.h>
  14 +
  15 +//ANN includes
7 16 #include <ANN/ANN.h>
  17 +
  18 +//BOOST includes
8 19 #include <boost/tuple/tuple.hpp>
9   -using namespace stim;
10   -//template <typename T>
11   -network<float>* network1;
12 20  
  21 +stim::gl_aabb<float> bb;
  22 +stim::camera cam;
  23 +
  24 +stim::gl_network<float> GT;
  25 +stim::gl_network<float> T;
  26 +
  27 +//hard-coded parameters
  28 +float resample_rate = 0.5;
  29 +
  30 +//mouse position tracking
  31 +int mouse_x;
  32 +int mouse_y;
  33 +
  34 +void glut_render(void) {
  35 +
  36 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  37 +
  38 + glMatrixMode(GL_MODELVIEW);
  39 + glLoadIdentity();
  40 + stim::vec<float> eye = cam.getPosition();
  41 + stim::vec<float> focus = cam.getLookAt();
  42 + stim::vec<float> up = cam.getUp();
  43 +
  44 + gluLookAt(eye[0], eye[1], eye[2], focus[0], focus[1], focus[2], up[0], up[1], up[2]);
  45 +
  46 +
  47 +
  48 + // render the bounding box
  49 + glColor3f(0.0, 0.0, 1.0);
  50 + glBegin(GL_LINE_LOOP);
  51 + bb.glPointsCW();
  52 + glEnd();
  53 +
  54 + //render the GT network (red)
  55 + glColor3f(1.0, 0.0, 0.0);
  56 + GT.glCenterline();
  57 +
  58 + //render the T network (green)
  59 + glColor3f(0.0, 1.0, 0.0);
  60 + T.glCenterline();
  61 +
  62 + glutSwapBuffers();
  63 +}
  64 +
  65 +// defines camera motion based on mouse dragging
  66 +void glut_motion(int x, int y){
  67 + float factor = 0.01;
  68 +
  69 + float theta = factor * (mouse_x - x);
  70 + float phi = factor * (y - mouse_y);
  71 +
  72 + cam.OrbitFocus(theta, phi);
  73 +
  74 + mouse_x = x;
  75 + mouse_y = y;
  76 +
  77 + glutPostRedisplay();
  78 +}
  79 +
  80 +// sets the mouse position when clicked
  81 +void glut_mouse(int button, int state, int x, int y){
  82 + mouse_x = x;
  83 + mouse_y = y;
  84 +}
  85 +
  86 +// re-calculates the projection matrix if the window is reshaped
  87 +void glut_reshape(int x, int y){
  88 +
  89 + glMatrixMode(GL_PROJECTION);
  90 + glLoadIdentity();
  91 + glViewport(0, 0, x, y);
  92 + float aspect = (float)x / (float)y;
  93 + gluPerspective(60, aspect, 0.1, 1000000);
  94 +
  95 +}
  96 +
  97 +void advertise(){
  98 + //output advertisement
  99 + std::cout<<std::endl<<std::endl;
  100 + std::cout<<"========================================================================="<<std::endl;
  101 + std::cout<<"Thank you for using the NetMets network comparison tool!"<<std::endl;
  102 + std::cout<<"Scalable Tissue Imaging and Modeling (STIM) Lab, University of Houston"<<std::endl;
  103 + std::cout<<"Developers: Pranathi Vemuri, David Mayerich"<<std::endl;
  104 + std::cout<<"Source: https://git.stim.ee.uh.edu/segmentation/netmets"<<std::endl;
  105 + std::cout<<"========================================================================="<<std::endl<<std::endl;
  106 +
  107 + std::cout<<"usage: netmets file1 file2 --sigma 10"<<std::endl;
  108 + std::cout<<" compare two files with a tolerance of 10 (units defined by the network)"<<std::endl;
  109 + std::cout<<" netmets file1 --gui"<<std::endl<<std::endl;
  110 + std::cout<<" load a file and display it using OpenGL"<<std::endl;
  111 +
  112 +}
  113 +
  114 +void compare(float sigma){
  115 +
  116 + // compare ground truth with truth and viceversa
  117 + stim::network<float> cGT = GT.compare(T, sigma);
  118 + stim::network<float> cT = T.compare(GT, sigma);
  119 +
  120 + //calculate the metrics
  121 + float FPR = cGT.average(1);
  122 + float FNR = cT.average(1);
  123 + // print false alarms and misses
  124 + std::cout << "FNR: " << FPR << std::endl;
  125 + std::cout << "FPR: " << FNR << std::endl;
  126 +}
  127 +
  128 +void glut_initialize(){
  129 + float factor = 1.2;
  130 +
  131 + // init GLUT and create Window
  132 + int myargc = 1;
  133 + char* myargv[1];
  134 + myargv [0]=strdup ("netmets");
  135 +
  136 + glutInit(&myargc, myargv);
  137 + glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
  138 + glutInitWindowPosition(100,100);
  139 + glutInitWindowSize(320,320);
  140 + glutCreateWindow("Lighthouse3D- GLUT Tutorial");
  141 +
  142 +
  143 + // register callbacks
  144 + glutDisplayFunc(glut_render);
  145 + glutMouseFunc(glut_mouse);
  146 + glutMotionFunc(glut_motion);
  147 + glutReshapeFunc(glut_reshape);
  148 +
  149 + //set up the camera
  150 + stim::vec<float> c = bb.center();
  151 + //place the camera along the z-axis at a distance determined by the network size along x and y
  152 + cam.setPosition(c + stim::vec<float>(0, 0, factor * std::max(bb.size()[0], bb.size()[1])));
  153 + cam.LookAt(c[0], c[1], c[2]); //look at the center
  154 +
  155 +}
  156 +
  157 +void display(){
  158 +
  159 +
  160 + //generate a bounding volume
  161 + bb = GT.boundingbox();
  162 +
  163 + std::cout<<bb.str()<<std::endl;
  164 +
  165 + std::cout<<"center: "<<bb.center().str()<<std::endl;
  166 + std::cout<<"size: "<<bb.size().str()<<std::endl;
  167 +
  168 + //create the GLUT window and set callback functions
  169 + glut_initialize();
  170 +
  171 + glut_reshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
  172 +
  173 + std::cout<<cam.str()<<std::endl;
  174 +
  175 + // enter GLUT event processing cycle
  176 + glutMainLoop();
  177 +}
13 178  
14 179 int main(int argc, char* argv[])
15 180 {
16   - if(argc < 4){
17   - std::cout<<"Please specify a ground truth and test case"<<std::endl;
  181 + //create an instance of arglist
  182 + stim::arglist args;
  183 +
  184 + //add arguments
  185 + args.add("help", "prints this help");
  186 + args.add("sigma", "force a sigma value to specify the tolerance of the network comparison", "10");
  187 + args.add("gui", "display the network or network comparison using OpenGL");
  188 +
  189 + //parse the user arguments
  190 + args.parse(argc, argv);
  191 +
  192 + //test for help
  193 + if(args["help"].is_set() || args.nargs() == 0){
  194 + advertise();
  195 + std::cout<<args.str();
18 196 exit(1);
19 197 }
20 198  
21   - float resample_rate = 0.1;
  199 + //if one file is specified, load it as the ground truth
  200 + if(args.nargs() >= 1){
  201 + GT.load_obj(args.arg(0));
  202 + }
22 203  
23   - float sigma = atof(argv[3]);
24   - stim::network<float> GT;stim::network<float> T;
25   - // load obj files to 3D network class
26   -
27   - //load the ground truth and test case networks
28   - GT.load_obj(argv[1]);
29   - T.load_obj(argv[2]);
  204 + //if two files are provided, compare them
  205 + if(args.nargs() == 2){
  206 + float sigma = args["sigma"].as_float(); //get the sigma value from the user
  207 + T.load_obj(args.arg(1)); //load the second (test) network
30 208  
31   - // resample the loaded networks
32   - stim::network<float> resampled_GT;
33   - stim::network<float> resampled_T;
  209 + GT = GT.resample(resample_rate * sigma); //resample both networks based on the sigma value
  210 + T = T.resample(resample_rate * sigma);
34 211  
35   - resampled_GT = GT.resample(sigma * resample_rate);
36   - resampled_T = T.resample(sigma * resample_rate);
  212 + compare(sigma); //run the comparison algorithm
  213 + }
37 214  
38   - // compare ground truth with truth and viceversa
39   - float gFPR, gFNR;
40   - gFPR = resampled_GT.compare(resampled_T, sigma);
41   - gFNR = resampled_T.compare(resampled_GT, sigma);
42   - // print false alarms and misses
43   - std::cout << "False postive rate is " << gFPR << std::endl;
44   - std::cout << "False negative rate is " << gFNR << std::endl;
  215 + //if a GUI is requested, display the network using OpenGL
  216 + if(args["gui"].is_set())
  217 + display();
  218 +
  219 +
  220 +
45 221 }
46 222 \ No newline at end of file
... ...