Repository: CORE-GATECH-GROUP/serpent-tools

Issue:
Universes from branching file can be stored with negative burnup
## Summary of issue
The burnup values in coefficient files can be negative, indicating units of days, not MWd/kgU
[Link to SERPENT coef card](http://serpent.vtt.fi/mediawiki/index.php/Input_syntax_manual#coef_.28coefficient_matrix_definition.29). This leads to `HomogUniv` objects being created with negative values of burnup, which is _slightly_ nonsensical.

## Code for reproducing the issue
Read in a coefficient file that has negative values of burnup.

## Actual outcome including console output and error traceback if applicable
For some branchContainer `b` in the branching reader:
```
>>> b.universes.keys()
dict_keys([(3102, 0.0, 1), (3102, -200.0, 6), (3102, -328.5, 9), (3102, -246.375, 7), (3102, -280.0, 8), (3102, -164.25, 5), (3102, -82.125, 3), (3102, -120.0, 4), (3102, -40.0, 2)])
>>> univ = b.universes[(3102, -328.5, 9)]
>>> univ.bu
-328.5
>>> univ.day
0
```

## Expected outcome
Universes with non-negative burnup.
Maybe implement a better method for retrieving universes given values of days or burnup.

## Versions

* ``serpentTools.__version__`` 0.2.1+12.g68709f6

Discussion:

Patch:
diff --git a/docs/examples/Branching.rst b/docs/examples/Branching.rst
index 32e10ca..7544198 100644
--- a/docs/examples/Branching.rst
+++ b/docs/examples/Branching.rst
@@ -1,3 +1,9 @@
+.. |branchReader| replace:: :py:class:`~serpentTools.parsers.branching.BranchingReader`
+
+.. |branchContainer| replace:: :py:class:`~serpentTools.objects.containers.BranchContainer`
+
+.. |homogUniv| replace:: :py:class:`~serpentTools.objects.containers.HomogUniv`
+
 .. _branching-ex:
 
 Branching Reader
@@ -34,37 +40,36 @@ The simplest way to read these files is using the
 
     >>> import serpentTools
     >>> branchFile = 'demo.coe'
-    INFO    : serpentTools: Using version 0.2.1
     >>> r0 = serpentTools.read(branchFile)
     INFO    : serpentTools: Inferred reader for demo.coe: BranchingReader
     INFO    : serpentTools: Preparing to read demo.coe
     INFO    : serpentTools: Done reading branching file
 
-The branches are stored in custom
-:py:class:`~serpentTools.objects.containers.BranchContainer` objects in the
-``branches`` dictionary
+The branches are stored in custom |branchContainer| objects in the
+:py:attr:`~serpentTools.parsers.branching.BranchingReader.branches`
+dictionary
 
 .. code:: 
 
     >>> r0.branches
-    {('B1000', 'FT1200'):
-        <serpentTools.objects.containers.BranchContainer at 0x2220c762438>,
+    {('B1000', 'FT1200'): 
+        <serpentTools.objects.containers.BranchContainer at 0x7f2c8d8c9b00>,
      ('B1000', 'FT600'):
-        <serpentTools.objects.containers.BranchContainer at 0x2220c787908>,
-     ('B1000', 'nom'):
-        <serpentTools.objects.containers.BranchContainer at 0x2220c737ef0>,
-     ('B750', 'FT1200'):
-        <serpentTools.objects.containers.BranchContainer at 0x2220c752cf8>,
-     ('B750', 'FT600'):
-        <serpentTools.objects.containers.BranchContainer at 0x2220c77c208>,
-     ('B750', 'nom'):
-        <serpentTools.objects.containers.BranchContainer at 0x2220c72c860>,
-     ('nom', 'FT1200'):
-        <serpentTools.objects.containers.BranchContainer at 0x2220c7455f8>,
-     ('nom', 'FT600'):
-        <serpentTools.objects.containers.BranchContainer at 0x2220c76dac8>,
-     ('nom', 'nom'):
-        <serpentTools.objects.containers.BranchContainer at 0x2220c7231d0>}
+        <serpentTools.objects.containers.BranchContainer at 0x7f2c8cfecfd0>,
+     ('B1000', 'nom'): 
+        <serpentTools.objects.containers.BranchContainer at 0x7f2c8d052b00>,
+     ('B750', 'FT1200'): 
+        <serpentTools.objects.containers.BranchContainer at 0x7f2c8d8cc400>,
+     ('B750', 'FT600'): 
+        <serpentTools.objects.containers.BranchContainer at 0x7f2c8cfe58d0>,
+     ('B750', 'nom'): 
+        <serpentTools.objects.containers.BranchContainer at 0x7f2c8d041470>,
+     ('nom', 'FT1200'): 
+        <serpentTools.objects.containers.BranchContainer at 0x7f2c8cfda208>,
+     ('nom', 'FT600'): 
+        <serpentTools.objects.containers.BranchContainer at 0x7f2c8cfdf1d0>,
+     ('nom', 'nom'): 
+        <serpentTools.objects.containers.BranchContainer at 0x7f2c8d03eda0>}
 
 Here, the keys are tuples of strings indicating what
 perturbations/branch states were applied for each ``SERPENT`` solution.
@@ -83,7 +88,9 @@ Examining a particular case
 
     var V1_name V1_value
 
-cards. These are stored in the ``stateData`` attribute
+cards. These are stored in the 
+:py:attr:`~serpentTools.objects.containers.BranchContainer.stateData` 
+attribute
 
 .. code:: 
 
@@ -106,9 +113,10 @@ Group Constant Data
     Group constants are converted from ``SERPENT_STYLE`` to
     ``mixedCase`` to fit the overall style of the project.
 
-The :py:class:`~serpentTools.objects.containers.BranchContainer` stores group 
-constant data in :py:class:`~serpentTools.objects.containers.HomogUniv`
-objects in the ``universes`` dictionary
+The |branchContainer| stores group 
+constant data in |homogUniv| objects in the 
+:py:attr:`~serpentTools.parsers.branching.BranchingReader.branches`
+dictionary
 
 .. code:: 
 
@@ -129,42 +137,43 @@ objects in the ``universes`` dictionary
      (40, 1.0, 2): <serpentTools.objects.containers.HomogUniv at 0x2220c78bdd8>,
      (40, 10.0, 3): <serpentTools.objects.containers.HomogUniv at 0x2220c791a58>}
 
-The keys here are vectors indicating the universe ID, burnup [MWd/kgU],
-and burnup index corresponding to the point in the burnup schedule.
+The keys here are vectors indicating the universe ID, burnup, and burnup
+index corresponding to the point in the burnup schedule. ``SERPENT``
+prints negative values of burnup to indicate units of days, which is
+reflected in the 
+:py:attr:`~serpentTools.objects.containers.BranchContainer.hasDays`
+attribute. ``hasDays-> True`` indicates
+that the values of burnup, second item in the above tuple, are in terms
+of days, not MWd/kgU.
 These universes can be obtained by indexing this dictionary, or by using
 the :py:meth:`~serpentTools.objects.containers.BranchContainer.getUniv` method
 
 .. code:: 
 
-    >>> univ0 = b0.universes[0, 1, 2]
+    >>> univ0 = b0.universes[0, 1, 1]
     >>> print(univ0)
+    <HomogUniv 0: burnup: 1.000 MWd/kgu, step: 1>
     >>> print(univ0.name)
+    0
     >>> print(univ0.bu)
+    1.0
     >>> print(univ0.step)
+    1
     >>> print(univ0.day)
-    <HomogUniv from demo.coe>
-    0
-    1.0
-    2
-    0
+    None
+    >>> print(b0.hasDays)
+    False
     >>> univ1 = b0.getUniv(0, burnup=1)
-    >>> univ2 = b0.getUniv(0, index=2)
+    >>> univ2 = b0.getUniv(0, index=1)
     >>> assert univ0 is univ1 is univ2
 
-Since the coefficient files do not store the day value of burnup, all
-:py:class:`~serpentTools.objects.containers.HomogUniv` objects created by the
-:py:class:`~serpentTools.objects.containers.BranchContainer` default to day
-zero.
-
 Group constant data is stored in five dictionaries:
 
-1. ``infExp``: Expected values for infinite medium group constants
-2. ``infUnc``: Relative uncertainties for infinite medium group
-   constants
-3. ``b1Exp``: Expected values for leakge-corrected group constants
-4. ``b1Unc``: Relative uncertainties for leakge-corrected group
-   constants
-5. ``metaData``: items that do not fit the in the above categories
+1. :py:attr:`~serpentTools.objects.containers.HomogUniv.infExp`: Expected values for infinite medium group constants
+2. :py:attr:`~serpentTools.objects.containers.HomogUniv.infUnc`: Relative uncertainties for infinite medium group constants
+3. :py:attr:`~serpentTools.objects.containers.HomogUniv.b1Exp`: Expected values for leakge-corrected group constants
+4. :py:attr:`~serpentTools.objects.containers.HomogUniv.b1Unc`: Relative uncertainties for leakge-corrected group constants
+5. :py:attr:`~serpentTools.objects.containers.HomogUniv.metaData`: items that do not fit the in the above categories
 
 .. code:: 
 
@@ -206,7 +215,7 @@ Iteration
 The branching reader has a
 :py:meth:`~serpentTools.parsers.branching.BranchingReader.iterBranches`
 method that works to yield branch names and their associated
-:py:class:`~serpentTools.objects.containers.BranchContainer` objects. This can
+|branchContainer| objects. This can
 be used to efficiently iterate over all the branches presented in the file.
 
 .. code:: 
@@ -231,9 +240,8 @@ User Control
 The ``SERPENT``
 `set coefpara <http://serpent.vtt.fi/mediawiki/index.php/Input_syntax_manual#set_coefpara>`_
 card already restricts the data present in the coeffient file to user
-control, and the :py:class:`~serpentTools.parsers.branching.BranchingReader`
-includes similar control. Below are the various settings that the
-:py:class:`~serpentTools.parsers.branching.BranchingReader` uses to read and
+control, and the |branchReader|  includes similar control. 
+Below are the various settings that the |branchReader| uses to read and
 process coefficient files.
 
 .. code:: 
@@ -290,7 +298,7 @@ that the default action is to store all state data variables as strings.
 
 As demonstrated in the :ref:`group-const-variables` example, use of
 ``xs.variableGroups`` and ``xs.variableExtras`` controls what data is
-stored on the :py:class:`~serpentTools.objects.containers.HomogUniv`
+stored on the |homogUniv| 
 objects. By default, all variables present in the coefficient file are stored.
 
 .. code:: 
@@ -327,8 +335,7 @@ variables explicitly requested are present
 Conclusion
 ----------
 
-The :py:class:`~serpentTools.parsers.branching.BranchingReader` is capable of
-reading coefficient files created
+The |branchReader| is capable of reading coefficient files created
 by the ``SERPENT`` automated branching process. The data is stored
 according to the branch parameters, universe information, and burnup.
 This reader also supports user control of the processing by selecting
diff --git a/examples/Branching.ipynb b/examples/Branching.ipynb
index d2f1836..ca01663 100644
--- a/examples/Branching.ipynb
+++ b/examples/Branching.ipynb
@@ -4,7 +4,7 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "Copyright (c) 2017 Andrew Johnson, Dan Kotlyar, GTRC\n",
+    "Copyright (c) 2017-2018 Andrew Johnson, Dan Kotlyar, Stefano Terlizzi, Gavin Ridley, GTRC\n",
     "\n",
     "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
    ]
@@ -39,17 +39,9 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": 18,
    "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "INFO    : serpentTools: Using version 1.0b0+37.ga1e314a.dirty\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
     "import serpentTools\n",
     "branchFile = 'demo.coe'"
@@ -66,7 +58,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 4,
+   "execution_count": 19,
    "metadata": {},
    "outputs": [
     {
@@ -92,33 +84,33 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 5,
+   "execution_count": 20,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
        "{('B1000',\n",
-       "  'FT1200'): <serpentTools.objects.containers.BranchContainer at 0x2220c762438>,\n",
+       "  'FT1200'): <serpentTools.objects.containers.BranchContainer at 0x7f2c8d8c9b00>,\n",
        " ('B1000',\n",
-       "  'FT600'): <serpentTools.objects.containers.BranchContainer at 0x2220c787908>,\n",
+       "  'FT600'): <serpentTools.objects.containers.BranchContainer at 0x7f2c8cfecfd0>,\n",
        " ('B1000',\n",
-       "  'nom'): <serpentTools.objects.containers.BranchContainer at 0x2220c737ef0>,\n",
+       "  'nom'): <serpentTools.objects.containers.BranchContainer at 0x7f2c8d052b00>,\n",
        " ('B750',\n",
-       "  'FT1200'): <serpentTools.objects.containers.BranchContainer at 0x2220c752cf8>,\n",
+       "  'FT1200'): <serpentTools.objects.containers.BranchContainer at 0x7f2c8d8cc400>,\n",
        " ('B750',\n",
-       "  'FT600'): <serpentTools.objects.containers.BranchContainer at 0x2220c77c208>,\n",
+       "  'FT600'): <serpentTools.objects.containers.BranchContainer at 0x7f2c8cfe58d0>,\n",
        " ('B750',\n",
-       "  'nom'): <serpentTools.objects.containers.BranchContainer at 0x2220c72c860>,\n",
+       "  'nom'): <serpentTools.objects.containers.BranchContainer at 0x7f2c8d041470>,\n",
        " ('nom',\n",
-       "  'FT1200'): <serpentTools.objects.containers.BranchContainer at 0x2220c7455f8>,\n",
+       "  'FT1200'): <serpentTools.objects.containers.BranchContainer at 0x7f2c8cfda208>,\n",
        " ('nom',\n",
-       "  'FT600'): <serpentTools.objects.containers.BranchContainer at 0x2220c76dac8>,\n",
+       "  'FT600'): <serpentTools.objects.containers.BranchContainer at 0x7f2c8cfdf1d0>,\n",
        " ('nom',\n",
-       "  'nom'): <serpentTools.objects.containers.BranchContainer at 0x2220c7231d0>}"
+       "  'nom'): <serpentTools.objects.containers.BranchContainer at 0x7f2c8d03eda0>}"
       ]
      },
-     "execution_count": 5,
+     "execution_count": 20,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -136,7 +128,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": 21,
    "metadata": {},
    "outputs": [
     {
@@ -157,15 +149,17 @@
    "metadata": {},
    "source": [
     "`SERPENT` allows the user to define variables for each branch through:\n",
-    "```\n",
+    "\n",
+    "`\n",
     "var V1_name V1_value\n",
-    "```\n",
+    "`\n",
+    "\n",
     "cards. These are stored in the `stateData` attribute"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 22,
    "metadata": {},
    "outputs": [
     {
@@ -178,7 +172,7 @@
        " 'VERSION': '2.1.29'}"
       ]
      },
-     "execution_count": 7,
+     "execution_count": 22,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -206,74 +200,76 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "The `BranchContainer` stores group constant data in `HomogUniv` objects in the `universes` dictionary"
+    "The `BranchContainer` stores group constant data in `HomogUniv` objects in the `universes` dictionary. "
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 23,
    "metadata": {},
    "outputs": [
     {
-     "data": {
-      "text/plain": [
-       "{(0, 0.0, 1): <serpentTools.objects.containers.HomogUniv at 0x2220c781ac8>,\n",
-       " (0, 1.0, 2): <serpentTools.objects.containers.HomogUniv at 0x2220c78b5f8>,\n",
-       " (0, 10.0, 3): <serpentTools.objects.containers.HomogUniv at 0x2220c791240>,\n",
-       " (10, 0.0, 1): <serpentTools.objects.containers.HomogUniv at 0x2220c787a58>,\n",
-       " (10, 1.0, 2): <serpentTools.objects.containers.HomogUniv at 0x2220c78b6a0>,\n",
-       " (10, 10.0, 3): <serpentTools.objects.containers.HomogUniv at 0x2220c791320>,\n",
-       " (20, 0.0, 1): <serpentTools.objects.containers.HomogUniv at 0x2220c787cc0>,\n",
-       " (20, 1.0, 2): <serpentTools.objects.containers.HomogUniv at 0x2220c78b908>,\n",
-       " (20, 10.0, 3): <serpentTools.objects.containers.HomogUniv at 0x2220c791588>,\n",
-       " (30, 0.0, 1): <serpentTools.objects.containers.HomogUniv at 0x2220c78b048>,\n",
-       " (30, 1.0, 2): <serpentTools.objects.containers.HomogUniv at 0x2220c78bb70>,\n",
-       " (30, 10.0, 3): <serpentTools.objects.containers.HomogUniv at 0x2220c7917f0>,\n",
-       " (40, 0.0, 1): <serpentTools.objects.containers.HomogUniv at 0x2220c78b1d0>,\n",
-       " (40, 1.0, 2): <serpentTools.objects.containers.HomogUniv at 0x2220c78bdd8>,\n",
-       " (40, 10.0, 3): <serpentTools.objects.containers.HomogUniv at 0x2220c791a58>}"
-      ]
-     },
-     "execution_count": 8,
-     "metadata": {},
-     "output_type": "execute_result"
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(0, 1.0, 1)\n",
+      "(10, 1.0, 1)\n",
+      "(20, 1.0, 1)\n",
+      "(30, 1.0, 1)\n",
+      "(20, 0.0, 0)\n",
+      "(40, 0.0, 0)\n",
+      "(20, 10.0, 2)\n",
+      "(10, 10.0, 2)\n",
+      "(0, 0.0, 0)\n",
+      "(10, 0.0, 0)\n",
+      "(0, 10.0, 2)\n",
+      "(30, 0.0, 0)\n",
+      "(40, 10.0, 2)\n",
+      "(40, 1.0, 1)\n",
+      "(30, 10.0, 2)\n"
+     ]
     }
    ],
    "source": [
-    "b0.universes"
+    "for key in b0.universes:\n",
+    "    print(key)"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "The keys here are vectors indicating the universe ID, burnup [MWd/kgU], and burnup index corresponding to the point in the burnup schedule. These universes can be obtained by indexing this dictionary, or by using the `getUniv` method"
+    "The keys here are vectors indicating the universe ID, burnup, and burnup index corresponding to the point in the burnup schedule. `SERPENT` prints negative values of burnup to indicate units of days, which is reflected in the `hasDays` attribute. `hasDays-> True` indicates that the values of burnup, second item in the above tuple, are in terms of days, not MWd/kgU.\n",
+    "\n",
+    "These universes can be obtained by indexing this dictionary, or by using the `getUniv` method."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 24,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "<HomogUniv from demo.coe>\n",
+      "<HomogUniv 0: burnup: 1.000 MWd/kgu, step: 1>\n",
       "0\n",
       "1.0\n",
-      "2\n",
-      "0\n"
+      "1\n",
+      "None\n",
+      "False\n"
      ]
     }
    ],
    "source": [
-    "univ0 = b0.universes[0, 1, 2]\n",
+    "univ0 = b0.universes[0, 1, 1]\n",
     "print(univ0)\n",
     "print(univ0.name)\n",
     "print(univ0.bu)\n",
     "print(univ0.step)\n",
-    "print(univ0.day)"
+    "print(univ0.day)\n",
+    "print(b0.hasDays)"
    ]
   },
   {
@@ -285,34 +281,12 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
-   "metadata": {
-    "collapsed": true
-   },
-   "outputs": [],
-   "source": [
-    "univ1 = b0.getUniv(0, burnup=1)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 11,
-   "metadata": {
-    "collapsed": true
-   },
-   "outputs": [],
-   "source": [
-    "univ2 = b0.getUniv(0, index=2)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 12,
-   "metadata": {
-    "collapsed": true
-   },
+   "execution_count": 25,
+   "metadata": {},
    "outputs": [],
    "source": [
+    "univ1 = b0.getUniv(0, burnup=1)\n",
+    "univ2 = b0.getUniv(0, index=1)\n",
     "assert univ0 is univ1 is univ2"
    ]
   },
@@ -326,12 +300,14 @@
     "1. `infUnc`: Relative uncertainties for infinite medium group constants\n",
     "1. `b1Exp`: Expected values for leakge-corrected group constants\n",
     "1. `b1Unc`: Relative uncertainties for leakge-corrected group constants\n",
-    "1. `metaData`: items that do not fit the in the above categories"
+    "1. `metaData`: items that do not fit the in the above categories, such as energy group structure, k-infinity, etc.\n",
+    "\n",
+    "For this problem, the coefficient file does not have uncertainties, nor these metadata arguments. For this reason, the `infUnc`, `b1Unc`, and `metaData` dictionaries are emtpy."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 13,
+   "execution_count": 26,
    "metadata": {},
    "outputs": [
     {
@@ -345,7 +321,7 @@
        " 'infTot': array([ 0.310842,  0.618286])}"
       ]
      },
-     "execution_count": 13,
+     "execution_count": 26,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -356,7 +332,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 14,
+   "execution_count": 27,
    "metadata": {},
    "outputs": [
     {
@@ -365,7 +341,7 @@
        "{}"
       ]
      },
-     "execution_count": 14,
+     "execution_count": 27,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -376,7 +352,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 15,
+   "execution_count": 28,
    "metadata": {},
    "outputs": [
     {
@@ -390,7 +366,7 @@
        " 'b1Tot': array([ 0.314521,  0.618361])}"
       ]
      },
-     "execution_count": 15,
+     "execution_count": 28,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -401,7 +377,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 16,
+   "execution_count": 29,
    "metadata": {},
    "outputs": [
     {
@@ -410,7 +386,7 @@
        "{}"
       ]
      },
-     "execution_count": 16,
+     "execution_count": 29,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -428,7 +404,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 17,
+   "execution_count": 30,
    "metadata": {},
    "outputs": [
     {
@@ -437,7 +413,7 @@
        "array([ 0.00271604,  0.059773  ])"
       ]
      },
-     "execution_count": 17,
+     "execution_count": 30,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -448,7 +424,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 18,
+   "execution_count": 31,
    "metadata": {},
    "outputs": [
     {
@@ -476,22 +452,22 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 20,
+   "execution_count": 32,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "('nom', 'nom') <BranchContainer for nom, nom from demo.coe>\n",
-      "('B750', 'nom') <BranchContainer for B750, nom from demo.coe>\n",
-      "('B1000', 'nom') <BranchContainer for B1000, nom from demo.coe>\n",
-      "('nom', 'FT1200') <BranchContainer for nom, FT1200 from demo.coe>\n",
-      "('B750', 'FT1200') <BranchContainer for B750, FT1200 from demo.coe>\n",
       "('B1000', 'FT1200') <BranchContainer for B1000, FT1200 from demo.coe>\n",
+      "('B750', 'FT1200') <BranchContainer for B750, FT1200 from demo.coe>\n",
+      "('nom', 'FT1200') <BranchContainer for nom, FT1200 from demo.coe>\n",
       "('nom', 'FT600') <BranchContainer for nom, FT600 from demo.coe>\n",
+      "('B750', 'nom') <BranchContainer for B750, nom from demo.coe>\n",
+      "('nom', 'nom') <BranchContainer for nom, nom from demo.coe>\n",
+      "('B1000', 'FT600') <BranchContainer for B1000, FT600 from demo.coe>\n",
       "('B750', 'FT600') <BranchContainer for B750, FT600 from demo.coe>\n",
-      "('B1000', 'FT600') <BranchContainer for B1000, FT600 from demo.coe>\n"
+      "('B1000', 'nom') <BranchContainer for B1000, nom from demo.coe>\n"
      ]
     }
    ],
@@ -511,10 +487,8 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 21,
-   "metadata": {
-    "collapsed": true
-   },
+   "execution_count": 33,
+   "metadata": {},
    "outputs": [],
    "source": [
     "import six\n",
@@ -523,33 +497,21 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 22,
+   "execution_count": 34,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "branching.areUncsPresent\n",
-      "\t default: False\n",
+      "xs.getInfXS\n",
+      "\t default: True\n",
+      "\t description: If true, store the infinite medium cross sections.\n",
       "\t type: <class 'bool'>\n",
-      "\t description: True if the values in the .coe file contain uncertainties\n",
-      "branching.intVariables\n",
-      "\t default: []\n",
-      "\t description: Name of state data variables to convert to integers for each branch\n",
-      "\t type: <class 'list'>\n",
       "branching.floatVariables\n",
       "\t default: []\n",
       "\t description: Names of state data variables to convert to floats for each branch\n",
       "\t type: <class 'list'>\n",
-      "xs.getInfXS\n",
-      "\t default: True\n",
-      "\t description: If true, store the infinite medium cross sections.\n",
-      "\t type: <class 'bool'>\n",
-      "xs.getB1XS\n",
-      "\t default: True\n",
-      "\t description: If true, store the critical leakage cross sections.\n",
-      "\t type: <class 'bool'>\n",
       "xs.variableGroups\n",
       "\t default: []\n",
       "\t description: Name of variable groups from variables.yaml to be expanded into SERPENT variable to be stored\n",
@@ -557,7 +519,19 @@
       "xs.variableExtras\n",
       "\t default: []\n",
       "\t description: Full SERPENT name of variables to be read\n",
-      "\t type: <class 'list'>\n"
+      "\t type: <class 'list'>\n",
+      "branching.intVariables\n",
+      "\t default: []\n",
+      "\t description: Name of state data variables to convert to integers for each branch\n",
+      "\t type: <class 'list'>\n",
+      "branching.areUncsPresent\n",
+      "\t default: False\n",
+      "\t description: True if the values in the .coe file contain uncertainties\n",
+      "\t type: <class 'bool'>\n",
+      "xs.getB1XS\n",
+      "\t default: True\n",
+      "\t description: If true, store the critical leakage cross sections.\n",
+      "\t type: <class 'bool'>\n"
      ]
     }
    ],
@@ -579,10 +553,8 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 23,
-   "metadata": {
-    "collapsed": true
-   },
+   "execution_count": 35,
+   "metadata": {},
    "outputs": [],
    "source": [
     "assert isinstance(b0.stateData['BOR'], str)"
@@ -592,7 +564,7 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "As demonstrated in the `Settings` example, use of `xs.variableGroups` and `xs.variableExtras` controls what data is stored on the `HomogUniv` objects. By default, all variables present in the coefficient file are stored."
+    "As demonstrated in the [Settings example](https://github.com/CORE-GATECH-GROUP/serpent-tools/blob/master/examples/Settings.ipynb), use of `xs.variableGroups` and `xs.variableExtras` controls what data is stored on the `HomogUniv` objects. By default, all variables present in the coefficient file are stored."
    ]
   },
   {
@@ -654,9 +626,7 @@
   {
    "cell_type": "code",
    "execution_count": 39,
-   "metadata": {
-    "collapsed": true
-   },
+   "metadata": {},
    "outputs": [],
    "source": [
     "assert isinstance(b1.stateData['BOR'], float)\n",
@@ -736,7 +706,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.6.1"
+   "version": "3.5.2"
   }
  },
  "nbformat": 4,
diff --git a/serpentTools/objects/containers.py b/serpentTools/objects/containers.py
index 745a613..8213dd2 100644
--- a/serpentTools/objects/containers.py
+++ b/serpentTools/objects/containers.py
@@ -4,6 +4,7 @@ Contents
 --------
 :py:class:`~serpentTools.objects.containers.HomogUniv`
 :py:class:`~serpentTools.objects.containers.BranchContainer
+:py:class:`~serpentTools.objects.containers.DetectorBase`
 :py:class:`~serpentTools.objects.containers.Detector`
 
 """
@@ -22,6 +23,17 @@ DET_COLS = ('value', 'energy', 'universe', 'cell', 'material', 'lattice',
 """Name of the columns of the data"""
 
 
+__all__ = ('DET_COLS', 'HomogUniv', 'BranchContainer', 'Detector',
+           'DetectorBase')
+
+
+def isNonNeg(value):
+    """Return true if a value is None or non-negative"""
+    if value is None:
+        return True
+    return value >= 0
+
+
 class HomogUniv(NamedObject):
     """
     Class for storing homogenized universe specifications and retrieving them
@@ -41,12 +53,12 @@ class HomogUniv(NamedObject):
     ----------
     name: str
         name of the universe
-    bu: float
-        burnup value
-    step: float
+    bu: float or int
+        non-negative burnup value
+    step: int
         temporal step
-    day: float
-        depletion day
+    day: float or int
+        non-negative depletion day
     infExp: dict
         Expected values for infinite medium group constants
     infUnc: dict
@@ -57,10 +69,26 @@ class HomogUniv(NamedObject):
         Relative uncertainties for leakage-corrected group constants
     metadata: dict
         Other values that do not not conform to inf/b1 dictionaries
+
+    Raises
+    ------
+    SerpentToolsException:
+        If a negative value of burnup, step, or burnup days is passed
+
     """
 
     def __init__(self, name, bu, step, day):
+        if not all(isNonNeg(xx) for xx in (bu, step, day)): 
+            tail = ['{}: {}'.format(name, val)
+                for name, val in zip(('burnup', 'index', 'days'),
+                                               (bu, step, day))]
+            raise SerpentToolsException(
+                "Will not create universe with negative burnup\n{}"
+                .format(', '.join(tail)))
         NamedObject.__init__(self, name)
+        if step is not None and step == 0:  
+            bu = bu if bu is not None else 0.0
+            day = day if day is not None else 0.0
         self.bu = bu
         self.step = step
         self.day = day
@@ -71,9 +99,22 @@ class HomogUniv(NamedObject):
         self.infUnc = {}
         self.metadata = {}
 
+    def __str__(self):
+        extras = []
+        if self.bu is not None:
+            extras.append('burnup: {:5.3f} MWd/kgu'.format(self.bu))
+        if self.step:
+            extras.append('step: {}'.format(self.step))
+        if self.day is not None:
+            extras.append('{:5.3f} days'.format(self.day))
+        if extras:
+            extras = ': ' + ', '.join(extras)
+        return '<{} {}{}>'.format(self.__class__.__name__, self.name,
+                                  extras or '')
+    
     def addData(self, variableName, variableValue, uncertainty=False):
         """
-        Sets the value of the variable and, optionally, the associate s.d.
+        sets the value of the variable and, optionally, the associate s.d.
 
         .. warning::
 
@@ -658,6 +699,8 @@ class BranchContainer(object):
         Keys are tuples of
         ``(universeID, burnup, burnIndex)``
     """
+    __mismatchedBurnup = ("Was not expecting a {} value of burnup. "
+                          "Expect burnup in units of {}")
 
     def __init__(self, filePath, branchID, branchNames, stateData):
         self.filePath = filePath
@@ -667,6 +710,7 @@ class BranchContainer(object):
         self.branchNames = branchNames
         self.__orderedUniverses = None
         self.__keys = set()
+        self.__hasDays = None
 
     def __str__(self):
         return '<BranchContainer for {} from {}>'.format(
@@ -693,8 +737,11 @@ class BranchContainer(object):
         Add a universe to this branch.
 
         Data for the universes are produced at specific points in time.
-        The additional arguments help track when the data for this
+        The additional arguments help track of when the data for this
         universe were created.
+        A negative value of ``burnup`` indicates the units on burnup are
+        really ``days``. Therefore, the value of ``burnDays`` and ``burnup``
+        will be swapped.
 
         .. warning::
 
@@ -705,7 +752,8 @@ class BranchContainer(object):
         univID: int or str
             Identifier for this universe
         burnup: float or int
-            Value of burnup [MWd/kgU]
+            Value of burnup [MWd/kgU]. A negative value here indicates
+            the value is really in units of days.
         burnIndex: int
             Point in the depletion schedule
         burnDays: int or float
@@ -713,11 +761,24 @@ class BranchContainer(object):
 
         Returns
         -------
-        newUniv: serpentTools.objects.containers.HomogUniv
+        serpentTools.objects.containers.HomogUniv
+            Empty new universe
+
         """
+        if self.__hasDays is None and burnup:
+            self.__hasDays = burnup < 0
+        if burnup < 0:
+            if not self.__hasDays:
+                raise SerpentToolsException(self.__mismatchedBurnup.format(
+                    'negative', 'MWd/kgU'))
+            burnup, burnDays = None if burnup else 0, - burnup
+        else:
+            if self.__hasDays and not burnDays:
+                raise SerpentToolsException(self.__mismatchedBurnup.format(
+                    'positive', 'days'))
+            burnDays = None if burnup else 0
         newUniv = HomogUniv(univID, burnup, burnIndex, burnDays)
-        key = tuple(
-            [univID, burnup, burnIndex] + ([burnDays] if burnDays else []))
+        key = (univID, burnup or burnDays, burnIndex)
         if key in self.__keys:
             warning('Overwriting existing universe {} in {}'
                     .format(key, str(self)))
@@ -743,8 +804,8 @@ class BranchContainer(object):
 
         Returns
         -------
-        univ: serpentTools.objects.containers.HomogUniv
-            Requested Universe
+        :py:class:`~serpentTools.objects.containers.HomogUniv`
+            Requested universe
 
         Raises
         ------
@@ -755,7 +816,7 @@ class BranchContainer(object):
         """
         if burnup is None and index is None:
             raise SerpentToolsException('Burnup or index are required inputs')
-        searchIndex = 2 if index is not None else 1
+        searchIndex = 2 if index is not None else 1 
         searchValue = index if index is not None else burnup
         for key in self.__keys:
             if key[0] == univID and key[searchIndex] == searchValue:
@@ -766,3 +827,11 @@ class BranchContainer(object):
         raise KeyError(
             'Could not find a universe that matched requested universe {} and '
             '{} {}'.format(univID, searchName, searchValue))
+
+    @property
+    def hasDays(self):
+        """Returns True if the burnups in the file are in units of days"""
+        if self.__hasDays is None:
+            raise AttributeError("Need to load at least one universe with "
+                                 "non-zero burnup first.""")
+        return self.__hasDays
diff --git a/serpentTools/parsers/branching.py b/serpentTools/parsers/branching.py
index 795036e..8b18e52 100644
--- a/serpentTools/parsers/branching.py
+++ b/serpentTools/parsers/branching.py
@@ -17,6 +17,10 @@ class BranchingReader(XSReader):
     ----------
     filePath: str
         path to the depletion file
+    branches: dict
+        Dictionary of branch names and their corresponding
+        :py:class:`~serpentTools.objects.containers.BranchContainer`
+        objects
     """
 
     def __init__(self, filePath):
@@ -98,7 +102,7 @@ class BranchingReader(XSReader):
     def _processBranchUniverses(self, branch, burnup, burnupIndex):
         """Add universe data to this branch at this burnup."""
         unvID, numVariables = [int(xx) for xx in self._advance()]
-        univ = branch.addUniverse(unvID, burnup, burnupIndex)
+        univ = branch.addUniverse(unvID, burnup, burnupIndex - 1)
         for step in range(numVariables):
             splitList = self._advance(
                 possibleEndOfFile=step == numVariables - 1)


Test patch:
diff --git a/serpentTools/tests/test_branching.py b/serpentTools/tests/test_branching.py
index 8bfd381..be967f5 100644
--- a/serpentTools/tests/test_branching.py
+++ b/serpentTools/tests/test_branching.py
@@ -10,6 +10,7 @@ from numpy.testing import assert_allclose
 from serpentTools.settings import rc
 from serpentTools.tests import TEST_ROOT
 from serpentTools.parsers import BranchingReader
+from serpentTools.objects.containers import BranchContainer
 from serpentTools.messages import SerpentToolsException
 
 
@@ -22,7 +23,7 @@ class _BranchTesterHelper(unittest.TestCase):
         cls.expectedBranches = {('nom', 'nom', 'nom')}
         cls.expectedUniverses = {
             # universe id, burnup, step
-            (0, 0, 1),
+            (0, 0, 0),
         }
         with rc:
             rc['serpentVersion'] = '2.1.29'
@@ -76,7 +77,7 @@ class BranchContainerTester(_BranchTesterHelper):
     def setUpClass(cls):
         _BranchTesterHelper.setUpClass()
         cls.refBranchID = ('nom', 'nom', 'nom')
-        cls.refUnivKey = (0, 0, 1)
+        cls.refUnivKey = (0, 0, 0)
         cls.refBranch = cls.reader.branches[cls.refBranchID]
         cls.refUniv = cls.refBranch.universes[cls.refUnivKey]
 
@@ -108,6 +109,18 @@ class BranchContainerTester(_BranchTesterHelper):
         with self.assertRaises(SerpentToolsException):
             self.refBranch.getUniv(key[0])
 
+    def test_cannotAddBurnupDays(self):
+        """
+        Verify that a universe cannot be added with burnup of opposite units.
+        """
+        containerWithBU = BranchContainer(None, None, None, None)
+        containerWithBU.addUniverse(101, 10, 1)
+        containerWithDays = BranchContainer(None, None, None, None)
+        containerWithDays.addUniverse(101, -10, 1)
+        with self.assertRaises(SerpentToolsException):
+            containerWithBU.addUniverse(101, -10, 1)
+        with self.assertRaises(SerpentToolsException):
+            containerWithDays.addUniverse(101, 10, 1)
 
 if __name__ == '__main__':
     unittest.main()