LCOV - code coverage report
Current view: top level - tools - Keywords.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 217 381 57.0 %
Date: 2021-11-18 15:22:58 Functions: 29 36 80.6 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-2020 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 "Keywords.h"
      23             : #include "Log.h"
      24             : #include "Tools.h"
      25             : #include <iostream>
      26             : 
      27             : namespace PLMD {
      28             : 
      29      464017 : Keywords::KeyType::KeyType( const std::string& type ) {
      30      464017 :   if( type=="compulsory" ) {
      31      124308 :     style=compulsory;
      32      339709 :   } else if( type=="flag" ) {
      33       88771 :     style=flag;
      34      250938 :   } else if( type=="optional" ) {
      35      131533 :     style=optional;
      36      179788 :   } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ) {
      37       59071 :     style=atoms;
      38       60334 :   } else if( type=="hidden" ) {
      39       29071 :     style=hidden;
      40       31263 :   } else if( type=="vessel" ) {
      41       31263 :     style=vessel;
      42             :   } else {
      43           0 :     plumed_massert(false,"invalid keyword specifier " + type);
      44             :   }
      45      464017 : }
      46             : 
      47        2243 : void Keywords::KeyType::setStyle( const std::string& type ) {
      48        2243 :   if( type=="compulsory" ) {
      49          58 :     style=compulsory;
      50        2185 :   } else if( type=="flag" ) {
      51           0 :     style=flag;
      52        2185 :   } else if( type=="optional" ) {
      53          25 :     style=optional;
      54        4128 :   } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ) {
      55         192 :     style=atoms;
      56        1968 :   } else if( type=="hidden" ) {
      57         129 :     style=hidden;
      58        1839 :   } else if( type=="vessel" ) {
      59        1839 :     style=vessel;
      60             :   } else {
      61           0 :     plumed_massert(false,"invalid keyword specifier " + type);
      62             :   }
      63        2243 : }
      64             : 
      65         669 : void Keywords::add( const Keywords& newkeys ) {
      66         669 :   newkeys.copyData( keys, reserved_keys, types, allowmultiple, documentation, booldefs, numdefs, atomtags, cnames, ckey, cdocs  );
      67         669 : }
      68             : 
      69         669 : void Keywords::copyData( std::vector<std::string>& kk, std::vector<std::string>& rk, std::map<std::string,KeyType>& tt, std::map<std::string,bool>& am,
      70             :                          std::map<std::string,std::string>& docs, std::map<std::string,bool>& bools, std::map<std::string,std::string>& nums,
      71             :                          std::map<std::string,std::string>& atags, std::vector<std::string>& cnam, std::map<std::string,std::string>& ck,
      72             :                          std::map<std::string,std::string>& cd ) const {
      73        1338 :   for(unsigned i=0; i<keys.size(); ++i) {
      74             :     std::string thiskey=keys[i];
      75           0 :     for(unsigned j=0; j<kk.size(); ++j) plumed_massert( thiskey!=kk[j], "keyword " + thiskey + " is in twice" );
      76           0 :     for(unsigned j=0; j<rk.size(); ++j) plumed_massert( thiskey!=rk[j], "keyword " + thiskey + " is in twice" );
      77           0 :     kk.push_back( thiskey );
      78           0 :     plumed_massert( types.count( thiskey ), "no type data on keyword " + thiskey + " to copy" );
      79           0 :     tt.insert( std::pair<std::string,KeyType>( thiskey,types.find(thiskey)->second) );
      80           0 :     if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair<std::string,std::string>( thiskey,atomtags.find(thiskey)->second) );
      81           0 :     plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" );
      82           0 :     am.insert( std::pair<std::string,bool>(thiskey,allowmultiple.find(thiskey)->second) );
      83           0 :     plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" );
      84           0 :     docs.insert( std::pair<std::string,std::string>(thiskey,documentation.find(thiskey)->second) );
      85           0 :     if( booldefs.count( thiskey ) ) bools.insert( std::pair<std::string,bool>( thiskey,booldefs.find(thiskey)->second) );
      86           0 :     if( numdefs.count( thiskey ) ) nums.insert( std::pair<std::string,std::string>( thiskey,numdefs.find(thiskey)->second) );
      87             :   }
      88       37464 :   for(unsigned i=0; i<reserved_keys.size(); ++i) {
      89             :     std::string thiskey=reserved_keys[i];
      90      306018 :     for(unsigned j=0; j<kk.size(); ++j) plumed_massert( thiskey!=kk[j], "keyword " + thiskey + " is in twice" );
      91      489159 :     for(unsigned j=0; j<rk.size(); ++j) plumed_massert( thiskey!=rk[j], "keyword " + thiskey + " is in twice" );
      92       12042 :     rk.push_back( thiskey );
      93           0 :     plumed_massert( types.count( thiskey ), "no type data on keyword " + thiskey + " to copy" );
      94       12042 :     tt.insert( std::pair<std::string,KeyType>( thiskey,types.find(thiskey)->second) );
      95       12042 :     if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair<std::string,std::string>( thiskey,atomtags.find(thiskey)->second) );
      96           0 :     plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" );
      97       12042 :     am.insert( std::pair<std::string,bool>(thiskey,allowmultiple.find(thiskey)->second) );
      98           0 :     plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" );
      99       24084 :     docs.insert( std::pair<std::string,std::string>(thiskey,documentation.find(thiskey)->second) );
     100           0 :     if( booldefs.count( thiskey ) ) bools.insert( std::pair<std::string,bool>( thiskey,booldefs.find(thiskey)->second) );
     101           0 :     if( numdefs.count( thiskey ) ) nums.insert( std::pair<std::string,std::string>( thiskey,numdefs.find(thiskey)->second) );
     102             :   }
     103       37464 :   for(unsigned i=0; i<cnames.size(); ++i) {
     104             :     std::string thisnam=cnames[i];
     105      331155 :     for(unsigned j=0; j<cnam.size(); ++j) plumed_massert( thisnam!=cnam[j], "component " + thisnam + " is in twice" );
     106       12042 :     cnam.push_back( thisnam );
     107           0 :     plumed_massert( ckey.count( thisnam ), "no keyword data on component " + thisnam + " to copy" );
     108       24084 :     ck.insert( std::pair<std::string,std::string>( thisnam, ckey.find(thisnam)->second) );
     109           0 :     plumed_massert( cdocs.count( thisnam ), "no documentation on component " + thisnam + " to copy" );
     110       24084 :     cd.insert( std::pair<std::string,std::string>( thisnam, cdocs.find(thisnam)->second) );
     111             :   }
     112         669 : }
     113             : 
     114       58080 : void Keywords::reserve( const std::string & t, const std::string & k, const std::string & d ) {
     115       58080 :   plumed_assert( !exists(k) && !reserved(k) );
     116             :   std::string fd, lowkey=k;
     117             :   // Convert to lower case
     118       58080 :   std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower);
     119             : // Remove any underscore characters
     120             :   for(unsigned i=0;; ++i) {
     121             :     std::size_t num=lowkey.find_first_of("_");
     122       78587 :     if( num==std::string::npos ) break;
     123       20507 :     lowkey.erase( lowkey.begin() + num, lowkey.begin() + num + 1 );
     124       20507 :   }
     125       58080 :   if( t=="vessel" ) {
     126       93789 :     fd = d + " The final value can be referenced using <em>label</em>." + lowkey;
     127       58848 :     if(d.find("flag")==std::string::npos) fd += ".  You can use multiple instances of this keyword i.e. " +
     128      165510 :           k +"1, " + k + "2, " + k + "3...  The corresponding values are then "
     129      137925 :           "referenced using <em>label</em>."+ lowkey +"-1,  <em>label</em>." + lowkey +
     130       82755 :           "-2,  <em>label</em>." + lowkey + "-3...";
     131       31263 :     allowmultiple.insert( std::pair<std::string,bool>(k,true) );
     132       93789 :     types.insert( std::pair<std::string,KeyType>(k,KeyType("vessel")) );
     133       26817 :   } else if( t=="numbered" ) {
     134       19648 :     fd = d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3...";
     135        2456 :     allowmultiple.insert( std::pair<std::string,bool>(k,true) );
     136        7368 :     types.insert( std::pair<std::string,KeyType>(k,KeyType("optional")) );
     137             :   } else {
     138             :     fd = d;
     139       24361 :     if( t=="atoms" && isaction ) fd = d + ".  For more information on how to specify lists of atoms see \\ref Group";
     140       24361 :     allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     141       48722 :     types.insert( std::pair<std::string,KeyType>(k,KeyType(t)) );
     142       25606 :     if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,t) );
     143             :   }
     144      116160 :   documentation.insert( std::pair<std::string,std::string>(k,fd) );
     145       58080 :   reserved_keys.push_back(k);
     146       58080 : }
     147             : 
     148        1758 : void Keywords::reserveFlag( const std::string & k, const bool def, const std::string & d ) {
     149        1758 :   plumed_assert( !exists(k) && !reserved(k) );
     150             :   std::string defstr;
     151        1758 :   if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; }
     152        5274 :   types.insert( std::pair<std::string,KeyType>(k,KeyType("flag")) );
     153        1758 :   std::string fd,lowkey=k; std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower);
     154        3516 :   fd=defstr + d;
     155        3516 :   documentation.insert( std::pair<std::string,std::string>(k,fd) );
     156        1758 :   allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     157        1758 :   booldefs.insert( std::pair<std::string,bool>(k,def) );
     158        1758 :   reserved_keys.push_back(k);
     159        1758 : }
     160             : 
     161       12487 : void Keywords::use( const std::string & k ) {
     162       12487 :   plumed_massert( reserved(k), "the " + k + " keyword is not reserved");
     163      480443 :   for(unsigned i=0; i<reserved_keys.size(); ++i) {
     164      151823 :     if(reserved_keys[i]==k) keys.push_back( reserved_keys[i] );
     165             :   }
     166       12487 : }
     167             : 
     168        2243 : void Keywords::reset_style( const std::string & k, const std::string & style ) {
     169        2243 :   plumed_massert( exists(k) || reserved(k), "no " + k + " keyword" );
     170        2243 :   (types.find(k)->second).setStyle(style);
     171        4082 :   if( (types.find(k)->second).isVessel() ) allowmultiple[k]=true;
     172        2435 :   if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,style) );
     173        2243 : }
     174             : 
     175      223095 : void Keywords::add( const std::string & t, const std::string & k, const std::string & d ) {
     176      669285 :   plumed_massert( !exists(k) && t!="flag" && !reserved(k) && t!="vessel", "keyword " + k + " has already been registered");
     177             :   std::string fd;
     178      223095 :   if( t=="numbered" ) {
     179        9280 :     fd=d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3...";
     180        1160 :     allowmultiple.insert( std::pair<std::string,bool>(k,true) );
     181        3480 :     types.insert( std::pair<std::string,KeyType>(k, KeyType("optional")) );
     182             :   } else {
     183             :     fd=d;
     184      221935 :     allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     185      443870 :     types.insert( std::pair<std::string,KeyType>(k,KeyType(t)) );
     186      279761 :     if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,t) );
     187             :   }
     188      228599 :   if( t=="atoms" && isaction ) fd = d + ".  For more information on how to specify lists of atoms see \\ref Group";
     189      446190 :   documentation.insert( std::pair<std::string,std::string>(k,fd) );
     190      223095 :   keys.push_back(k);
     191      223095 : }
     192             : 
     193       94071 : void Keywords::add( const std::string & t, const std::string & k, const std::string &  def, const std::string & d ) {
     194      188142 :   plumed_assert( !exists(k) && !reserved(k) &&  (t=="compulsory" || t=="hidden" )); // An optional keyword can't have a default
     195      188142 :   types.insert(  std::pair<std::string,KeyType>(k, KeyType(t)) );
     196      470355 :   documentation.insert( std::pair<std::string,std::string>(k,"( default=" + def + " ) " + d) );
     197       94071 :   allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     198      188142 :   numdefs.insert( std::pair<std::string,std::string>(k,def) );
     199       94071 :   keys.push_back(k);
     200       94071 : }
     201             : 
     202       87013 : void Keywords::addFlag( const std::string & k, const bool def, const std::string & d ) {
     203       87013 :   plumed_massert( !exists(k) && !reserved(k), "keyword " + k + " has already been registered");
     204             :   std::string defstr;
     205       87013 :   if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; }
     206      261039 :   types.insert( std::pair<std::string,KeyType>(k,KeyType("flag")) );
     207      261039 :   documentation.insert( std::pair<std::string,std::string>(k,defstr + d) );
     208       87013 :   allowmultiple.insert( std::pair<std::string,bool>(k,false) );
     209       87013 :   booldefs.insert( std::pair<std::string,bool>(k,def) );
     210       87013 :   keys.push_back(k);
     211       87013 : }
     212             : 
     213        1200 : void Keywords::remove( const std::string & k ) {
     214             :   bool found=false; unsigned j=0, n=0;
     215             : 
     216             :   while(true) {
     217       33148 :     for(j=0; j<keys.size(); j++) if(keys[j]==k)break;
     218       89381 :     for(n=0; n<reserved_keys.size(); n++) if(reserved_keys[n]==k)break;
     219        2400 :     if(j<keys.size()) {
     220        1183 :       keys.erase(keys.begin()+j);
     221             :       found=true;
     222        1217 :     } else if(n<reserved_keys.size()) {
     223          17 :       reserved_keys.erase(reserved_keys.begin()+n);
     224             :       found=true;
     225             :     } else break;
     226             :   }
     227             :   // Delete documentation, type and so on from the description
     228             :   types.erase(k); documentation.erase(k); allowmultiple.erase(k); booldefs.erase(k); numdefs.erase(k);
     229        1200 :   plumed_massert(found,"You are trying to forbid " + k + " a keyword that isn't there"); // You have tried to forbid a keyword that isn't there
     230        1200 : }
     231             : 
     232        7625 : bool Keywords::numbered( const std::string & k ) const {
     233       15250 :   if( style( k,"atoms") ) return true;
     234           0 :   plumed_massert( allowmultiple.count(k), "Did not find keyword " + k );
     235        5693 :   return allowmultiple.find(k)->second;
     236             : }
     237             : 
     238      476601 : bool Keywords::style( const std::string & k, const std::string & t ) const {
     239           0 :   plumed_massert( types.count(k), "Did not find keyword " + k );
     240             : 
     241      953202 :   if( (types.find(k)->second).toString()==t ) return true;
     242      369034 :   return false;
     243             : }
     244             : 
     245      601999 : unsigned Keywords::size() const {
     246      601999 :   return keys.size();
     247             : }
     248             : 
     249        8992 : std::string Keywords::getKeyword( const unsigned i ) const {
     250        8992 :   plumed_assert( i<size() );
     251       17984 :   return keys[i];
     252             : }
     253             : 
     254      606175 : bool Keywords::exists( const std::string & k ) const {
     255    19197956 :   for(unsigned i=0; i<keys.size(); ++i) {
     256     6117713 :     if( keys[i]==k ) return true;
     257             :   }
     258             :   return false;
     259             : }
     260             : 
     261      478463 : bool Keywords::reserved( const std::string & k ) const {
     262     3265156 :   for(unsigned i=0; i<reserved_keys.size(); ++i) {
     263      783856 :     if( reserved_keys[i]==k ) return true;
     264             :   }
     265             :   return false;
     266             : }
     267             : 
     268           0 : void Keywords::print_template(const std::string& actionname, bool include_optional) const {
     269             :   unsigned nkeys=0;
     270             :   printf("%s",actionname.c_str());
     271           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     272           0 :     if ( (types.find(keys[i])->second).isAtomList() ) nkeys++;
     273             :   }
     274           0 :   if( nkeys>0 ) {
     275           0 :     std::string prevtag="start";
     276           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     277           0 :       if( (types.find(keys[i])->second).isAtomList() ) {
     278           0 :         plumed_massert( atomtags.count(keys[i]), "keyword " + keys[i] + " allegedly specifies atoms but no tag has been specified. Please email Gareth Tribello");
     279           0 :         if( prevtag!="start" && prevtag!=atomtags.find(keys[i])->second ) break;
     280           0 :         if( (atomtags.find(keys[i])->second).find("residues")!=std::string::npos) printf(" %s=<residue selection>", keys[i].c_str() );
     281             :         else printf(" %s=<atom selection>", keys[i].c_str() );
     282           0 :         prevtag=atomtags.find(keys[i])->second;
     283             :       }
     284             :     }
     285             :   }
     286             :   nkeys=0;
     287           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     288           0 :     if ( include_optional || \
     289           0 :          (types.find(keys[i])->second).isCompulsory() ) nkeys++;
     290             :   }
     291           0 :   if( nkeys>0 ) {
     292           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     293           0 :       if ( (types.find(keys[i])->second).isCompulsory() ) {
     294             :         std::string def;
     295           0 :         if( getDefaultValue( keys[i], def) ) {
     296             :           printf(" %s=%s ", keys[i].c_str(), def.c_str() );
     297             :         } else {
     298             :           printf(" %s=    ", keys[i].c_str() );
     299             :         }
     300           0 :       } else if (include_optional) {
     301             :         // TG no defaults for optional keywords?
     302             :         printf(" [%s]", keys[i].c_str() );
     303             :       }
     304             :     }
     305             :   }
     306             :   printf("\n");
     307           0 : }
     308             : 
     309         253 : void Keywords::print_vim() const {
     310       11291 :   for(unsigned i=0; i<keys.size(); ++i) {
     311        3595 :     if( (types.find(keys[i])->second).isFlag() ) {
     312             :       printf( ",flag:%s", keys[i].c_str() );
     313             :     } else {
     314        2783 :       if( allowmultiple.find(keys[i])->second ) printf(",numbered:%s",keys[i].c_str() );
     315             :       else printf(",option:%s",keys[i].c_str() );
     316             :     }
     317             :   }
     318         253 :   fprintf(stdout,"\n");
     319         253 :   print(stdout);
     320         253 : }
     321             : 
     322           0 : void Keywords::print_html() const {
     323             : 
     324             : // This is the part that outputs the details of the components
     325           0 :   if( cnames.size()>0 ) {
     326             :     unsigned ndef=0;
     327           0 :     for(unsigned i=0; i<cnames.size(); ++i) {
     328           0 :       if(ckey.find(cnames[i])->second=="default") ndef++;
     329             :     }
     330             : 
     331           0 :     if( ndef>0 ) {
     332           0 :       std::cout<<"\\par Description of components\n\n";
     333           0 :       std::cout<<cstring<<"\n\n";
     334           0 :       std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
     335             :       printf("<tr> <td width=5%%> <b> Quantity </b> </td> <td> <b> Description </b> </td> </tr>\n");
     336             :       unsigned nndef=0;
     337           0 :       for(unsigned i=0; i<cnames.size(); ++i) {
     338             :         //plumed_assert( ckey.find(cnames[i])->second=="default" );
     339           0 :         if( ckey.find(cnames[i])->second!="default" ) { nndef++; continue; }
     340             :         printf("<tr>\n");
     341             :         printf("<td width=15%%> <b> %s </b></td>\n",cnames[i].c_str() );
     342             :         printf("<td> %s </td>\n",(cdocs.find(cnames[i])->second).c_str() );
     343             :         printf("</tr>\n");
     344             :       }
     345           0 :       std::cout<<"</table>\n\n";
     346           0 :       if( nndef>0 ) {
     347             :         std::cout<<"In addition the following quantities can be calculated by employing the keywords listed below"<<std::endl;
     348           0 :         std::cout<<"\n\n";
     349           0 :         std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
     350             :         printf("<tr> <td width=5%%> <b> Quantity </b> </td> <td> <b> Keyword </b> </td> <td> <b> Description </b> </td> </tr>\n");
     351           0 :         for(unsigned i=0; i<cnames.size(); ++i) {
     352           0 :           if( ckey.find(cnames[i])->second!="default") {
     353             :             printf("<tr>\n");
     354             :             printf("<td width=5%%> <b> %s </b></td> <td width=10%%> <b> %s </b> </td> \n",
     355             :                    cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() );
     356             :             printf("<td> %s </td>\n",(cdocs.find(cnames[i])->second).c_str() );
     357             :             printf("</tr>\n");
     358             :           }
     359             :         }
     360           0 :         std::cout<<"</table>\n\n";
     361             :       }
     362             :     } else {
     363             :       unsigned nregs=0;
     364           0 :       for(unsigned i=0; i<cnames.size(); ++i) {
     365           0 :         if( exists(ckey.find(cnames[i])->second) ) nregs++;
     366             :       }
     367           0 :       if( nregs>0 ) {
     368           0 :         std::cout<<"\\par Description of components\n\n";
     369           0 :         std::cout<<cstring<<"\n\n";
     370           0 :         std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
     371             :         printf("<tr> <td width=5%%> <b> Quantity </b> </td> <td> <b> Keyword </b> </td> <td> <b> Description </b> </td> </tr>\n");
     372           0 :         for(unsigned i=0; i<cnames.size(); ++i) {
     373           0 :           if( exists(ckey.find(cnames[i])->second) ) {
     374             :             printf("<tr>\n");
     375             :             printf("<td width=5%%> <b> %s </b></td> <td width=10%%> <b> %s </b> </td> \n",
     376             :                    cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() );
     377             :             printf("<td> %s </td>\n",(cdocs.find(cnames[i])->second).c_str() );
     378             :             printf("</tr>\n");
     379             :           }
     380             :         }
     381           0 :         std::cout<<"</table>\n\n";
     382             :       }
     383             :     }
     384             :   }
     385             : 
     386             :   unsigned nkeys=0;
     387           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     388           0 :     if ( (types.find(keys[i])->second).isAtomList() ) nkeys++;
     389             :   }
     390           0 :   if( nkeys>0 ) {
     391           0 :     if(isaction && isatoms) std::cout<<"\\par The atoms involved can be specified using\n\n";
     392           0 :     else if(isaction) std::cout<<"\\par The data to analyze can be the output from another analysis algorithm\n\n";
     393           0 :     else std::cout<<"\\par The input trajectory is specified using one of the following\n\n";
     394           0 :     std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
     395           0 :     std::string prevtag="start"; unsigned counter=0;
     396           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     397           0 :       if ( (types.find(keys[i])->second).isAtomList() ) {
     398           0 :         plumed_massert( atomtags.count(keys[i]), "keyword " + keys[i] + " allegedly specifies atoms but no tag has been specified. Please email Gareth Tribello");
     399           0 :         if( prevtag!="start" && prevtag!=atomtags.find(keys[i])->second && isaction ) {
     400           0 :           std::cout<<"</table>\n\n";
     401           0 :           if( isatoms ) std::cout<<"\\par Or alternatively by using\n\n";
     402           0 :           else if( counter==0 ) { std::cout<<"\\par Alternatively data can be collected from the trajectory using \n\n"; counter++; }
     403           0 :           else std::cout<<"\\par Lastly data collected in a previous analysis action can be reanalyzed by using the keyword \n\n";
     404           0 :           std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
     405             :         }
     406           0 :         print_html_item( keys[i] );
     407           0 :         prevtag=atomtags.find(keys[i])->second;
     408             :       }
     409             :     }
     410           0 :     std::cout<<"</table>\n\n";
     411             :   }
     412             :   nkeys=0;
     413           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     414           0 :     if ( (types.find(keys[i])->second).isCompulsory() ) nkeys++;
     415             :   }
     416           0 :   if( nkeys>0 ) {
     417           0 :     if(isaction) std::cout<< "\\par Compulsory keywords\n\n";
     418           0 :     else std::cout<<"\\par The following must be present\n\n";
     419           0 :     std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
     420           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     421           0 :       if ( (types.find(keys[i])->second).isCompulsory() ) print_html_item( keys[i] );
     422             :     }
     423           0 :     std::cout<<"</table>\n\n";
     424             :   }
     425             :   nkeys=0;
     426           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     427           0 :     if ( (types.find(keys[i])->second).isFlag() || (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++;
     428             :   }
     429           0 :   if( nkeys>0 ) {
     430           0 :     if(isaction) std::cout<<"\\par Options\n\n";
     431           0 :     else std::cout<<"\\par The following options are available\n\n";
     432           0 :     std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
     433           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     434           0 :       if ( (types.find(keys[i])->second).isFlag() ) print_html_item( keys[i] );
     435             :     }
     436           0 :     std::cout<<"\n";
     437             :   }
     438             :   nkeys=0;
     439           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     440           0 :     if ( (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++;
     441             :   }
     442           0 :   if( nkeys>0 ) {
     443           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     444           0 :       if ( (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) print_html_item( keys[i] );
     445             :     }
     446             :   }
     447           0 :   std::cout<<"</table>\n\n";
     448           0 : }
     449             : 
     450           0 : void Keywords::print_spelling() const {
     451           0 :   for(unsigned i=0; i<keys.size(); ++i) printf("%s\n", keys[i].c_str() );
     452           0 :   for(unsigned i=0; i<cnames.size(); ++i) printf("%s\n",cnames[i].c_str() );
     453           0 : }
     454             : 
     455         253 : void Keywords::print( FILE* out ) const {
     456             :   unsigned nkeys=0;
     457       11291 :   for(unsigned i=0; i<keys.size(); ++i) {
     458        3595 :     if ( (types.find(keys[i])->second).isAtomList() ) nkeys++;
     459             :   }
     460         253 :   if( nkeys>0 ) {
     461             :     fprintf(out,"The input trajectory can be in any of the following formats: \n\n");
     462        6444 :     for(unsigned i=0; i<keys.size(); ++i) {
     463        2304 :       if ( (types.find(keys[i])->second).isAtomList() ) printKeyword( keys[i], out );
     464             :     }
     465             :   }
     466             :   nkeys=0;
     467       11291 :   for(unsigned i=0; i<keys.size(); ++i) {
     468        3595 :     if ( (types.find(keys[i])->second).isCompulsory() ) nkeys++;
     469             :   }
     470             :   unsigned ncompulsory=nkeys;
     471         253 :   if( nkeys>0 ) {
     472             :     fprintf(out,"\nThe following arguments are compulsory: \n\n");
     473        8960 :     for(unsigned i=0; i<keys.size(); ++i) {
     474        3576 :       if ( (types.find(keys[i])->second).isCompulsory() ) printKeyword( keys[i], out );   //log.printKeyword( keys[i], documentation[i] );
     475             :     }
     476             :   }
     477             :   nkeys=0;
     478       11291 :   for(unsigned i=0; i<keys.size(); ++i) {
     479        3595 :     if ( (types.find(keys[i])->second).isFlag() ) nkeys++;
     480             :   }
     481         253 :   if( nkeys>0 ) {
     482         219 :     if(ncompulsory>0) fprintf( out,"\nIn addition you may use the following options: \n\n");
     483             :     else fprintf( out,"\nThe following options are available\n\n");
     484       10731 :     for(unsigned i=0; i<keys.size(); ++i) {
     485        4243 :       if ( (types.find(keys[i])->second).isFlag() ) printKeyword( keys[i], out );   //log.printKeyword( keys[i], documentation[i] );
     486             :     }
     487             :   }
     488             :   nkeys=0;
     489       11291 :   for(unsigned i=0; i<keys.size(); ++i) {
     490        6542 :     if ( (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++;
     491             :   }
     492         253 :   if( nkeys>0 ) {
     493        9662 :     for(unsigned i=0; i<keys.size(); ++i) {
     494        6712 :       if ( (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) printKeyword( keys[i], out );   //log.printKeyword( keys[i], documentation[i] );
     495             :     }
     496             :     fprintf(out,"\n");
     497             :   }
     498         253 : }
     499             : 
     500        2928 : void Keywords::printKeyword( const std::string& key, FILE* out ) const {
     501        2928 :   bool killdot=( (documentation.find(key)->second).find("\\f$")!=std::string::npos ); // Check for latex
     502        5856 :   std::vector<std::string> w=Tools::getWords( documentation.find(key)->second );
     503             :   fprintf(out,"%23s - ", key.c_str() );
     504        2928 :   unsigned nl=0; std::string blank=" ";
     505      186759 :   for(unsigned i=0; i<w.size(); ++i) {
     506       60583 :     nl+=w[i].length() + 1;
     507       60583 :     if( nl>60 ) {
     508             :       fprintf(out,"\n%23s   %s ", blank.c_str(), w[i].c_str() ); nl=0;
     509             :     } else {
     510             :       fprintf(out,"%s ", w[i].c_str() );
     511             :     }
     512       62917 :     if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot
     513             :   }
     514             :   fprintf(out,"\n");
     515        2928 : }
     516             : 
     517           0 : void Keywords::print( Log& log ) const {
     518             :   unsigned nkeys=0;
     519           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     520           0 :     if ( (types.find(keys[i])->second).isAtomList() ) nkeys++;
     521             :   }
     522           0 :   if (nkeys>0 ) {
     523           0 :     log.printf( "The input for this keyword can be specified using one of the following \n\n");
     524           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     525           0 :       if ( (types.find(keys[i])->second).isAtomList() ) printKeyword( keys[i], log );   //log.printKeyword( keys[i], documentation[i] );
     526             :     }
     527             :   }
     528             :   nkeys=0;
     529           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     530           0 :     if ( (types.find(keys[i])->second).isCompulsory() ) nkeys++;
     531             :   }
     532           0 :   if( nkeys>0 ) {
     533           0 :     log.printf( "\n The compulsory keywords for this action are: \n\n");
     534           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     535           0 :       if ( (types.find(keys[i])->second).isCompulsory() ) printKeyword( keys[i], log );   //log.printKeyword( keys[i], documentation[i] );
     536             :     }
     537             :   }
     538             :   nkeys=0;
     539           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     540           0 :     if ( (types.find(keys[i])->second).isFlag() ) nkeys++;
     541             :   }
     542           0 :   if( nkeys>0 ) {
     543           0 :     log.printf( "\n The following options are available: \n\n");
     544           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     545           0 :       if ( (types.find(keys[i])->second).isFlag() ) printKeyword( keys[i], log );   //log.printKeyword( keys[i], documentation[i] );
     546             :     }
     547           0 :     log.printf("\n");
     548             :   }
     549             :   nkeys=0;
     550           0 :   for(unsigned i=0; i<keys.size(); ++i) {
     551           0 :     if ( (types.find(keys[i])->second).isOptional() ) nkeys++;
     552             :   }
     553           0 :   if( nkeys>0 ) {
     554           0 :     for(unsigned i=0; i<keys.size(); ++i) {
     555           0 :       if ( (types.find(keys[i])->second).isOptional() ) printKeyword( keys[i], log );   //log.printKeyword( keys[i], documentation[i] );
     556             :     }
     557           0 :     log.printf("\n");
     558             :   }
     559           0 : }
     560             : 
     561           0 : void Keywords::printKeyword( const std::string& key, Log& log ) const {
     562           0 :   bool killdot=( (documentation.find(key)->second).find("\\f$")!=std::string::npos ); // Check for latex
     563           0 :   std::vector<std::string> w=Tools::getWords( documentation.find(key)->second );
     564           0 :   log.printf("%23s - ", key.c_str() );
     565           0 :   unsigned nl=0; std::string blank=" ";
     566           0 :   for(unsigned i=0; i<w.size(); ++i) {
     567           0 :     nl+=w[i].length() + 1;
     568           0 :     if( nl>60 ) {
     569           0 :       log.printf("\n%23s   %s ", blank.c_str(), w[i].c_str() ); nl=0;
     570             :     } else {
     571           0 :       log.printf("%s ", w[i].c_str() );
     572             :     }
     573           0 :     if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot
     574             :   }
     575           0 :   log.printf("\n");
     576           0 : }
     577             : 
     578           0 : void Keywords::print_html_item( const std::string& key ) const {
     579             :   printf("<tr>\n");
     580             :   printf("<td width=15%%> <b> %s </b></td>\n",key.c_str() );
     581             :   printf("<td> %s </td>\n",(documentation.find(key)->second).c_str() );
     582             :   printf("</tr>\n");
     583           0 : }
     584             : 
     585      283438 : std::string Keywords::get( const unsigned k ) const {
     586      283438 :   plumed_assert( k<size() );
     587      566876 :   return keys[k];
     588             : }
     589             : 
     590       13353 : bool Keywords::getLogicalDefault( std::string key, bool& def ) const {
     591       13353 :   if( booldefs.find(key)!=booldefs.end() ) {
     592       13353 :     def=booldefs.find(key)->second;
     593       13353 :     return true;
     594             :   } else {
     595             :     return false;
     596             :   }
     597             : }
     598             : 
     599        8755 : bool Keywords::getDefaultValue( std::string key, std::string& def ) const {
     600       26265 :   plumed_assert( style(key,"compulsory") || style(key,"hidden") );
     601             : 
     602        8755 :   if( numdefs.find(key)!=numdefs.end() ) {
     603        4309 :     def=numdefs.find(key)->second;
     604             :     return true;
     605             :   } else {
     606             :     return false;
     607             :   }
     608             : }
     609             : 
     610           0 : void Keywords::destroyData() {
     611           0 :   keys.clear(); reserved_keys.clear(); types.clear();
     612             :   allowmultiple.clear(); documentation.clear();
     613             :   booldefs.clear(); numdefs.clear(); atomtags.clear();
     614             :   ckey.clear(); cdocs.clear(); ckey.clear();
     615           0 : }
     616             : 
     617        5666 : void Keywords::setComponentsIntroduction( const std::string& instr ) {
     618        5666 :   cstring = instr;
     619        5666 : }
     620             : 
     621       41267 : void Keywords::addOutputComponent( const std::string& name, const std::string& key, const std::string& descr ) {
     622       41267 :   plumed_assert( !outputComponentExists( name, false ) );
     623       41267 :   plumed_massert( name.find("-")==std::string::npos,"dash is reseved character in component names" );
     624             : 
     625             :   std::size_t num2=name.find_first_of("_");
     626       41267 :   if( num2!=std::string::npos ) plumed_massert( num2==0, "underscore is reserved character in component names that has special meaning");
     627             : 
     628       82534 :   ckey.insert( std::pair<std::string,std::string>(name,key) );
     629       82534 :   cdocs.insert( std::pair<std::string,std::string>(name,descr) );
     630       41267 :   cnames.push_back(name);
     631       41267 : }
     632             : 
     633       74587 : bool Keywords::outputComponentExists( const std::string& name, const bool& custom ) const {
     634      107595 :   if( custom && cstring.find("customize")!=std::string::npos ) return true;
     635             : 
     636             :   std::string sname; std::size_t num=name.find_first_of("-");
     637       45284 :   if( num!=std::string::npos ) sname=name.substr(0,num);
     638             :   else {
     639             :     std::size_t num2=name.find_first_of("_");
     640       46892 :     if( num2!=std::string::npos ) sname=name.substr(num2);
     641             :     else sname=name;
     642             :   }
     643             : 
     644     1055930 :   for(unsigned i=0; i<cnames.size(); ++i) {
     645      325566 :     if( sname==cnames[i] ) return true;
     646             :   }
     647             :   return false;
     648             : }
     649             : 
     650        5517 : }

Generated by: LCOV version 1.14