Sophie

Sophie

distrib > Fedora > 20 > x86_64 > by-pkgid > 29c20b29a62bbdf39f70400098af0a5a > files > 2754

psi4-doc-4.0-0.11.0c7ea92git.fc20.noarch.rpm




<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>Best Practices for Python Functions &mdash; PSI4 [] documentation</title>
    
    <link rel="stylesheet" href="_static/psi4.css" type="text/css" />
    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
    <link rel="stylesheet" href="#" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '',
        VERSION:     '',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="_static/jquery.js"></script>
    <script type="text/javascript" src="_static/underscore.js"></script>
    <script type="text/javascript" src="_static/doctools.js"></script>
    <script type="text/javascript" src="_static/jquery.cookie.js"></script>
    <script type="text/javascript" src="_static/toggle_sections.js"></script>
    <script type="text/javascript" src="_static/toggle_sidebar.js"></script>
    <script type="text/javascript" src="_static/toggle_codeprompt.js"></script>
    <link rel="top" title="PSI4 [] documentation" href="index.html" />
    <link rel="up" title="Contributions: Intro to Programming in PSI4" href="contributing.html" />
    <link rel="next" title="Documentation" href="documentation.html" />
    <link rel="prev" title="Plugins: Adding New Functionality to PSI4" href="plugins.html" /> 
  </head>
  <body>
    <div class="relbar-top">
        
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="py-modindex.html" title="Python Module Index"
             >modules</a> &nbsp; &nbsp;</li>
        <li class="right" >
          <a href="contents.html" title="Table Of Contents"
             accesskey="C">toc</a> &nbsp; &nbsp;</li>
        <li class="right" >
          <a href="documentation.html" title="Documentation"
             accesskey="N">next</a> &nbsp; &nbsp;</li>
        <li class="right" >
          <a href="plugins.html" title="Plugins: Adding New Functionality to PSI4"
             accesskey="P">previous</a> &nbsp; &nbsp;</li>
    <li><a href="index.html">PSI4 []</a> &raquo; </li>

          <li><a href="contributing.html" accesskey="U">Contributions: Intro to Programming in PSI4</a> &raquo;</li> 
      </ul>
    </div>
    </div>
  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <img alt="PSI4 Project Logo" src="_images/psi4banner.png" style="width: 100%;" />
<div class="section" id="best-practices-for-python-functions">
<span id="sec-bestpractices-py"></span><h1>Best Practices for Python Functions<a class="headerlink" href="#best-practices-for-python-functions" title="Permalink to this headline">ΒΆ</a></h1>
<ul>
<li><p class="first">Thy python functions shall always have final argument **kwargs, that they may take in and pass on keywords meant for other functions. Yea, even the run_mcscf(), and run_ccsd() -type functions that have no use for kwargs. The exceptions are python functions that are only helpers called by a driver function.</p>
</li>
<li><p class="first">Python functions should read the kwargs dictionary and (possibly) add to it. Functions should not pop or remove keywords from kwargs, even those keywords meaningful only to itself. This will ensure that the complete kwargs is available for pickling and sow/reap procedures. The exception is the molecule argument, which is read by the first function that gets ahold of it. This first function activates the molecule and pops it out of kwargs, effectively setting molecule for all subsequent functions. The code below should suffice.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c"># Make sure the molecule the user provided is the active one</span>
<span class="k">if</span> <span class="s">&#39;molecule&#39;</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="p">:</span>
    <span class="n">activate</span><span class="p">(</span><span class="n">kwargs</span><span class="p">[</span><span class="s">&#39;molecule&#39;</span><span class="p">])</span>
    <span class="k">del</span> <span class="n">kwargs</span><span class="p">[</span><span class="s">&#39;molecule&#39;</span><span class="p">]</span>
<span class="n">molecule</span> <span class="o">=</span> <span class="n">psi4</span><span class="o">.</span><span class="n">get_active_molecule</span><span class="p">()</span>
<span class="n">molecule</span><span class="o">.</span><span class="n">update_geometry</span><span class="p">()</span>
</pre></div>
</div>
</li>
<li><p class="first">Preferrably, the python function signature (for functions intended to be called in input files) is <tt class="docutils literal"><span class="pre">function(name,</span> <span class="pre">**kwargs)</span></tt>. For functions that have other positional keywords, please bundle them into kwargs at earliest convenience (see <a class="reference internal" href="db.html#sec-db"><em>Database</em></a> argument db_name for example).</p>
</li>
<li><p class="first">After the docstring, the first two lines of your function should be the ones below. The first provides a case insensitive handle to the name argument value. The second converts all the kwargs dictionary keys to lowercase versions of themselves, so that input files can be case insensitive.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">lowername</span> <span class="o">=</span> <span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
<span class="n">kwargs</span> <span class="o">=</span> <span class="n">kwargs_lower</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li><p class="first">Case sensitivity for kwargs dictionary values still needs to be handled. The first line below shows how to convert argument values to lowercase for matching. When not matching a whole value such that regular expressions are needed, the second line below performs a case insensitive match.</p>
<div class="highlight-python"><pre>if (kwargs['db_mode'].lower() == 'continuous'):
if re.match(r'^sapt', name, flags=re.IGNORECASE):</pre>
</div>
</li>
<li><p class="first">Match boolean keywords (db_cp in the example below) with expressions like the following, which allow case insensitive yes/true/on/1/no/false/off/0 user input. If your argument&#8217;s value is a derivative level, similarly, use input.der0th, input.der1st, and input.der2nd.</p>
<div class="highlight-python"><pre>if input.yes.match(str(db_cp)):
elif input.no.match(str(db_cp)):</pre>
</div>
</li>
<li><p class="first">For keywords that might be used in other functions as well as your own, prepend the argument name with a short representation of your function name. For example, there are keywords cp_func, db_func, and opt_func to request what python function, if not energy(), is called by cp(), database(), and optimize().</p>
</li>
<li><p class="first">Upon checking in a new python file, edit the file <tt class="docutils literal"><span class="pre">psi4/doc/userman/source/index.rst</span></tt> and follow the instructions therein that your file may be autodocumented here.</p>
</li>
<li><p class="first">Write docstrings! For a major function intended for use in input files, start with the skeleton docstring in <tt class="docutils literal"><span class="pre">psi4/lib/python/example_docstring</span></tt> and replace anything that looks like <tt class="docutils literal"><span class="pre">&lt;this&gt;</span></tt>. For a behind-the-scenes function or if you don&#8217;t want the bother of dealing with <a class="reference external" href="http://docutils.sourceforge.net/docs/user/rst/quickref.html">reStructuredText</a>, just write an ordinary docstring. It will get slurped into the documentation in plain text.</p>
</li>
<li><p class="first">Your python function should follow <a class="reference external" href="http://www.python.org/dev/peps/pep-0008/">PEP8</a> conventions (without the line-length restriction). I&#8217;m aiming for files to pass the line below, unless for good reason. The second line is for database Python files.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">pep8</span><span class="o">.</span><span class="n">py</span> <span class="o">-</span><span class="n">r</span> <span class="o">--</span><span class="n">ignore</span><span class="o">=</span><span class="n">E501</span> <span class="n">pythonfile</span><span class="o">.</span><span class="n">py</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">pep8</span><span class="o">.</span><span class="n">py</span> <span class="o">-</span><span class="n">r</span> <span class="o">--</span><span class="n">ignore</span><span class="o">=</span><span class="n">E501</span><span class="p">,</span><span class="n">E221</span><span class="p">,</span><span class="n">E222</span><span class="p">,</span><span class="n">E241</span><span class="p">,</span><span class="n">E201</span><span class="p">,</span><span class="n">E202</span> <span class="n">databasefile</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
</li>
<li><p class="first">Your python function should not prevent any test case (<tt class="docutils literal"><span class="pre">make</span> <span class="pre">tests</span></tt>, NOT <tt class="docutils literal"><span class="pre">make</span> <span class="pre">longtests</span></tt>) from passing. A test case(s) should be written and checked in for any major python function, so that others do not break your code. If most of your work was on the python (as opposed to c++) side, the test case prefix pywrap_ is suggested.</p>
</li>
<li><p class="first">Be sure to set any new PSI variables through lines like those below. Especially if the function returns an energy, set the &#8216;current energy&#8217; variable. This last is needed to communicate with the optimizer.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">psi4</span><span class="o">.</span><span class="n">set_variable</span><span class="p">(</span><span class="s">&#39;MP2.5 CORRELATION ENERGY&#39;</span><span class="p">,</span> <span class="n">ce_mp25</span><span class="p">)</span>
<span class="n">psi4</span><span class="o">.</span><span class="n">set_variable</span><span class="p">(</span><span class="s">&#39;MP2.5 TOTAL ENERGY&#39;</span><span class="p">,</span> <span class="n">e_mp25</span><span class="p">)</span>
<span class="n">psi4</span><span class="o">.</span><span class="n">set_variable</span><span class="p">(</span><span class="s">&#39;CURRENT ENERGY&#39;</span><span class="p">,</span> <span class="n">e_mp25</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li><p class="first">Once your python function is fairly stable on its own, it&#8217;s potential for interoperability with energy()/opt()/cp()/db()/cbs()/etc. should be evaluated. If it makes physical sense that it should work, you should strive to make that interoperability a reality. Some steps:</p>
<blockquote>
<div><ul>
<li><p class="first">If any interoperability is possible, define an argument xx_func, where xx is a short name for your function. Add near the top of your function code like the below (less the final two lines). The net result of this code is that if the user specifies no *_func arguments, then energy() gets called. If the user defines xx_func, then its value gets called. If the user defines func, then its value gets reassigned to xx_func, func itself is deleted, and xx_func() gets called. Whatever is getting called is stored in func within the function.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c"># Establish function to call</span>
<span class="k">if</span> <span class="ow">not</span><span class="p">(</span><span class="s">&#39;xx_func&#39;</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="p">):</span>
    <span class="k">if</span> <span class="p">(</span><span class="s">&#39;func&#39;</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="p">):</span>
        <span class="n">kwargs</span><span class="p">[</span><span class="s">&#39;xx_func&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s">&#39;func&#39;</span><span class="p">]</span>
        <span class="k">del</span> <span class="n">kwargs</span><span class="p">[</span><span class="s">&#39;func&#39;</span><span class="p">]</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">kwargs</span><span class="p">[</span><span class="s">&#39;xx_func&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">energy</span>
<span class="n">func</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s">&#39;xx_func&#39;</span><span class="p">]</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">func</span><span class="p">:</span>
    <span class="k">raise</span> <span class="n">ValidationError</span><span class="p">(</span><span class="s">&#39;Function </span><span class="se">\&#39;</span><span class="si">%s</span><span class="se">\&#39;</span><span class="s"> does not exist to be called by wrapper counterpoise_correct.&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">func</span><span class="o">.</span><span class="n">__name__</span><span class="p">))</span>
<span class="k">if</span> <span class="p">(</span><span class="n">func</span> <span class="ow">is</span> <span class="n">db</span><span class="p">):</span>
    <span class="k">raise</span> <span class="n">ValidationError</span><span class="p">(</span><span class="s">&#39;Wrapper xx is unhappy to be calling function </span><span class="se">\&#39;</span><span class="si">%s</span><span class="se">\&#39;</span><span class="s">.&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">func</span><span class="o">.</span><span class="n">__name__</span><span class="p">))</span>
</pre></div>
</div>
</li>
<li><p class="first">If specific interoperabilities are known, code them in. For example, if xx shouldn&#8217;t call db, add the last two lines above to the xx function. If db shouldn&#8217;t call xx, add the following two lines below to the db function.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">if</span> <span class="p">(</span><span class="n">func</span> <span class="ow">is</span> <span class="n">xx</span><span class="p">):</span>
    <span class="k">raise</span> <span class="n">ValidationError</span><span class="p">(</span><span class="s">&#39;Wrapper database is unhappy to be calling function </span><span class="se">\&#39;</span><span class="si">%s</span><span class="se">\&#39;</span><span class="s">.&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">func</span><span class="o">.</span><span class="n">__name__</span><span class="p">))</span>
</pre></div>
</div>
</li>
<li><p class="first">Create a multipart test case that runs some intercalls between your function and others (akin to <a class="reference external" href="http://vergil.chemistry.gatech.edu/psi_doc/master/samples/pywrap_all)/input.dat">pywrap_all)</a>. In trials, permute the order of calls a few times to expose any calls that don&#8217;t clean up after themselves and need further attention.</p>
</li>
<li><p class="first">When all is validated, add your findings to the great <a class="reference internal" href="intercalls.html#table-intercalls"><em>Permitted nesting of Psithon functions</em></a> table in the documentation.</p>
</li>
</ul>
</div></blockquote>
</li>
</ul>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
  <h4>Previous topic</h4>
  <p class="topless"><a href="plugins.html"
                        title="previous chapter">Plugins: Adding New Functionality to PSI4</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="documentation.html"
                        title="next chapter">Documentation</a></p>
  <h3>This Page</h3>
  <ul class="this-page-menu">
    <li><a href="_sources/bestpractices_py.txt"
           rel="nofollow">Show Source</a></li>
  </ul>
<div id="searchbox" style="display: none">
  <h3>Quick search</h3>
    <form class="search" action="search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    <p class="searchtip" style="font-size: 90%">
    Enter search terms or a module, class or function name.
    </p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="relbar-bottom">
        
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="py-modindex.html" title="Python Module Index"
             >modules</a> &nbsp; &nbsp;</li>
        <li class="right" >
          <a href="contents.html" title="Table Of Contents"
             >toc</a> &nbsp; &nbsp;</li>
        <li class="right" >
          <a href="documentation.html" title="Documentation"
             >next</a> &nbsp; &nbsp;</li>
        <li class="right" >
          <a href="plugins.html" title="Plugins: Adding New Functionality to PSI4"
             >previous</a> &nbsp; &nbsp;</li>
    <li><a href="index.html">PSI4 []</a> &raquo; </li>

          <li><a href="contributing.html" >Contributions: Intro to Programming in PSI4</a> &raquo;</li> 
      </ul>
    </div>
    </div>

    <div class="footer">
        &copy; Copyright 2013, The Psi4 Project.
      Last updated on May 13, 2014.
      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
    </div>
    <!-- cloud_sptheme 1.3 -->
  </body>
</html>