2020-12-09 09:30

Feature request: configurable logging for vmtk

When running vmtk code, messages are printed to stdout, thereby being completely ignorant of the caller's logging policies. This is particularly an issue when working with the Python wrapper, where it is almost impossible to catch and redirect the messages that are generated in vtkvmtk objects.


  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答


  • weixin_39831001 weixin_39831001 5月前

    Hey , thanks for reaching out! This is probably a better place for Feature Requests than the vmtk user group (things tend to get lost in the flood of activity there).

    The specification for writing the message OutputStream to sys.stdout occurs at https://github.com/vmtk/vmtk/blob/master/PypeS/pype.py#L47 . It shouldn't be difficult to add a configurable option to write to a file, but in order to make the change I'd like to know a bit more about your use case.

    Can you provide an example of your ideal "logging policy" and maybe an example of how you envision the solution working?

    点赞 评论 复制链接分享
  • weixin_39875192 weixin_39875192 5月前

    Honestly, I was not aware of member OutputStream. So this was a good occasion to re-read the documentation about pypes and how they are implemented.

    When looking at the code of Pype and pypeScript, the option to set OutputStream helps only to suppress messages created within the python layer of vmtk. All the messages created from within C++ objects cannot be controlled by setting the OutputStream to open(os.devnull, 'w') or NullOutputStream.

    For example, the code below still creates output:

    source = vtk.vtkSphereSource()
    remeshed = vmtkscripts.vmtkSurfaceRemeshing()
    remeshed.Surface = source.GetOutput()
    remeshed.ElementSizeMode = 'area'
    remeshed.TargetArea = 0.05
    remeshed.NumberOfIterations = 5
    remeshed.OutputStream = open(os.devnull, 'w')     # 

    Output on the console:

    Iteration 1/5
    Iteration 2/5
    Iteration 3/5
    Iteration 4/5
    Iteration 5/5
    Final mesh improvement
    点赞 评论 复制链接分享
  • weixin_39875192 weixin_39875192 5月前

    Regarding logging policies: You can take the python module logging as a reference how caller systems might organize logging. By defining loggers and message handlers one is very flexible in specifying which messages go where. Having the possibility to set pypeScript.OutputStream is fully compatible with that. However the lower-level messaging currently cannot be controlled easily, unless you tell me otherwise.

    点赞 评论 复制链接分享
  • weixin_39875192 weixin_39875192 5月前

    And more about logging: I think log4j set some standards and influenced various other logging systems. For C++ there are log4cplus, log4cxx, log4cpp that all come with their own flavors...

    These solutions are great because one can adjust the verbosity in a modular way. For instance it is possible to silence just one submodule, while receiving debug-messages for another. Also it is possible to identify the origin of a message, which can be helpful for debugging too.

    So a suggestion is to introduce such a logging system to vmtk and to configure it via API calls or an optional config file (e.g. here). But making stdout/stderr configurable would be a simple and feasible solution too. However, no idea how well this works across language boundaries (python/C++).

    点赞 评论 复制链接分享
  • weixin_39831001 weixin_39831001 5月前

    So I actually don't think I ever realized that the C++ layer in vtkVmtkScripts was generating output to the console. Thanks for pointing this out!

    I took a quick look at the code, and it appears that the console message in your example code is generated by a simple cout << foo at L#322 and L#340. A quick grep showed that there are 91 such uses of cout through the vtkVmtk module.

    vtkVmtk/ComputationalGeometry  (3 usages found)
        vtkvmtkCenterlineBranchGeometry.cxx  (2 usages found)
            361//   cout<NumberOfIterations<<endl cout mesh improvement vtkvmtkunstructuredgridgradientfilter.cxx usages found system vtkvmtk vtkvmtkdicomimagereader.cxx orientation: this->OrientationStringX << " " << this->OrientationStringY << " " << this->OrientationStringZ << " " << endl;
            259  cout << "Flipping: " << flipX << " " << flipY << " " << flipZ << endl;
        vtkvmtkFDNEUTReader.cxx  (1 usage found)
            465        cout<GetMinimum() << " " << minmax->GetMaximum() << std::endl;
            690        std::cout << "iterations/timestep \t" << m_Iterations << " " << m_TimeStep << std::endl; 
            691        std::cout << "recalc v            \t" << m_RecalculateVesselness << std::endl;
            692        std::cout << "scales              \t";
            695            std::cout << m_Scales[i] << " ";
            697        std::cout << std::endl;
            698        std::cout << "alpha/beta/gamma    \t" << m_Alpha << " " << m_Beta << " " << m_Gamma << std::endl;
            699        std::cout << "eps/omega/sens      \t" << m_Epsilon <<  " " << m_Omega << " " << m_Sensitivity << std::endl;
            713         std::cout << "start algorithm ... " << std::endl;
            728        std::cout << std::endl;
            729        std::cout << "min/max             \t" << mm->GetMinimum() << " " << mm->GetMaximum() << std::endl;
            730        std::cout << "end vesselenhancingdiffusion3Dimagefilter" << std::endl;
        vtkvmtkCollidingFrontsImageFilter.cxx  (1 usage found)
            65  std::cout<<input->GetScalarType()<<:endl vtkvmtk usages found tetgen.cxx scoutsegmentsub scout the first triangle on path from one point tetgenmesh::scoutsegmentsub searchsh tend return if segment and insert it is found. scoutsegment look for a given in tetrahedralization t. tetgenmesh::interresult tetgenmesh::scoutsegment2 sseg printf seg pointmark ref of dir="scoutsegment2(&sseg," scoutsubface subface tetgenmesh::scoutsubface pssub scoutcrosstet tetrahedron across facet. tetgenmesh::scoutcrosstet facpoints scoutfront face d. tetgenmesh::scoutfront front triface idfront number crossed faces segs: tetgen.h interresult scoutsegment2 ssub searchtet int arraypool></:endl></input-></endl>

    As far as I'm aware, there is no current functionality built in to the module to redirect/preserve message output generated by the C++ layer. While this is an issue for logging, It's also an issue because if the same pypes is run from both the terminal,and PypePad, the apparent output stream will be different (as PypePad only receives text from the python layer).

    Since the majority of the log info is generated through python, I think the cleanest solution would be to eliminate direct output in c++ all together. My initial thought is to have C++ call the pype object's self.PrintLog('foo') method. It shouldn't be too crazy to implement, and it would mean that a more formal logging system would only have to deal with output from the python layer.

    Any thoughts?

    点赞 评论 复制链接分享
  • weixin_39875192 weixin_39875192 5月前

    Your suggestions sound feasible to me, especially the point that status logging should take place only within the python layer.

    There should be a policy within vtkvmtk how and what to print. No logging by default is a reasonable choice. However, some users may appreciate the feedback for example on the progress via stdout messages (see for example the surface remeshing above).

    In vtk, there is a debug-flag that for any vtkObject that controls the output. A derived class then simply checks for that debug flag.

        if( this->GetDebug() )
          cout << "Debug message" << endl;

    Since vtkvmtk objects derive from vtkObject, this would be a good solution too. All the couts simply go behind that guard - a change that requires little effort.

    However, I noticed that vmtk scripts currently don't set the debug status for vtkvmtk/vtk objects based on command-line flags. So if the verbosity level should be made configurable via command line arguments, a bit more work would be required. Maybe the Pypes.LogOn flag could be used or a new one created?

    点赞 评论 复制链接分享
  • weixin_39875192 weixin_39875192 5月前

    And a brief note on the already mentioned alternatives: Given the low amount of logging within the vtkvmtk module, installation of a full-blown logging framework looks like an overkill. Controlling output from linked libraries within python is not trivial and requires threading, as explained in this SO thread.

    点赞 评论 复制链接分享
  • weixin_39875192 weixin_39875192 5月前

    Not entirely sure if this the right place to place a feature request from the community :)

    点赞 评论 复制链接分享