diff --git a/src/specmicp_common/cached_vector.hpp b/src/specmicp_common/cached_vector.hpp
index 1a881c6..cf9ecbe 100644
--- a/src/specmicp_common/cached_vector.hpp
+++ b/src/specmicp_common/cached_vector.hpp
@@ -1,389 +1,447 @@
 /* =============================================================================
 
  Copyright (c) 2014 - 2016
  F. Georget <fabieng@princeton.edu> Princeton University
  All rights reserved.
 
 
 Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:
 
     1. Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
 
     2. Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
 
     3. Neither the name of the copyright holder nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
 
 ============================================================================= */
 
 #ifndef SPECMICP_REACTMICP_CACHEDVECTOR_HPP
 #define SPECMICP_REACTMICP_CACHEDVECTOR_HPP
 
 //! \file cached_vector.hpp
 //! \brief Vector with cache
 
 #include <vector>
 #include <string>
 #include <utility>
 #include <stdexcept>
 #include <algorithm>
 #include <type_traits>
 
 namespace specmicp {
 namespace utils {
 
 //! \brief A vector with cache
 //!
 //! This vector is designed to simulate a large vector with only a few different
 //! values of type T, where T is 'big'
 //!
 //! \tparam T must be copyable, assignable, default constructible
 template <typename T>
 class CachedVector
 {
-    class CachedIterator;
+    class CachedIterator; // forward declaration of the iterator class
 
 public:
-    using value_type = T;
-    using reference = T&;
-    using const_reference = const T&;
-    using size_type = std::size_t;
-    using iterator = CachedIterator;
-    using const_iterator = const CachedIterator;
-    using index_vector = std::vector<size_type>;
+    using value_type = T; //!< Type of a value
+    using reference = T&; //!< Type a reference to a value
+    using const_reference = const T&; //!< Type of a const reference to a value
+    using size_type = std::size_t; //!< Type for the size of a vector
+    using iterator = CachedIterator; //!< Type of an iterator
+    using const_iterator = const CachedIterator; //!< Type of a const iterator
+    using index_vector = std::vector<size_type>; //!< Type of the index vector
 
     //! \brief Default constructor, an empty vector
     CachedVector() {}
-    //! \brief Initialize a 'size' vector with value T
+    //! \brief Initialize a vector with value T
+    //!
+    //! \param size size of the vector
+    //! \param value initial value for all entry
     CachedVector(size_type size, T&& value):
         m_cache({std::forward<T>(value),}),
         m_indexes(size, 0)
     {}
-    //! \brief Initialize a 'size' vector with default T
+    //! \brief Initialize a vector with default T
+    //!
+    //! \param size size of the vector
+    //!
+    //! \warning This constructor is only available if a default constructor exist for T
     CachedVector(size_type size,
                  typename std::enable_if<std::is_default_constructible<T>::value>::type* = nullptr):
         m_cache(),
         m_indexes(size, 0)
     {
         m_cache.emplace_back();
     }
 
     //! \brief Reserve storage
+    //!
+    //! Reserves memory for the vector
+    //!
+    //! \param size_cap the size to reserve in memory for the vector
     void reserve(size_type size_cap) {
         m_indexes.reserve(size_cap);
     }
 
     //! \brief Reserve cache storage
+    //!
+    //! Reserves memory for the cache
+    //!
+    //! \param size_cap The cache will be able to store up to 'size_cap' value
+    //!  without realllocation
     void reserve_cache(size_type size_cap) {
         m_cache.reserve(size_cap);
     }
 
-    //! \brief Access specified element
+    //! \brief Access an element
+    //!
+    //! No bounds checkoing is performed in this method.
+    //!
+    //! \sa at
     reference operator[] (size_type pos) {
         return m_cache[m_indexes[pos]];
     }
-
-    //! \brief Access specified element
+    //! \brief Access an element
+    //!
+    //! No bounds checkoing is performed in this method.
+    //!
+    //! \sa at
     const_reference operator[] (size_type pos) const {
         return m_cache[m_indexes[pos]];
     }
 
-    //! \brief Access specified element with bounds checking
+    //! \brief Access an lement with bounds checking
+    //!
+    //! \sa operator[]
     reference at(size_type pos) {
         std::size_t ind = m_indexes.at(pos);
         return m_cache.at(ind);
     }
-
-    //! \brief Access specified element with bounds checking
+    //! \brief Access an element with bounds checking
+    //!
+    //! \sa operator[]
     const_reference at(size_type pos) const {
         std::size_t ind = m_indexes.at(pos);
         return m_cache.at(ind);
     }
 
     //! \brief Return a reference to the position in the cache
+    //!
+    //! \sa get
     size_type& operator() (size_type pos) {
         return m_indexes[pos];
     }
 
     //! \brief Return a reference to the position in the cache
+    //!
+    //! \sa get
     const size_type& operator () (size_type pos) const {
         return m_indexes[pos];
     }
 
     //! \brief Return the cached value
+    //!
+    //! \sa operator()
     reference get(size_t pos_cache) {
         return m_cache[pos_cache];
     }
     //! \brief Return the cached value
+    //!
+    //! \sa operator()
     const_reference get(size_t pos_cache) const {
         return m_cache[pos_cache];
     }
 
     //! \brief Return the size of the vector
     size_type size() const {
         return m_indexes.size();
     }
 
     //! \brief Return the size of the cache
     size_type size_cache() const {
         return m_cache.size();
     }
 
     //! \brief Push an element to the cache
     //!
     //! \param value The element to add
     //! \return the position of the element in the cache
     size_type push_back_cache(T&& value) {
         m_cache.push_back(std::forward<T>(value));
         return (m_cache.size() - 1);
     }
 
     //! \brief Emplace a new element to the cache
     template <typename ...Args>
     size_type emplace_back_cache(Args...args) {
         m_cache.emplace_back(args...);
         return (m_cache.size() - 1);
     }
 
     //! \brief Adds an element to the end
     //!
     //! \param index refers to a position in the cache
     void push_back(size_type index) {
         m_indexes.push_back(index);
     }
 
     //! \brief Adds an element to the end and a new value to the cache
     //!
     //! \param value a new value
     void push_back(T&& value) {
         auto ind = push_back_cache(std::forward<T>(value));
         m_indexes.push_back(ind);
     }
 
     //! \brief Add a new element at the end and build a new element to the cache
     template <typename ...Args>
     void emplace_back(Args...args) {
         auto ind = emplace_back_cache(args...);
         m_indexes.push_back(ind);
     }
 
     //! \brief Fork the value at the given position
     reference fork(size_type pos) {
         m_cache.push_back(m_cache[m_indexes[pos]]);
         m_indexes[pos] = m_cache.size() - 1;
         return m_cache.back();
     }
 
     //! \brief Set the value to another
     //!
     //! Don't check the validity of the value !
     void set(size_type pos, size_type pos_cache) {
         m_indexes[pos] = pos_cache;
     }
 
     // Iterator business
 
     //! \brief Return an iterator to the beginning
     iterator begin() {
         return CachedIterator(m_indexes.begin(), m_cache);
     }
     //! \brief Return an iterator to the end
     iterator end() {
         return CachedIterator(m_indexes.end(), m_cache);
     }
     //! \brief Return an iterator to the beginning
     const_iterator cbegin() const {
         return CachedIterator(m_indexes.begin(), m_cache);
     }
     //! \brief Return an iterator to the end
     const_iterator cend() const{
         return CachedIterator(m_indexes.end(), m_cache);
     }
 
     //! \brief Return an iterator to the beginning of the indexes
     index_vector::iterator begin_index() {
         return m_indexes.begin();
     }
     //! \brief Return an iterator to the end of the indexes
     index_vector::iterator end_index() {
         return m_indexes.end();
     }
     //! \brief Return an iterator to the beginning of the indexes
     index_vector::const_iterator cbegin_index() const {
         return m_indexes.cbegin();
     }
     //! \brief Return an iterator to the end of the indexes
     index_vector::const_iterator cend_index() const{
         return m_indexes.cend();
     }
 
 private:
-    //! \brief The iterator
+    //! \brief The iterator class for a cached vector
     class CachedIterator: public std::vector<size_type>::iterator
     {
         using base = std::vector<size_type>;
         using base_iterator = base::iterator;
 
     public :
+        //! \param base iterator over the index vector
+        //! \param cache referece to the cache vector
         CachedIterator(
                 const base_iterator& base,
                 std::vector<T>& cache):
             base_iterator(base),
             m_cache(cache)
         {}
+        //! \param pos position where to start the iterator
+        //! \param cache referece to the cache vector
         CachedIterator(
                 std::size_t pos,
                 std::vector<T>& cache
                 ):
             base_iterator(),
             m_cache(cache)
         {
             advance(static_cast<base_iterator&>(*this), pos-1);
         }
 
+        //! \brief Dereference operator
+        //!
+        //! \return a reference to the corresponding value
         T& operator* () {
             return m_cache[base_iterator::operator* ()];
         }
+        //! \brief Const dereference operator
+        //!
+        //! \return a const reference to the corresponding value
         const T& operator* () const {
             return m_cache[base_iterator::operator* ()];
         }
 
     private:
         std::vector<T>& m_cache;
     };
 
 private:
     std::vector<T> m_cache;
     std::vector<size_type> m_indexes;
 };
 
-//! \brief A name cached vector
+//! \brief A named cached vector
 //!
-//! Every cache value has an associated name
+//! Every cache value has an associated name which can be used to obtain the
+//! values.
 template <typename T>
-class NameCachedVector: public CachedVector<T>
+class NameCachedVector:
+        public CachedVector<T>
 {
 public:
-    using size_type = typename CachedVector<T>::size_type;
-    using reference = typename CachedVector<T>::reference;
-    using const_reference = typename CachedVector<T>::const_reference;
+    using size_type = typename CachedVector<T>::size_type; //!< Type of the size of a value
+    using reference = typename CachedVector<T>::reference; //!< Type of a reference
+    using const_reference = typename CachedVector<T>::const_reference; //!< Type of a const reference
 
     NameCachedVector():
         CachedVector<T>()
     {}
+
+    //! \brief Initialize a vector with a default value
+    //!
+    //! \param size size of the vector
+    //! \param name name of the default value
+    //! \param value the default value
     NameCachedVector(size_type size, std::string name, T&& value):
         CachedVector<T>(size, std::forward<T>(value)),
         m_names({name, })
     {}
+    //! \brief Initialize the vector with the default value
+    //!
+    //! \param size size of the vector
+    //! \param name name of the default value
+    //!
+    //! \warning only exist if the value type has a default constructor
     NameCachedVector(size_type size, std::string name,
                      typename std::enable_if<std::is_default_constructible<T>::value>::type* = nullptr):
         CachedVector<T>(size),
         m_names({name, })
     {}
 
     //! \brief Reserve cache storage
     void reserve_cache(size_type size_cap) {
         CachedVector<T>::reserve_cache(size_cap);
         m_names.reserve(size_cap);
     }
 
 
     //! \brief Push an element to the cache
     //!
     //! \param name label for the value to add
     //! \param value The element to add
     //! \return the position of the element in the cache
     size_type push_back_cache(const std::string& name, T&& value) {
         m_names.push_back(name);
         return CachedVector<T>::push_back_cache(std::forward<T>(value));
     }
 
     //! \brief Emplace a new element to the cache
     template <typename ...Args>
     size_type emplace_back_cache(const std::string& name, Args...args) {
         m_names.push_back(name);
         return CachedVector<T>::emplace_back_cache(args...);
     }
 
     //! \brief Adds an element to the end and a new value to the cache
     //!
     //! \param name label for the value
     //! \param value a new value
     void push_back(const std::string& name, T&& value) {
         CachedVector<T>::push_back(std::forward<T>(value));
         m_names.push_back(name);
     }
 
     //! \brief Add a new element at the end and build a new element to the cache
     template <typename ...Args>
     void emplace_back(const std::string& name, Args...args) {
         CachedVector<T>::emplace_back(args...);
         m_names.push_back(name);
     }
 
     //! \brief Return the value stored as "name"
     reference get(std::string name) {
         return CachedVector<T>::get(get_cache_position(name));
 
     }
     //! \brief Return the value stored as "name"
     const_reference get(std::string name) const {
         return CachedVector<T>::get(get_cache_position(name));
     }
     bool has_value(std::string name) const {
         auto it = std::find(m_names.cbegin(), m_names.cend(), name);
         return (it != m_names.cend());
     }
 
     //! \brief Fork the value at the given position
     reference fork(size_type pos, const std::string& name) {
         m_names.push_back(name);
         return CachedVector<T>::fork(pos);
     }
     //! \brief Fork the value of a given name
     reference fork(const std::string& old_name, const std::string& new_name) {
         auto&& val = get(old_name);
         auto pos = push_back_cache(new_name, std::forward<T>(val));
         return CachedVector<T>::get(pos);
     }
 
     //! \brief Set the given node to the value 'name'
     void set(size_type pos, const std::string& name) {
         CachedVector<T>::set(pos, get_cache_position(name));
     }
 
     //! \brief Return the position in the cache
     size_type get_cache_position(const std::string& name) const {
         auto it = std::find(m_names.cbegin(), m_names.cend(), name);
         if (it == m_names.cend()) {
             throw std::invalid_argument("Unknow value in NamedCachedVector '"
                                         + name + "'.");
         }
         return (it-m_names.cbegin());
     }
 
 private:
     std::vector<std::string> m_names;
 };
 
 } //end namespace utils
 } //end namespace specmicp
 
 
 #endif // SPECMICP_REACTMICP_CACHEDVECTOR_HPP
diff --git a/src/specmicp_common/dateandtime.hpp b/src/specmicp_common/dateandtime.hpp
index 4adbeb0..86444b7 100644
--- a/src/specmicp_common/dateandtime.hpp
+++ b/src/specmicp_common/dateandtime.hpp
@@ -1,67 +1,66 @@
 /* =============================================================================
 
  Copyright (c) 2014 - 2016
  F. Georget <fabieng@princeton.edu> Princeton University
  All rights reserved.
 
 
 Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:
 
     1. Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
 
     2. Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
 
     3. Neither the name of the copyright holder nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
 
 ============================================================================= */
 
 #ifndef SPECMICP_UTILS_DATEANDTIME_HPP
 #define SPECMICP_UTILS_DATEANDTIME_HPP
 
 //! \file dateandtime.hpp
 //! \brief Date and time tools
 
 #include "types.hpp"
 #include <string>
 #include <ctime>
 
 namespace specmicp {
 //! \namespace specmicp::dateandtime
 //! \brief Date and time utilities
 namespace dateandtime {
 
 //! \brief Return a textual representation of time_point
 std::string SPECMICP_DLL_PUBLIC to_text(std::time_t& time_point);
 
 //! \brief Return a localized textual representation of time point
 std::string SPECMICP_DLL_PUBLIC to_text_localized(std::time_t& time_point);
 
 //! \brief Return a textual representation of the current date and time
 std::string SPECMICP_DLL_PUBLIC now();
 
 //! \brief Return a localized textual representation of the current date and time
-//! Locali
 std::string SPECMICP_DLL_PUBLIC now_localized();
 
 } //end namespace dateandtime
 } //end namespace specmicp
 
 
 #endif // SPECMICP_UTILS_DATEANDTIME_HPP
diff --git a/src/specmicp_common/filesystem.hpp b/src/specmicp_common/filesystem.hpp
index 5c1958e..f05996a 100644
--- a/src/specmicp_common/filesystem.hpp
+++ b/src/specmicp_common/filesystem.hpp
@@ -1,93 +1,111 @@
 /* =============================================================================
 
  Copyright (c) 2014 - 2016
  F. Georget <fabieng@princeton.edu> Princeton University
  All rights reserved.
 
 
 Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:
 
     1. Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
 
     2. Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
 
     3. Neither the name of the copyright holder nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
 
 ============================================================================= */
 
 #ifndef SPECMICP_UTILS_FILESYSTEM
 #define SPECMICP_UTILS_FILESYSTEM
 
 //! \file filesystem.hpp
 //! \brief helper functions to deal with the filesystem
 
 #include "macros.hpp"
 #include <string>
 #include <vector>
 
 namespace specmicp {
 namespace utils {
 
 //! \brief Check that the directory exist
 bool SPECMICP_DLL_PUBLIC is_directory(const std::string& path);
 
 //! \brief Check that the directory exist
 bool SPECMICP_DLL_PUBLIC is_file(const std::string& path);
 
 //! \brief Return the current directory
 std::string SPECMICP_DLL_PUBLIC get_current_directory();
 
-//! \brief Complete a path
+//! \brief Complete a path from a given directory and a file
+//!
+//! \param dir the directory
+//! \param file the basename of the file
 std::string SPECMICP_DLL_PUBLIC complete_path(
         const std::string& dir,
         const std::string& file
         );
 
 //! \brief Return true if the given path is absolute
+//!
+//! \param path the path to test
 bool SPECMICP_DLL_PUBLIC is_path_absolute(const std::string& path);
 
 //! \brief Return an absolute path from a relative one
 //!
+//! \param[in] rel_path a path
+//! \param[out] error a string to contain error message if needed
+//! \return An aboslute path, or an empty string if an error occured
+//!
 //! If an error is detected then the return string will be empty,
 //! and error will contain a message about the error
 std::string SPECMICP_DLL_PUBLIC relative_to_absolute(
         const std::string& rel_path,
         std::string& error
         );
 
 //! \brief Return the complete path to a file from a set of directories
+//!
+//! \param filename basename of the file to seek
+//! \param directories list of directories where to search the file
+//! \return an absolute path, or an empty string if the file wasn't found
 std::string SPECMICP_DLL_PUBLIC find_path(
         std::string filename,
         const std::vector<std::string>& directories
         );
 
 //! \brief Return true if the environment variable is defined
+//!
+//! \param env_var the environment variable to check
 bool SPECMICP_DLL_PUBLIC has_env(
         const std::string& env_var
         );
 
 //! \brief Return an environment variable
+//!
+//! \param env_var the environment variable
+//! \return the value stored in the environment variable, or an empty string
 std::string SPECMICP_DLL_PUBLIC get_env(
         const std::string& env_var
         );
 } // end namespace utils
 } // end namespace specmicp
 
 #endif // SPECMICP_UTILS_FILESYSTEM
diff --git a/src/specmicp_common/moving_average.hpp b/src/specmicp_common/moving_average.hpp
index 899cf3b..5c89ef1 100644
--- a/src/specmicp_common/moving_average.hpp
+++ b/src/specmicp_common/moving_average.hpp
@@ -1,103 +1,111 @@
 /* =============================================================================
 
  Copyright (c) 2014 - 2016
  F. Georget <fabieng@princeton.edu> Princeton University
  All rights reserved.
 
 
 Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:
 
     1. Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
 
     2. Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
 
     3. Neither the name of the copyright holder nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
 
 ============================================================================= */
 
 #ifndef SPECMICP_UTILS_MOVINGAVERAGE_HPP
 #define SPECMICP_UTILS_MOVINGAVERAGE_HPP
 
 /*!
 \file moving_average.hpp
 \brief Exponential moving average
 
 The moving average allows to take a weighted average
 of the last x points in the data series.
 
 It is used in particular in the adaptive timestepping algorithm.
 
-\code{.cpp}
-  ExponentialMovingAverage moving_average(0.1, 1.0);
-  for (int i=0; i<10; ++i) {
-     std::cout << "Current value : " << moving_average.add_point(i);
-  }
-  // reset to 1.0
-  moving_average.reset(1.0);
-\endcode
  */
 
 #include "types.hpp"
 
 namespace specmicp {
 //! \namespace specmicp::utils
 //! \brief misc and others used in different places
 namespace utils {
 
-//! \brief Exponential moving average
-//!
-//! https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
-//!
-//! @param alpha coefficient between 0 and 1
-//! @param init initial value of the average
+/*! \brief Exponential moving average
+
+The exponential moving average \f$Y_n\$ is given by
+\f$Y_n = \alpha y + (1 - \alpha) Y_{n-1}\f$
+where y is a value to add to the average, and \f$Y_{n-1}\f$ the previous value.
+
+The average allows to take into account several previous values while storing
+only one value. The impact of the previous iteration on the average value is
+ controlled by the parameter \$\alpha\$, which is between 0 and 1.
+
+\code{.cpp}
+  ExponentialMovingAverage moving_average(0.1, 1.0);
+  for (int i=0; i<10; ++i) {
+     std::cout << "Current value : " << moving_average.add_point(i);
+  }
+  // reset to 1.0
+  moving_average.reset(1.0);
+\endcode
+
+*/
 class SPECMICP_DLL_PUBLIC ExponentialMovingAverage
 {
 public:
+    //! \param alpha coefficient between 0 and 1
+    //! \param init initial value of the average
     ExponentialMovingAverage(scalar_t alpha, scalar_t init):
         m_alpha(alpha),
         m_current_value(init)
     {
     }
     //! \brief Add a point in the series, return current average value
     scalar_t add_point(scalar_t value);
 
     //! \brief Return the current average value
     scalar_t current_value() {
         return m_current_value;
     }
     //! \brief Reset the average to 'value'
     void reset(scalar_t value) {
         m_current_value = value;
     }
 
     //! \brief Set the average parameter value
     void set_alpha(scalar_t alpha) {m_alpha = alpha;}
 
 
 private:
     scalar_t m_alpha;
     scalar_t m_current_value;
 };
 
 
 } // end namespace utils
 } // end namespace specmicp
 
 #endif // SPECMICP_UTILS_MOVINGAVERAGE_HPP
diff --git a/src/specmicp_common/string_algorithms.cpp b/src/specmicp_common/string_algorithms.cpp
index 7ef9676..d83397b 100644
--- a/src/specmicp_common/string_algorithms.cpp
+++ b/src/specmicp_common/string_algorithms.cpp
@@ -1,419 +1,419 @@
 /* =============================================================================
 
  Copyright (c) 2014 - 2016
  F. Georget <fabieng@princeton.edu> Princeton University
  All rights reserved.
 
 
 Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:
 
     1. Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
 
     2. Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
 
     3. Neither the name of the copyright holder nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
 
 ============================================================================= */
 
 #include "string_algorithms.hpp"
 
 #include <algorithm>
 
 
 #define RANGE_SEP ':'
 
 
 namespace specmicp {
 namespace utils {
 
 //! \brief Split a string
 std::vector<std::string> split(const std::string& to_split, char separator)
 {
     std::vector<std::string> splitted;
     auto nb_elem = std::count(to_split.begin(), to_split.end(), separator);
     splitted.reserve(nb_elem+1);
 
     auto start = to_split.begin();
     for (auto current=to_split.cbegin(); current!= to_split.cend(); ++current)
     {
         if (*current == separator) {
             splitted.emplace_back(to_split.substr(
                                       start - to_split.cbegin(), current-start));
             start = current + 1;
         }
     }
     // last value
     if (start < to_split.cend()) {
         splitted.emplace_back(to_split.substr(start - to_split.cbegin()));
     }
     return splitted;
 }
 
 
 std::string strip(const std::string& to_trim)
 {
     auto start = to_trim.begin();
     auto end = to_trim.end();
 
     // at the beginning
     auto current=to_trim.begin();
     for (; current!=to_trim.cend(); ++current) {
         if (*current != ' ')
         {
             start = current;
             break;
         }
     }
     if (current == to_trim.cend()) {return "";} // empty string
 
     // at the end
     for (auto current=to_trim.cend()-1;current>=to_trim.begin(); --current) {
         if (*current != ' ')
         {
             end = ++current;
             break;
         }
     }
 
     return to_trim.substr(start - to_trim.begin(), end-start);
 }
 
 
-void parse_one_term(std::vector<index_t>& numbers, const std::string& term);
-void parse_one_term(std::vector<uindex_t>& numbers, const std::string& term);
+static void parse_one_term(std::vector<index_t>& numbers, const std::string& term);
+static void parse_one_term(std::vector<uindex_t>& numbers, const std::string& term);
 
 template <typename T>
 std::vector<T> range_indices_impl(const std::string& range_str)
 {
     std::vector<T> numbers;
     const uindex_t nb_sep = std::count(range_str.cbegin(), range_str.cend(), ',');
     numbers.reserve(nb_sep+1);
     if (nb_sep == 0) { // if only one term
         parse_one_term(numbers, range_str);
     }
     else {
         const std::vector<std::string> terms = split(range_str, ',');
         for (const auto& term: terms) {
             parse_one_term(numbers, term);
         }
     }
     // sort the indices
     std::sort(numbers.begin(), numbers.end());
     return numbers;
 }
 
 template <>
 std::vector<index_t> range_indices(const std::string& range_str)
 {
     return range_indices_impl<index_t>(range_str);
 }
 
 template <>
 std::vector<uindex_t> range_indices(const std::string& range_str)
 {
     return range_indices_impl<uindex_t>(range_str);
 }
 
 void parse_one_term(std::vector<index_t>& numbers, const std::string &term)
 {
     if (term == "") return; // check for empty terms
 
     const auto to_anal = strip(term);
     const auto is_range = std::find(to_anal.cbegin(), to_anal.cend(), RANGE_SEP);
     if (is_range == to_anal.cend()) {
         // if just a number
         numbers.push_back(std::stol(to_anal));
     }
     else {
         // if a range
         const std::string first_str = to_anal.substr(0, is_range-to_anal.cbegin());
         const std::string last_str = to_anal.substr(is_range-to_anal.cbegin()+1);
         const index_t first = std::stol(first_str);
         const index_t last = std::stol(last_str);
         for (auto ind=first; ind<=last; ++ind) {
             numbers.push_back(ind);
         }
     }
 }
 
 void parse_one_term(std::vector<uindex_t>& numbers, const std::string &term)
 {
     if (term == "") return; // check for empty terms
 
     const auto to_anal = strip(term);
     const auto is_range = std::find(to_anal.cbegin(), to_anal.cend(), RANGE_SEP);
     if (is_range == to_anal.cend()) {
         // if just a number
         auto val = std::stol(to_anal);
         if (val < 0) {
             throw std::invalid_argument("Negative argurment found in "
                                         "positive ranges : '"+std::to_string(val)
                                         + "'.");
         }
         numbers.push_back(val);
     }
     else {
         // if a range
         const std::string first_str = to_anal.substr(0, is_range-to_anal.cbegin());
         const std::string last_str = to_anal.substr(is_range-to_anal.cbegin()+1);
         const index_t first = std::stol(first_str);
         if (first < 0 ) {
             throw std::invalid_argument("Negative argurment found in "
                                         "positive ranges : '"+std::to_string(first)
                                         + "'.");
         }
         const index_t last = std::stol(last_str);
         for (auto ind=first; ind<=last; ++ind) {
             numbers.push_back(ind);
         }
     }
 }
 
 template <typename T>
 class ExpressionParser
 {
 public:
     ExpressionParser(
             const std::string& expr,
             const std::unordered_map<std::string, T>& vars
             ):
         complete_expr(expr),
         variables(vars)
     {
 
     }
 
     T parse() {return parse_term(complete_expr);}
 
     T parse_value(const std::string& value);
     T parse_factor(const std::string& factor);
     T parse_term(const std::string& term);
 
 private:
     const std::string& complete_expr;
     const std::unordered_map<std::string, T>& variables;
 };
 
 template <>
 scalar_t ExpressionParser<scalar_t>::parse_value(const std::string& expr)
 {
     auto trimmed_expr = strip(expr);
     if (trimmed_expr == "") {
         throw std::invalid_argument("Error while parsing : " + complete_expr);
     }
     scalar_t val = std::nan("");
     try {
         std::size_t pos;
         val = std::stod(trimmed_expr, &pos);
         if (pos != trimmed_expr.size()) {
             throw std::logic_error("Error while processing '" + expr +
                                    "'. Just a number was expected."
                                    "Error occured while processing '"
                                    + complete_expr + "'.");
         }
     }
     catch (const std::invalid_argument& e) {
         auto it = variables.find(trimmed_expr);
         if (it == variables.cend()) {
             throw std::out_of_range("Unknown variable '"+
                                         trimmed_expr + "' in parsing of '"
                                         + complete_expr +"'.");
         }
         val = it->second;
     }
     return val;
 }
 
 template <>
 index_t ExpressionParser<index_t>::parse_value(const std::string& expr)
 {
     auto trimmed_expr = strip(expr);
     index_t val = INT_MAX;
     try {
         std::size_t pos;
         val = std::stol(trimmed_expr, &pos);
         if (pos != trimmed_expr.size()) {
             throw std::logic_error("Error while processing" + expr +
                                    ". Just a number was expected."
                                    "Error occured while processing "
                                    + complete_expr + ".");
         }
     }
     catch (const std::invalid_argument& e) {
         auto it = variables.find(trimmed_expr);
         if (it == variables.cend()) {
             throw std::out_of_range("Unknown variable '"+
                                         trimmed_expr + "' in parsing of '"
                                         + complete_expr +"'.");
         }
         val = it->second;
     }
     return val;
 }
 
 template <typename T>
 T ExpressionParser<T>::parse_factor(const std::string& expr)
 {
     auto it = expr.find_last_of("*/");
     if (it == expr.npos) {
         return parse_value(expr);
     }
     auto val1 = parse_factor(expr.substr(0, it));
     auto val2 = parse_value(expr.substr(it+1));
     if (expr[it] == '*') {
         return val1*val2;
     } else {
         return val1/val2;
     }
     return 0;
 }
 
 template <typename T>
 T ExpressionParser<T>::parse_term(const std::string& expr)
 {
     auto it = expr.find_first_of("+-");
     if (it == expr.npos) {
         return parse_factor(expr);
     }
     else if (it != 0) {
         auto val1 = parse_factor(expr.substr(0, it));
         auto val2 = parse_factor(expr.substr(it+1));
         if (expr[it] == '+') {
             return val1+val2;
         } else {
              return val1-val2;
         }
     }
     else {
         if (expr[it] == '-') {
             return -parse_term(expr.substr(1));
         } else {
             return parse_term(expr.substr(1));
         }
     }
     return 0;
 }
 
 template <>
 scalar_t ExpressionParser<scalar_t>::parse_term(const std::string& expr)
 {
     auto pred = [](const char& t) -> bool {return ((t == '+') or( t == '-'));};
     std::size_t pos = 0;
     char op;
     auto it = expr.begin();
     while (pos < expr.size())
     {
         it = std::find_if(it, expr.end(), pred);
         if (it == expr.cend()) {
             pos = expr.size();
             break;
         }
         op = *it;
         pos = it-expr.cbegin();
         // xe-y notation => it's a number !
         if (op == '-' and expr[pos-1] == 'e' and std::isdigit(expr[pos-2]))
         {
             ++it; // jump to next char
             continue;
         }
         else
         {
             break;
         }
     }
     if (pos == expr.size()) {
         return parse_factor(expr);
     }
 
     if (pos > 0) {
         auto val1 = parse_factor(expr.substr(0, pos));
         auto val2 = parse_factor(expr.substr(pos+1));
         if (op == '+') {
             return val1+val2;
         } else {
              return val1-val2;
         }
     }
     else {
         if (op == '-') {
             return -parse_term(expr.substr(1));
         } else {
             return parse_term(expr.substr(1));
         }
     }
     return 0;
 }
 
 template <>
 scalar_t parse_expression(
         const std::string& expr,
         const std::unordered_map<std::string, scalar_t>& variables
         )
 {
     return ExpressionParser<scalar_t>(expr, variables).parse();
 }
 
 template <>
 index_t parse_expression(
         const std::string& expr,
         const std::unordered_map<std::string, index_t>& variables
         )
 {
     return ExpressionParser<index_t>(expr, variables).parse();
 
 }
 
 
 bool string_to_bool(const std::string& to_bool_str)
 {
     // Contain the strings that matches true or false
     static const char* true_str_test[]  = {"True", "true", "1", "yes", "Yes", "Y"};
     static const char* false_str_test[] = {"False", "false", "0", "no", "No", "N"};
 
     auto trimmed = strip(to_bool_str);
     bool val = false;
     // test for true
     for (auto test: true_str_test) {
         if (test == trimmed) {
             val = true;
             goto exit;
         }
     }
     // test for false
     for (auto test: false_str_test) {
         if (test == trimmed) {
             val = false;
             goto exit;
         }
     }
     // no match => error
     throw std::invalid_argument("Unrecognized value when converting to bool '"
                                 + trimmed + "'. Recognized value : true/false."
                                 );
 
     exit:
     return val;
 }
 
 
 
 } //end namespace utils
 } //end namespace specmicp
 
diff --git a/src/specmicp_common/string_algorithms.hpp b/src/specmicp_common/string_algorithms.hpp
index 478690d..453e2a6 100644
--- a/src/specmicp_common/string_algorithms.hpp
+++ b/src/specmicp_common/string_algorithms.hpp
@@ -1,127 +1,126 @@
 /* =============================================================================
 
  Copyright (c) 2014 - 2016
  F. Georget <fabieng@princeton.edu> Princeton University
  All rights reserved.
 
 
 Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:
 
     1. Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
 
     2. Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
 
     3. Neither the name of the copyright holder nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
 
 ============================================================================= */
 
 #ifndef SPECMICP_UTILS_STRINGALGORITHMS_HPP
 #define SPECMICP_UTILS_STRINGALGORITHMS_HPP
 
 //! \file string_algorithms.hpp
 //! \brief Algorithms for string
 //!
 //! Commom algorithms to handle/parse/modify strings.
 
 #include "types.hpp"
 #include <string>
 #include <vector>
 #include <unordered_map>
 
 namespace specmicp {
 namespace utils {
 
 //! \brief Split a string
 //!
 //! Split a string into several string
 //!
 //! \param to_split the string to split
 //! \param separator the separator to use
 std::vector<std::string> SPECMICP_DLL_PUBLIC  split(
         const std::string& to_split,
         char separator
         );
 
 //! \brief Strip a string
 //!
 //! Remove spaces at the beginning and the end
 std::string SPECMICP_DLL_PUBLIC strip(const std::string& to_trim);
 
 
 //! \brief Get a range of index from a string
 //!
 //! The different format accepted for range_str are :
 //!  - "x"
 //!  - "x-y"
 //!  - "u,v"
 //!
 //! where x,y are number and u,v are valid range_str
 template <typename T=index_t>
 std::vector<T> range_indices(const std::string& range_str);
-
 template <>
 std::vector<index_t> range_indices(const std::string& range_str);
 template <>
 std::vector<uindex_t> range_indices(const std::string& range_str);
 
 //! \brief Parse a simple algebraic expression of type T
 template <typename T>
 T parse_expression(
         const std::string& expr,
         const std::unordered_map<std::string, T>& variables
         );
 // Note : this is a template for API consistence with the overload
 // which doesn't take a map of variables
 
 
 //! \brief Parse a simple algebraic expression of floating numbers
 //!
 //! Parenthesis are not parsed yet and will result in errors
 template <>
 scalar_t parse_expression(
         const std::string& expr,
         const std::unordered_map<std::string, scalar_t>& variables
         );
 
 //! \brief Parse a simple algebraic expression of floating numbers
 //!
 //! Parenthesis are not parsed yet and will result in errors
 template <>
 index_t parse_expression(
         const std::string& expr,
         const std::unordered_map<std::string, index_t>& variables
         );
 
 //! \brief Parse a simple algebraic equation
 template <typename T>
 T parse_expression(
         const std::string& expr
         )
 {
     return parse_expression(expr, std::unordered_map<std::string, T>());
 }
 
 //! \brief Transform a string to a boolean
 bool string_to_bool(const std::string& to_bool_str);
 
 } //end namespace utils
 } //end namespace specmicp
 
 #endif // SPECMICP_UTILS_STRINGALGORITHMS_HPP