LCOV - code coverage report
Current view: top level - cltools - GenExample.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 251 305 82.3 %
Date: 2026-11-05 10:19:04 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2019-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #include "CLTool.h"
      23             : #include "core/CLToolRegister.h"
      24             : #include "tools/Tools.h"
      25             : #include "config/Config.h"
      26             : #include "core/ActionRegister.h"
      27             : #include "core/ActionWithValue.h"
      28             : #include "core/ActionWithVirtualAtom.h"
      29             : #include "core/ActionShortcut.h"
      30             : #include "core/ActionSet.h"
      31             : #include "core/PlumedMain.h"
      32             : #include "tools/Communicator.h"
      33             : #include "tools/IFile.h"
      34             : #include <cstdio>
      35             : #include <string>
      36             : #include <vector>
      37             : #include <iostream>
      38             : #include <fstream>
      39             : 
      40             : namespace PLMD {
      41             : namespace cltools {
      42             : 
      43             : //+PLUMEDOC TOOLS gen_example
      44             : /*
      45             : gen_example is a tool that you can use to construct an example for the manual that users can interact with to understand
      46             : 
      47             : The example constructed by this action is in html. In all probability you will never need to use this
      48             : tool. However, it is used within the scripts that generate the html manual for PLUMED.  If you need to use this
      49             : tool outside those scripts the input is specified using the following command line arguments.
      50             : 
      51             : THIS COMMAND WILL LIKELY BE DELETED SOON AS IT HAS BEEN SUPERCEDED BY PLUMEDTOHTML.
      52             : 
      53             : ## Examples
      54             : 
      55             : The following generates an example based on the contents of the plumed file plumed.dat
      56             : 
      57             : ```plumed
      58             : plumed gen_example --plumed plumed.dat --status working
      59             : ```
      60             : 
      61             : 
      62             : */
      63             : //+ENDPLUMEDOC
      64             : 
      65             : class GenExample:
      66             :   public CLTool {
      67             : private:
      68             :   int multi;
      69             :   std::string status, version;
      70             :   Communicator intracomm;
      71             :   Communicator intercomm;
      72             : public:
      73             :   static void registerKeywords( Keywords& keys );
      74             :   explicit GenExample(const CLToolOptions& co );
      75             :   int main(FILE* in, FILE*out,Communicator& pc) override;
      76           7 :   std::string description()const override {
      77           7 :     return "construct an example for the manual that users can interact with";
      78             :   }
      79             :   void printExampleInput( const std::vector<std::vector<std::string> >& input, const std::string& egname, const std::string& divname, std::ofstream& ofile );
      80             :   std::vector<std::vector<std::string> > createLongInput( const std::vector<std::vector<std::string> >& input );
      81             : };
      82             : 
      83       21972 : PLUMED_REGISTER_CLTOOL(GenExample,"gen_example")
      84             : 
      85        7321 : void GenExample::registerKeywords( Keywords& keys ) {
      86        7321 :   CLTool::registerKeywords( keys );
      87        7321 :   keys.add("compulsory","--plumed","plumed.dat","convert the input in this file to the html manual");
      88        7321 :   keys.add("compulsory","--out","example.html","the file on which to output the example in html");
      89        7321 :   keys.add("compulsory","--name","ppp","the name to use for this particular input");
      90        7321 :   keys.add("compulsory","--status","nobadge","whether or not the input file works");
      91        7321 :   keys.add("compulsory","--multi","0","set number of replicas for multi environment (needs MPI)");
      92        7321 : }
      93             : 
      94           9 : GenExample::GenExample(const CLToolOptions& co ):
      95             :   CLTool(co),
      96           9 :   multi(0),
      97          18 :   status("nobadge"),
      98           9 :   version("master") {
      99           9 :   inputdata=inputType::commandline;
     100           9 : }
     101             : 
     102           2 : int GenExample::main(FILE* in, FILE*out,Communicator& pc) {
     103             : 
     104             : // set up for multi replica driver:
     105           2 :   parse("--multi",multi);
     106           2 :   if(multi) {
     107           0 :     int ntot=pc.Get_size();
     108           0 :     int nintra=ntot/multi;
     109           0 :     if(multi*nintra!=ntot) {
     110           0 :       error("invalid number of processes for multi environment");
     111             :     }
     112           0 :     pc.Split(pc.Get_rank()/nintra,pc.Get_rank(),intracomm);
     113           0 :     pc.Split(pc.Get_rank()%nintra,pc.Get_rank(),intercomm);
     114             :   } else {
     115           2 :     intracomm.Set_comm(pc.Get_comm());
     116             :   }
     117             : 
     118           4 :   if( config::getVersionLong().find("dev")==std::string::npos ) {
     119           0 :     version="v"+config::getVersion();
     120             :   }
     121             :   std::string fname, egname, outfile;
     122           2 :   parse("--plumed",fname);
     123           2 :   parse("--name",egname);
     124           2 :   parse("--out",outfile);
     125           2 :   parse("--status",status);
     126             : 
     127           2 :   int r=0;
     128           2 :   if(intracomm.Get_rank()==0) {
     129           2 :     r=intercomm.Get_rank();
     130             :   }
     131           2 :   intracomm.Bcast(r,0);
     132           2 :   if(r>0) {
     133             :     outfile="/dev/null";
     134             :   }
     135             : 
     136           2 :   IFile ifile;
     137           2 :   ifile.open(fname);
     138           2 :   ifile.allowNoEOL();
     139           2 :   std::ofstream ofile;
     140           2 :   ofile.open(outfile);
     141           2 :   std::vector<bool> shortcuts;
     142             :   bool hasshortcuts=false, endplumed=false;
     143           2 :   std::vector<std::vector<std::string> > input;
     144           2 :   std::vector<std::string> words;
     145          20 :   while( Tools::getParsedLine(ifile, words, false) ) {
     146          18 :     input.push_back( words );
     147          18 :     shortcuts.push_back( false );
     148          18 :     if( words.empty() || words[0].find("#")!=std::string::npos || endplumed ) {
     149           6 :       continue;
     150             :     }
     151          14 :     std::vector<std::string> interpreted( words );
     152          14 :     Tools::interpretLabel(interpreted);
     153          14 :     if( interpreted[0]=="ENDPLUMED" ) {
     154             :       endplumed=true;
     155             :       continue;
     156             :     }
     157          12 :     Keywords keys;
     158          12 :     actionRegister().getKeywords( interpreted[0], keys );
     159          12 :     if( status=="working" && keys.exists("IS_SHORTCUT") ) {
     160           2 :       hasshortcuts=shortcuts[shortcuts.size()-1]=true;
     161             :     }
     162          14 :   }
     163           2 :   ifile.close();
     164           2 :   if( hasshortcuts ) {
     165           2 :     ofile<<"<div style=\"width: 80%; float:left\" id=\"value_details_"<<egname<<"\"> Click on the labels of the actions for more information on what each action computes </div>\n";
     166           3 :     ofile<<"<div style=\"width: 10%; float:left\"><button type=\"button\" id=\""<<egname<<"_button\" onclick=\'swapInput(\""<<egname<<"\")\'>contract shortcuts</button></div>";
     167             :   } else {
     168           2 :     ofile<<"<div style=\"width: 90%; float:left\" id=\"value_details_"<<egname<<"\"> Click on the labels of the actions for more information on what each action computes </div>\n";
     169             :   }
     170           2 :   ofile<<"<div style=\"width: 10%; float:left\">";
     171           2 :   ofile<<"<img src=\"https://img.shields.io/badge/";
     172           2 :   if(status=="working") {
     173           1 :     ofile<<version<<"-passing-green";
     174           1 :   } else if(status=="broken") {
     175           0 :     ofile<<version<<"-failed-red";
     176           1 :   } else if(status=="loads") {
     177           0 :     ofile<<"with-LOAD-yellow";
     178           1 :   } else if(status=="incomplete") {
     179           0 :     ofile<<version<<"-incomplete-yellow";
     180           1 :   } else if ( status=="nobadge" ) {
     181           1 :     ofile<<"nobadge-36454F";
     182             :   } else {
     183           0 :     error("unknown status: "+status);
     184             :   }
     185           4 :   ofile<<".svg\" alt=\"tested on "<<version<<"\" /></div>";
     186           2 :   ofile.flush();
     187           2 :   if( hasshortcuts ) {
     188             :     // Write out the short version of the input
     189           2 :     ofile<<"<div style=\"width: 100%; float:left\" id=\"input_"<<egname<<"\"></div>"<<std::endl;
     190             :     // Write an extra pre to make sure the html after the example is put in the right place on the page
     191           1 :     ofile<<"<pre style=\"width: 97%;\" class=\"fragment\"></pre>"<<std::endl;
     192           1 :     ofile<<"<script type=\"text/javascript\">"<<std::endl;
     193           1 :     ofile<<"if (window.addEventListener) { // Mozilla, Netscape, Firefox"<<std::endl;
     194           2 :     ofile<<"    window.addEventListener('load', "<<egname<<"Load, false);"<<std::endl;
     195           1 :     ofile<<"} else if (window.attachEvent) { // IE"<<std::endl;
     196           2 :     ofile<<"    window.attachEvent('onload', "<<egname<<"Load);"<<std::endl;
     197           1 :     ofile<<"}"<<std::endl;
     198           2 :     ofile<<"function "<<egname<<"Load(event) {"<<std::endl;
     199           2 :     ofile<<"       swapInput(\""<<egname<<"\");"<<std::endl;
     200           1 :     ofile<<"}"<<std::endl;
     201           1 :     ofile<<"</script>"<<std::endl;
     202           2 :     ofile<<"<div style=\"display:none;\" id=\""<<egname<<"short\">"<<std::endl;
     203           1 :     printExampleInput( input, egname + "short", egname, ofile );
     204           1 :     ofile<<"</div>"<<std::endl;
     205             :     // Write out long version of the input
     206           2 :     ofile<<"<div style=\"display:none;\" id=\""<<egname<<"long\">";
     207           1 :     std::vector<std::vector<std::string> > long_input = createLongInput( input );
     208           1 :     printExampleInput( long_input, egname + "long", egname, ofile );
     209           1 :     ofile<<"</div>"<<std::endl;
     210           1 :   } else {
     211           1 :     printExampleInput( input, egname, egname, ofile );
     212             :   }
     213           2 :   ofile.close();
     214           2 :   return 0;
     215           4 : }
     216             : 
     217           1 : std::vector<std::vector<std::string> > GenExample::createLongInput( const std::vector<std::vector<std::string> >& input ) {
     218           1 :   std::vector<std::vector<std::string> > long_input;
     219           1 :   PlumedMain myplumed;
     220           1 :   int rr=sizeof(double), natoms=10000000;
     221           1 :   double kt=2.49;
     222           1 :   myplumed.cmd("setRealPrecision",&rr);
     223           1 :   if(Communicator::initialized()) {
     224           0 :     if(multi) {
     225           0 :       if(intracomm.Get_rank()==0) {
     226           0 :         myplumed.cmd("GREX setMPIIntercomm",&intercomm.Get_comm());
     227             :       }
     228           0 :       myplumed.cmd("GREX setMPIIntracomm",&intracomm.Get_comm());
     229           0 :       myplumed.cmd("GREX init");
     230             :     }
     231           0 :     myplumed.cmd("setMPIComm",&intracomm.Get_comm());
     232             :   }
     233             :   bool endplumed=false;
     234           1 :   myplumed.cmd("setNatoms",&natoms);
     235           1 :   myplumed.cmd("setKbT",&kt);
     236           1 :   myplumed.cmd("init");
     237          10 :   for(unsigned ll=0; ll<input.size(); ++ll) {
     238           9 :     if( input[ll].empty() || endplumed ) {
     239           1 :       long_input.push_back( input[ll] );
     240           3 :       continue;
     241             :     }
     242           8 :     if( input[ll][0].find("#")!=std::string::npos ) {
     243           1 :       long_input.push_back( input[ll] );
     244           1 :       continue;
     245             :     }
     246           7 :     std::vector<std::string> interpreted( input[ll] );
     247           7 :     Tools::interpretLabel(interpreted);
     248           7 :     if( interpreted[0]=="ENDPLUMED" ) {
     249             :       endplumed=true;
     250           1 :       long_input.push_back( input[ll] );
     251             :       continue;
     252             :     }
     253           6 :     Keywords keys;
     254           6 :     plumed_assert( actionRegister().check( interpreted[0] ) );
     255           6 :     actionRegister().getKeywords( interpreted[0], keys );
     256             :     std::string lab, myinputline;
     257          12 :     if( Tools::parse(interpreted, "LABEL", lab ) ) {
     258          10 :       myinputline = lab + ": ";
     259             :     }
     260           6 :     myinputline += interpreted[0] + " ";
     261             :     bool trailingcomment=false;
     262          22 :     for(unsigned i=1; i<interpreted.size(); ++i) {
     263          16 :       if( trailingcomment && interpreted[i]=="@newline") {
     264             :         trailingcomment=false;
     265           0 :         continue;
     266             :       }
     267          16 :       if( interpreted[i].find("#")!=std::string::npos ) {
     268             :         trailingcomment=true;
     269           1 :         continue;
     270             :       }
     271             :       // the words of a trailing comment are not part of the input
     272          15 :       if( trailingcomment ) {
     273           2 :         continue;
     274             :       }
     275          13 :       if( interpreted[i]=="@newline" || interpreted[i]=="..." ) {
     276           3 :         continue;
     277             :       }
     278             :       std::size_t pos = 0;
     279          10 :       while ((pos = interpreted[i].find("@newline",pos)) != std::string::npos) {
     280           0 :         interpreted[i].replace(pos, 8, "\n");
     281           0 :         pos++;
     282             :       }
     283          20 :       myinputline += interpreted[i] + " ";
     284             :     }
     285           6 :     if( status=="working" && keys.exists("IS_SHORTCUT") ) {
     286           2 :       myplumed.readInputLine( myinputline );
     287           2 :       ActionShortcut* as=dynamic_cast<ActionShortcut*>( myplumed.getActionSet()[myplumed.getActionSet().size()-1].get() );
     288           2 :       plumed_assert( as );
     289           2 :       const auto & shortcut_commands = as->getSavedInputLines();
     290             :       // some shortcuts do not save their expansion: keep the original line
     291           2 :       if( shortcut_commands.size()==0 ) {
     292           2 :         long_input.push_back( input[ll] );
     293             :       }
     294           2 :       for(unsigned i=0; i<shortcut_commands.size(); ++i) {
     295           0 :         std::vector<std::string> words = Tools::getWords( shortcut_commands[i] );
     296           0 :         long_input.push_back( words );
     297           0 :       }
     298             :     } else {
     299           4 :       long_input.push_back( input[ll] );
     300           4 :       myplumed.readInputLine( myinputline );
     301             :     }
     302           7 :   }
     303           1 :   return long_input;
     304           6 : }
     305             : 
     306           3 : void GenExample::printExampleInput( const std::vector<std::vector<std::string> >& input, const std::string& egname, const std::string& divname, std::ofstream& ofile ) {
     307           3 :   PlumedMain myplumed;
     308           3 :   int rr=sizeof(double), natoms=10000000;
     309           3 :   double kt=2.49;
     310           3 :   myplumed.cmd("setRealPrecision",&rr);
     311           3 :   if(Communicator::initialized()) {
     312           0 :     if(multi) {
     313           0 :       if(intracomm.Get_rank()==0) {
     314           0 :         myplumed.cmd("GREX setMPIIntercomm",&intercomm.Get_comm());
     315             :       }
     316           0 :       myplumed.cmd("GREX setMPIIntracomm",&intracomm.Get_comm());
     317           0 :       myplumed.cmd("GREX init");
     318             :     }
     319           0 :     myplumed.cmd("setMPIComm",&intracomm.Get_comm());
     320             :   }
     321           3 :   myplumed.cmd("setNatoms",&natoms);
     322           3 :   myplumed.cmd("setKbT",&kt);
     323           3 :   myplumed.cmd("init");
     324           3 :   std::vector<std::string> labellist;
     325             :   bool endplumed=false;
     326           3 :   ofile<<"<pre style=\"width: 97%;\" class=\"fragment\">"<<std::endl;
     327          30 :   for(unsigned ll=0; ll<input.size(); ++ll) {
     328          27 :     if( input[ll].empty() ) {
     329             :       ofile<<std::endl;
     330           0 :       continue;
     331             :     }
     332          27 :     if( input[ll][0].find("#")!=std::string::npos || endplumed ) {
     333           6 :       ofile<<"<span style=\"color:blue\">"<<input[ll][0];
     334          18 :       for(unsigned i=1; i<input[ll].size(); ++i) {
     335          12 :         ofile<<" "<<input[ll][i];
     336             :       }
     337           6 :       ofile<<"</span>"<<std::endl;;
     338             :     } else {
     339             :       // Interpret the label if this needs to be done
     340          21 :       std::vector<std::string> interpreted( input[ll] );
     341          21 :       Tools::interpretLabel(interpreted);
     342             :       std::string lab, myinputline;
     343             :       // Now read in the label
     344          42 :       if( Tools::parse(interpreted,"LABEL",lab) ) {
     345          75 :         ofile<<"<b name=\""<<egname<<lab<<"\" onclick=\'showPath(\""<<divname<<"\",\""<<egname<<lab<<"\")\'>"<<lab<<": </b>";
     346          15 :         labellist.push_back(lab);
     347          30 :         myinputline = lab + ": ";
     348             :       }
     349             :       // Print the keyword in use in the action
     350          21 :       std::string action = interpreted[0];
     351          21 :       myinputline += interpreted[0] + " ";
     352          21 :       if( action=="ENDPLUMED" ) {
     353             :         endplumed=true;
     354             :       }
     355          21 :       Keywords keys;
     356          21 :       actionRegister().getKeywords( interpreted[0], keys );
     357             :       // Handle conversion of action names to links
     358          21 :       std::transform(action.begin(), action.end(), action.begin(), [](unsigned char c) {
     359         150 :         return std::tolower(c);
     360             :       });
     361          42 :       ofile<<"<a href=\"https://www.plumed.org/doc-"<<version<<"/user-doc/html/";
     362             :       while(true) {
     363          21 :         std::size_t und=action.find_first_of("_");
     364          21 :         if( und==std::string::npos ) {
     365             :           break;
     366             :         }
     367           0 :         std::string first=action.substr(0,und);
     368           0 :         for(auto c : first ) {
     369           0 :           if( isdigit(c) ) {
     370           0 :             ofile<<c;
     371             :           } else {
     372           0 :             ofile<<"_"<<c;
     373             :           }
     374             :         }
     375           0 :         ofile<<"_";
     376           0 :         action=action.substr(und+1);
     377           0 :       }
     378         171 :       for(auto c : action ) {
     379         150 :         if( isdigit(c) ) {
     380           0 :           ofile<<c;
     381             :         } else {
     382         150 :           ofile<<"_"<<c;
     383             :         }
     384             :       }
     385          42 :       ofile<<".html\" style=\"color:green\">"<<interpreted[0]<<"</a> ";
     386             :       // And write out everything else in the input line
     387             :       bool trailingcomment=false;
     388          69 :       for(unsigned i=1; i<interpreted.size(); ++i) {
     389          48 :         if( interpreted[i]=="@newline" && i==1 ) {
     390           6 :           ofile<<"..."<<std::endl<<"   ";
     391           3 :           continue;
     392          45 :         } else if( interpreted[i]=="@newline" ) {
     393           3 :           if( trailingcomment ) {
     394           0 :             ofile<<"</span>";
     395             :             trailingcomment=false;
     396             :           }
     397           3 :           if( i+1<interpreted.size() && interpreted[i+1]=="..." ) {
     398             :             ofile<<std::endl;
     399             :           } else {
     400           0 :             ofile<<std::endl<<"   ";
     401             :           }
     402           3 :           continue;
     403          42 :         } else if( interpreted[i]=="__FILL__" ) {
     404           0 :           if( status!="incomplete" ) {
     405           0 :             error("found __FILL__ statement but status is " + status);
     406             :           }
     407           0 :           ofile<<"<span style=\"background-color:yellow\">__FILL__</span>";
     408           0 :           continue;
     409          42 :         } else if( interpreted[i]==action ) {
     410           0 :           continue;
     411             :         }
     412          42 :         if( interpreted[i].find("#")!=std::string::npos ) {
     413             :           trailingcomment=true;
     414           3 :           ofile<<"<span style=\"color:blue\">";
     415             :         }
     416             : 
     417          39 :         if( !trailingcomment ) {
     418          33 :           std::size_t eq=interpreted[i].find_first_of("=");
     419          33 :           if( eq!=std::string::npos ) {
     420          27 :             std::string keyword=interpreted[i].substr(0,eq), rest=interpreted[i].substr(eq+1);
     421          81 :             ofile<<"<span class=\"tooltip\">"<<keyword<<"<span class=\"right\">"<<keys.getTooltip(keyword)<<"<i></i></span></span>";
     422          27 :             if( rest=="__FILL__" ) {
     423           0 :               if( status!="incomplete" ) {
     424           0 :                 error("found __FILL__ statement but status is " + status);
     425             :               }
     426           0 :               ofile<<"=<span style=\"background-color:yellow\">__FILL__</span>";
     427          27 :             } else if( rest.find_first_of("{")!=std::string::npos ) {
     428             :               std::size_t pos = 0;
     429           0 :               while ((pos = rest.find("@newline",pos)) != std::string::npos) {
     430           0 :                 rest.replace(pos, 8, "\n");
     431           0 :                 pos++;
     432             :               }
     433           0 :               ofile<<"="<<rest<<" ";
     434           0 :               myinputline += keyword + "=" + rest + " ";
     435             :             } else {
     436          27 :               std::vector<std::string> args=Tools::getWords(rest,"\t\n ,");
     437          27 :               ofile<<"=";
     438          66 :               for(unsigned ii=0; ii<args.size(); ++ii) {
     439             :                 bool islabel=false;
     440             :                 std::string thislab;
     441         126 :                 for(unsigned j=0; j<labellist.size(); ++j) {
     442          99 :                   std::size_t dot=args[ii].find_first_of(".");
     443          99 :                   std::string lll=args[ii].substr(0,dot);
     444          99 :                   if( lll==labellist[j] ) {
     445             :                     islabel=true;
     446             :                     thislab=labellist[j];
     447             :                     break;
     448             :                   }
     449             :                 }
     450             :                 if( islabel ) {
     451          36 :                   ofile<<"<b name=\""<<egname<<thislab<<"\">"<<args[ii]<<"</b>";
     452             :                 } else {
     453             :                   ofile<<args[ii];
     454             :                 }
     455          39 :                 if( ii!=args.size()-1 ) {
     456          12 :                   ofile<<",";
     457             :                 }
     458             :               }
     459          27 :               myinputline += interpreted[i] + " ";
     460          27 :             }
     461          27 :             ofile<<" ";
     462           6 :           } else if( interpreted[i]!="@newline" && interpreted[i]!="..." ) {
     463           3 :             myinputline += interpreted[i] + " ";
     464          12 :             ofile<<"<span class=\"tooltip\">"<<interpreted[i]<<"<span class=\"right\">"<<keys.getTooltip(interpreted[i])<<"<i></i></span></span> ";
     465           3 :           } else if( interpreted[i]=="..." ) {
     466           3 :             ofile<<"...";
     467             :           }
     468             :         } else {
     469           9 :           ofile<<interpreted[i]<<" ";
     470             :         }
     471             :       }
     472          21 :       if( trailingcomment ) {
     473           3 :         ofile<<"</span>";
     474             :       }
     475             :       // This builds the hidden content that tells the user about what is calculated
     476          21 :       if( status=="working" ) {
     477          28 :         ofile<<"<span style=\"display:none;\" id=\""<<egname<<lab<<"\">";
     478          42 :         ofile<<"The "<<interpreted[0]<<" action with label <b>"<<lab<<"</b>";
     479          14 :         myplumed.readInputLine( myinputline );
     480          14 :         ActionWithValue* av=myplumed.getActionSet().selectWithLabel<ActionWithValue*>(lab);
     481             :         // virtual atoms are also ActionWithValue, but their components are not documented
     482          14 :         ActionWithVirtualAtom* avv=myplumed.getActionSet().selectWithLabel<ActionWithVirtualAtom*>(lab);
     483          14 :         if( avv ) {
     484           2 :           ofile<<" calculates the position of a virtual atom";
     485          12 :         } else if( av ) {
     486           6 :           if( av->getNumberOfComponents()==1 ) {
     487           2 :             ofile<<" calculates a single scalar value";
     488           4 :           } else if( av->getNumberOfComponents()>0 ) {
     489           4 :             ofile<<" calculates the following quantities:"<<std::endl;
     490           4 :             ofile<<"<table  align=\"center\" frame=\"void\" width=\"95%\" cellpadding=\"5%\">"<<std::endl;
     491           4 :             ofile<<"<tr><td width=\"5%\"><b> Quantity </b>  </td><td><b> Description </b> </td></tr>"<<std::endl;
     492           4 :             unsigned ncomp = av->getNumberOfComponents();
     493          14 :             for(unsigned k=0; k<ncomp; ++k ) {
     494          10 :               std::string myname = av->copyOutput(k)->getName();
     495          10 :               std::size_t dot=myname.find_first_of(".");
     496          10 :               std::string tname=myname.substr(dot+1);
     497          40 :               ofile<<"<tr><td width=\"5%\">"<<myname<<"</td><td>"<<av->getOutputComponentDescription(tname,keys)<<"</td></tr>"<<std::endl;
     498             :             }
     499           4 :             ofile<<"</table>"<<std::endl;
     500             :           }
     501           6 :         } else if( interpreted[0]=="GROUP" ) {
     502           2 :           ofile<<" defines a group of atoms so that they can be referred to later in the input";
     503             :         }
     504          14 :         ofile<<"</span>"<<std::endl;
     505             :       } else {
     506          14 :         ofile<<"<span style=\"display:none;\" id=\""<<egname<<lab<<"\"> You cannot view the components that are calculated by each action for this input file. Sorry </span>"<<std::endl;
     507             :       }
     508          42 :     }
     509          27 :     ofile.flush();
     510             :   }
     511           3 :   ofile<<"</pre>"<<std::endl;
     512           3 : }
     513             : 
     514             : } // End of namespace
     515             : }

Generated by: LCOV version 1.16