DEPRECATED

This space is obsolete and unmaintained. The entire content of the DM Developer Guide is now maintained at https://developer.lsst.io .

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Current »

LSST uses doxygen as its primary source code documentation generator tool. The doxygen manual is available for specific questions about Doxygen.

General Guidelines

The following is the general guideline for documenting source code for LSST. Detailed discussion relative to a specific language is provided for C++ and Python.

  • The beginning of each source file should start with
    • The emacs file format line
  • The LSST Copyright statement appropriate for the file type. Refer to:
    • git@git.lsstcorp.org:LSST/DMS/devenv/templates.git  {CopyrightHeader.pyCopyrightHeader.hCopyrightHeader.cc}
  • Next, each source file (.h, .cc, .py) should briefly describe the purpose of the code contained within.
    • For C++:
      • Use '@file' to start this block;
      • Then provide a brief (1-line) comment for the doxygen 'Files' content index;
      • Followed by a longer description for the file's Detailed Description.
    • For python use docstrings to provide the file contents description
  • For source files containing class specifications
    • For C++, Preceding each class specification
      • Use '@class' to start the class documentation block;
      • Provide the brief (1-line) comment used in the doxygen 'Classes' content index.
      • Describe the class' purpose in a longer block.
      • Document each constructor, public instance variable, and public method.
      • Document each argument to methods and constructors.
    • For python, followng each class specification
      • provide similar information as for C++ but use docstrings formatted using doxygen markup tags
  • For files that do not contain classes, (ie, just functions)
    • Document each function and each of its arguments
    • Document each global variable
  • For C++, to annotate issues which need to be addressed in the future
    • use the '@todo' special command. This allows Doxygen to report on all such events occurring in the code - thus ensuring we don't forget to go back to handle the set-aside issues.
  • For C++, to annotate note-worthy information
    • use the '@note' special command which uses block formatting for visual impact.
       
  • Be aware that LSST makes use of Doxygen's Markdown support for text formatting; please mark up your documentation appropriately.

C++

C++ General Guidelines

The following guidelines should be followed for LSST C++ source files.

When deciding where to document an object, place the doxygen documentation where the item is declared. Thus most doxygen documentation will be in header files.

Required Documentation Style

Use @ to precede all doxygen special command. Eg @param or @file.

Strongly Preferred Documentation Style

Use / to start and */ to end a comment block.

Use /< to start in-line comments.

Acceptable Documentation Style with Constraints

Use one-line, inline comments to document arguments in the method definition only if all methods in the source file are documented similarly.

Warning

Method parameter documentation must remain consistent with the method argument declaration. The scons build will abort should a mismatch occur. (To be instituted in DC3)

Examples

The following guidelines were extracted from "MINOS Offline Documentation, How to document your code for doxygen" here and modified to reflect the LSST Doxygen standard for C++.

Doing nothing, Doxygen will produce a nice cross referenced HTML-ized version of the code. However, you can make this even more useful by embedding documentation on how to use your classes right in the code itself.

Detailed comment before

Add an extra '*'

/** This is a method that does so
* much that I must write an epic 
* novel just to describe how much
* it truly does. 
*/
void DoNothing();

Brief comment before

The first line in a comment block, up to a newline or period, defaults to be the 'brief' comment.

/** This method does something
*/
void DoSomething();

Brief and Detailed comments before

Add extra "*" followed by one liner, then followed by Detailed comments. The Brief comment is ended by first newline or period; the extra blank line is for visual clarity.

/** Implementation of a trace facility for LSST
*
* Tracing is controlled on a per "component" basis, where a "component" is a
* name of the form aaa.bbb.ccc where aaa is the Most significant part; for
* example, the utilities library might be called "utils", the doubly-linked
* list "utils.dlist", and the code to destroy a list "utils.dlist.del"
*
*/
class TraceImpl {
public:
}

Modules or Packages

You can group a package worth of things using a single instance of "@defgroup". A good location for this is the <package>.h file if the package has one. It might look something like:

/** @defgroup PackageName PackageTitle
*
* @brief Provide some stuff to do stuff
*/

Then in all the .h opening comments (see below) add a line like:

/** ...
*
* @ingroup PackageName
*
* ...
*/

Miscellaneous Useful Options

Add generic note

@note The fliber gadget operates underwater.

 

Add references

@see See http::/lsstdoc/manual.

Add exception note

@throw myruntime description of myruntime exception

Add note about work remaining to be done

@todo Add --help feature by jan 5, 2009

Add warning regarding usage

@warning The --button option overrides the --zipper option

Preamble for each source file

// -*- lsst-c++ -*-
...insert HERE the LSST Source Copyright available at 
...http://www.lsstcorp.org/LegalNotices/LsstSourceCopyrightNotice.txt or
...http://dev.lsstcorp.org/trac/browser/DMS/devenv/templates/trunk/CopyrightHeader.cc
/**
* @file <filename>
*
* @ingroup <packagename>
*
* @brief ONE line description of the class
*
* @author Robert Lupton, Princeton University
*/

Class Declaration

Doxygen comments describing the overall Class should be included in the .h file.

/** Implementation of a trace facility for LSST
*
* Tracing is controlled on a per "component" basis, where a "component" is a
* name of the form aaa.bbb.ccc where aaa is the Most significant part; for
* example, the utilities library might be called "utils", the doubly-linked
* list "utils.dlist", and the code to destroy a list "utils.dlist.del"
*
*/
class TraceImpl {
public:
}

 

Method and Function Documentation

Locate each method's documentation where the method is defined. Generally, that will be in the .cc file. However, for inline methods the documentation will be in the .h file at the point the inline is defined. Two methods are acceptable for documenting parameters of the methods and functions; which ever method you choose, be consistent throughout the source file.

Provide the one-liner followed by the comprehensive description of the method. Document the method parameters in the method definition's leading comment block using '@param'.

/** Set a component's verbosity.
*
* If no verbosity is specified, inherit from parent
*
* @param name component of interest
* @param verbosity desired trace verbosity
*/
void TraceImpl::setVerbosity(const std::string &name, const int verbosity) {
}

Optionally, document the method parameters as below. Use single-line embedded comments only; if you need more than a one line description, revert to using '@param'.

/** Set a component's verbosity.
*
* If no verbosity is specified, inherit from parent
*/
void TraceImpl::setVerbosity(const std::string &name, ///< component of interest
const int verbosity ///< desired trace verbosity
) {}

Overloaded Methods

'@overload' may be used when two methods/functions are effectively the same but have different parameters list for reasons of convenience.

 

/** seconds from midnight
*/
long GetTime(void){
return secondFromMidnight(CURRENT);
}
/** @overload void GetTime(int &hours, int &minutes, int &seconds)
*/
void GetTime(int &hours, ///< set: current hour
int &minutes, ///< set: current minutes
int &seconds ///< set: current seconds
){
hours = _hours;
minutes = _minutes;
seconds = _seconds;
}

Example .h file

Below is a full example.

 

// -*- lsst-c++ -*-
/*
* LSST Data Management System
* Copyright 2008, 2009, 2010 LSST Corporation.
*
* This product includes software developed by the
* LSST Project (http://www.lsst.org/).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the LSST License Statement and
* the GNU General Public License along with this program. If not,
* see <http://www.lsstcorp.org/LegalNotices/>.
*/
/**
* @file ExampleClass.h
* @brief This message displayed in Doxygen File index.
*
* @ingroup PackageName
* (Note: this needs exactly one @defgroup somewhere)
*
* @author Joe Smith
* Contact: js@gmail.com
*
* Created on: Wed Apr 13 18:39:37 2005
* (optionally: @date Wed Apr 13 18:39:37 2005 )
*
*/
#ifndef EXAMPLECLASS_H
#define EXAMPLECLASS_H
/** @class
* Provide an example. This message displayed in Doxygen Class index.
* (optionally: @brief Provide an example. This message displayed in Doxygen Class index. )
*
* This class is meant as an example. It is not useful by itself
* rather its usefulness is only a function of how much it helps
* the reader. It is in a sense defined by the person who reads it
* and otherwise does not exist in any real form. 
*
*
* @note Attempts at zen rarely work.
*/
class ExampleClass
{
public:
ExampleClass();
ExampleClass(std::string a, std::string b);
~ExampleClass();
void DoSomething();
void DoNothing();
void* VeryUsefulMethod(bool level);
private:
std::string _question; ///< the question
std::string _answer; ///< the answer 
}; // end of class ExampleClass
#endif // EXAMPLECLASS_H

Example .cc file

 

// -*- lsst-c++ -*-
/*
* LSST Data Management System
* Copyright 2008, 2009, 2010 LSST Corporation.
*
* This product includes software developed by the
* LSST Project (http://www.lsst.org/).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the LSST License Statement and
* the GNU General Public License along with this program. If not,
* see <http://www.lsstcorp.org/LegalNotices/>.
*/
/**
* @file ExampleClass.cc
* (Optionally: file )
* @brief This message displayed in Doxygen Files index
*
* @ingroup PackageName
* (Note: this needs exactly one @defgroup somewhere)
*
* @author Joe Smith
* Contact: js@gmail.com
*
*/
#include <string>
/** Create an ExampleClass
*/
ExampleClass() {
_question = std::string('What');
_answer = std::string('None');
}
/** Create an ExampleClass with lots of initial values.
* Note the parameter explanations to the right of the parameter.
*/
ExampleClass(
std::string question, ///< the question
std::string answer ///< the answer
) {
_question = question; 
_answer = answer; 
}
~ExampleClass(){};
/** This method does something
*/
void DoSomething(){}
/** This is a method that does so
* much that I must write an epic 
* novel just to describe how much
* it truly does. */
void DoNothing(){}
/** A useful method.
* @return a number 
* 
* This method does unbelievably useful things. 
* And returns exceptionally useful results.
* Use it everyday with good health.
*/
int VeryUsefulMethod(
bool level ///< some useful comment about level
){
if ( level == HIGH ) {
return 44;
} 
return 23;
}

Python

Python files should be documented using Docstrings. Doxygen markup tags should be used within the Docstring to provide formatting structure.

Python Docstring Documentation

 

"""Documentation for this module.
More details.
"""
def func():
"""Documentation for a function.
More details.
"""
pass
class PyClass:
"""Documentation for a class.
More details.
"""

def __init__(self):
"""The constructor."""
self._memVar = 0;

def PyMethod(self):
"""Documentation for a method."""
pass

The above can be passed to doxygen to generate HTML documentation. Click here to see what that looks like.

Formatting of the Docstring Text

 

Although Doxygen special commands are not interpreted when included within a docstring, DM uses a formatting convention which intentionally uses doxygen tags inside the python docstrings. The rationale behind this is as follows:

  • The tags promote a structure that is both logical and readable.
    • it does require some formatting style that is human-friendly, but this is good in general anyway.
  • It allows for a future tool that could extract the docstrings into doxygen documentation.

The following example illustrates the use of doxygen special commands, within docstrings, to highlight key information:

 

class SharedData(object):
"""
@brief Lock-protected container for data that can be shared amongst threads.
This container also behaves like a threading.Container, via its 
wait(), notify(), and notifyAll() functions. Also like Condition, 
acquire() is reentrant.
SharedData instances may be used with the with statement:
@verbatim
sd = SharedData()
with sd:
sd.blah = 1
@endverbatim
The with statement will acquire the lock and ensure that it is released
when its block is exited. 
"""
def __init__(self, needLockOnRead=True, cond=None):
"""
create and initialize the shared data
@param needLockOnRead if true (default), acquiring the lock will 
be needed when reading the data. This is recommended
if the data items are anything but primitive types;
otherwise, a compound data item (e.g. of type dict)
could be updated without acquiring a lock. 
@param cond Reuse this existing Condition instance to protect this
container
"""

Preamble for each source file

 

#
...insert HERE the LSST Source Copyright available at 
...http://dev.lsstcorp.org/trac/browser/DMS/devenv/templates/trunk/CopyrightHeader.py
"""
Description of the file contents
@author Joe Developer, Organization
"""

Complete Python Example

 

#
# LSST Data Management System
# Copyright 2008, 2009, 2010 LSST Corporation.
#
# This product includes software developed by the
# LSST Project (http://www.lsst.org/).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the LSST License Statement and
# the GNU General Public License along with this program. If not,
# see <http://www.lsstcorp.org/LegalNotices/>.
#
"""
Description of file contents 

@author Joe Developer, Organization
"""

class SharedData(object):
"""
@brief Lock-protected container for data that can be shared amongst threads.
This container also behaves like a threading.Container, via its 
wait(), notify(), and notifyAll() functions. Also like Condition, 
acquire() is reentrant.
SharedData instances may be used with the with statement:
@verbatim
sd = SharedData()
with sd:
sd.blah = 1
@endverbatim
The with statement will acquire the lock and ensure that it is released
when its block is exited. 
"""
def __init__(self, needLockOnRead=True, cond=None):
"""
create and initialize the shared data
@param needLockOnRead if true (default), acquiring the lock will 
be needed when reading the data. This is recommended
if the data items are anything but primitive types;
otherwise, a compound data item (e.g. of type dict)
could be updated without acquiring a lock. 

@param cond Reuse this existing Condition instance to protect this
container
"""
Not Supported: Not Using Docstrings
The following illustrates an alternative doxygen python formatting style which is NO LONGER ACCEPTABLE in LSST DM source.
Docstrings does not currently support any of the special doxygen commands . In order to use those tags, doxygen recognizes special Python comment blocks that start with "##", as in the following example. This formatting style is NO LONGER ACCEPTABLE in LSST DM source.
## Documentation for this module. **** NOT valid LSST Doc Style ****
#
# More details.
## Documentation for a function.
#
# More details.
def func():
pass
## Documentation for a class.
#
# More details.
  • No labels