Chris Mutel committed 0301371

Major documentation efforts

Comments (0)

Files changed (10)

 - import_method can't handle SimaPro XML files (where exchanges are numbered sequentially)
-- RobustFinder to find processes or flows which aren't correctly specified (import scripts)
-- Manager.copy() should copy databases and methods
+- RobustFinder to find processes or flows which aren't correctly specified (import scripts)


 class Config(object):
+    """A singleton that store configuration settings. Default data directory is ``brightway`` in the user's home directory, and is stored as ``config.dir``. Other configuration settings can also be assigned as needed.
+    Args:
+        *path* (str, optional): The path of the data directory. Must be writeable.
+    """
     def __init__(self, path=None):
+        self.is_temp_dir = False
-    def check_dir(self):
-        pass
+    def check_dir(self, dir=None):
+        """Check is directory is writeable."""
+        return os.access(dir or self.dir, os.W_OK)
     def reset(self, path=None):
         """Reset to original configuration. Useful for testing."""
         self.dir = self.get_home_directory(path)
-        if not os.access(self.dir, os.W_OK):
-            print "Using temporary directory:"
+        if not self.check_dir():
             self.dir = tempfile.mkdtemp()
+            self.is_temp_dir = True
+            print "Your changes will not be saved! Set a writeable directory!"
+            print "Current data directory is:"
             print self.dir
-            print "Your changes will not be saved! Set a writeable directory!"
-        self.check_dir()
-    def get_home_directory(self, path):
+    def get_home_directory(self, path=None):
+        """Get data directory, trying in order:
+        * Provided path (optional)
+        * ``BRIGHTWAY2-DIR`` environment variable
+        * ``brightway2`` in user's home directory
+        To set the environment variable:
+        * Unix/Max: ``export BRIGHTWAY2-DIR=/path/to/brightway2/directory``
+        * Windows: ``set BRIGHTWAY2-DIR=\path\to\brightway2\directory``
+        """
         if path:
             return path
-        # Unix/Max: export BRIGHTWAY2-VAR=/brightway2/directory
-        # Windows: set BRIGHTWAY2-VAR=\brightway2\directory
-        envvar = os.getenv("BRIGHTWAY2-VAR")
+        envvar = os.getenv("BRIGHTWAY2-DIR")
         if envvar:
             return envvar
             return os.path.expanduser("~/brightway2")
+    def request_dir(self, dirname):
+        """Return ``True`` if directory already exists or can be created."""
+        path = os.path.join(self.dir, dirname)
+        if self.check_dir(path):
+            return True
+        else:
+            try:
+                os.mkdir(path)
+                return True
+            except:
+                return False
     def _get_dir(self):
         return self._dir
     def _set_dir(self, d):
         self._dir = d
-        self.check_dir()
+        if not self.check_dir():
+            raise OSError("This directory is not writeable")
     dir = property(_get_dir, _set_dir)


 class Mapping(PickledDict):
+    """A dictionary that maps object ids, like ``("Ecoinvent 2.2", 42)``, to integers. Needed because parameter arrays have integer ``row`` and ``column`` fields.
+    File data is saved in ``mapping.pickle``.
+    This dictionary does not support setting items directly; instead, use the ``add`` method to add multiple keys."""
     _filename = "mapping.pickle"
     def add(self, keys):
+        """Add a set of keys. These keys can already be in the mapping; only new keys will be added.
+        Args:
+            *keys* (list): The keys to add.
+        """
         index = max(
         for i, key in enumerate(keys):
             if key not in
     def delete(self, keys):
+        """Delete a set of keys.
+        Args:
+            *keys* (list): The keys to delete.
+        """
         for key in keys:
     def __unicode__(self):
         return u"Mapping from databases and methods to parameter indices."
+    def __len__(self):
+        return len(
 class Databases(SerializedDict):
+    """A dictionary for database metadata. This class includes methods to manage database versions. File data is saved in ``databases.json``."""
     _filename = "databases.json"
     def increment_version(self, database):
+        """Increment the ``database`` version. Returns the new version."""[database]["version"] += 1
     def version(self, database):
+        """Return the ``database`` version"""
     def __unicode__(self):
 class Methods(SerializedDict):
+    """A dictionary for method metadata. File data is saved in ``methods.json``."""
     _filename = "methods.json"
     def pack(self, data):
-        # Transform to list because JSON can't handle lists as keys
+        """Transform the dictionary to a list because JSON can't handle lists as keys"""
         return [(k, v) for k, v in data.iteritems()]
     def unpack(self, data):
-        # Tuples can be dict keys, but not lists; JSON can't encode tuples
+        """Transform data back to a dictionary"""
         return dict([(tuple(x[0]), x[1]) for x in data])
     def __unicode__(self):


     "iin": lambda x, y: x.lower() in y.lower(),
     "inot": lambda x, y: x.lower() != y.lower(),
     "iis": lambda x, y: x.lower() == y.lower(),
+    "len": lambda x, y: len(x) == y,


 class SerializedDict(object):
+    """Base class for dictionary that can be serlialized to of unserialized from disk. Uses JSON as its storage format. Has most of the methods of a dictionary.
+    Upon instantiation, the serialized dictionary is read from disk."""
     def __init__(self):
+        if not getattr(self, "_filename"):
+            raise NotImplemented("SerializedDict must be subclassed, and the filename must be set.")
         self._filepath = os.path.join(config.dir, self._filename)
     def load(self):
+        """Load the serialized data. Creates the file if not yet present."""
    = self.deserialize()
         except IOError:
     def flush(self):
+        """Serialize the current data to disk."""
     def list(self):
+        """List the keys of the dictionary. This is a property, and does not need to be called."""
         return sorted(
     def __getitem__(self, key):
     def serialize(self, filepath=None):
+        """Method to do the actual serialization. Can be replaced with other serialization formats.
+        Args:
+            *filepath* (str, optional): Provide an alternate filepath (e.g. for backup).
+        """
         with open(filepath or self._filepath, "w") as f:
             json.dump(self.pack(, f, indent=2)
     def deserialize(self):
+        """Load the serialized data. Can be replaced with other serialization formats."""
         return self.unpack(json.load(open(self._filepath, "r")))
     def pack(self, data):
+        """Transform the data, if necessary. Needed because JSON must have strings as dictionary keys."""
         return data
     def unpack(self, data):
+        """Return serialized data to true form."""
         return data
     def backup(self):
-        """Write a backup version of the data to backups directory"""
+        """Write a backup version of the data to the ``backups`` directory."""
         filepath = os.path.join(config.dir, "backups",
             self._filename + ".%s.backup" % int(time()))
 class PickledDict(SerializedDict):
+    """Subclass of ``SerializedDict`` that uses the pickle format instead of JSON."""
     def serialize(self):
         with open(self._filepath, "wb") as f:
             pickle.dump(self.pack(, f,


 .. autoclass:: brightway2.Method
 .. Brightway2 documentation master file, created by
    sphinx-quickstart on Tue Nov 13 15:32:29 2012.
-Documentation for the core Brightway2 LCA framework
+Brightway2 life cycle assessment framework
+Brightway2 is a simple framework for life cycle assessment (LCA). Its focus is on efficient calculation and visualization. Brightway2 is a complete rewrite of the original Brightway, which was a previous LCA framework developed during the PhD thesis of Chris Mutel.
+Fast LCA and Monte Carlo calculations
+The life cycle assessment calculators are the most advanced part of Brightway2. For those that are interested, a full technical guide is available. For the rest of you, suffice it to say that LCA calculations are powerful and efficient (working with LCI databases of hundreds of thousands of processes has been done successfully), and the Monte Carlo implementation allows for effective use of modern computers. On a semi-modern laptop, around 100 Monte Carlo iterations per core are possible, and each core can be used in parallel.
+New data visualizations
+(Include visualizations here)
+Treemaps and Hinton matrices are already part of the standard LCA report, and new visualizations using the D3 library are planned. See the examples.
+Simple data structure
+Brightway2 uses a very simple data structure. Instead of a database, which is powerful but difficult to install or upgrade, Brightway2 uses a data directory, and saves data as Python datastructures serialized to normal files. The location of the data directory can be configured; default is in your home directory. Although this approach loses some of the benefits of relational databases, it has several advantages:
+* No database installation or configuration.
+* You can easily share your work with someone else by copying the data directory and sending it to your colleagues. Syncing services like dropbox can also be easily used.
+* Copying, modifying, and backing up databases is easy and fast.
+Table of contents:
 .. toctree::
-   :maxdepth: 1
+   :maxdepth: 2
+   querying
+   technical
 Indices and tables
 * :ref:`genindex`
-* :ref:`modindex`
 * :ref:`search`


 Introduction to Brightway2
-This is it!
+Brightway2 has the following features:
+* Foo
+* Bar


+Querying a database or method
+The Database class
+.. autoclass:: brightway2.Result
+	:members:
+.. autoclass:: brightway2.Query
+	:members:
+.. autoclass:: brightway2.Filter
+	:members:


+Technical guide
+Modular structure
+Brightway2 is a framework for life cycle assessment, and consists of several packages. You only need to install or understand the components that are of interest to you. Splitting components allow for a clean separation of concerns, as each package has a limited focus, and makes testing and documenting each package easier and cleaner. 
+This guide has technical details for the ``brightway2`` package. Each separate package also has its own documentation.
+The current components of Brightway2 are:
+* brightway2: This package provides data handling, querying, and import/export functionality.
+* brightway2-calc: The LCA calculators. Normal LCA, several varieties of Monte Carlo LCA (including parallel Monte Carlo using all the cores on your computer), Latin Hypercubic sampling, and graph traversal.
+* brightway2-analyzer: Functions for analyzing the results of LCA calculations, including contribution and sensitivity analysis.
+* brightway2-ui: Two different user interfaces for Brightway2. Brightway2 is pure Python, and can be used by other programs or in an ipython notebook. For people who aren't as comfortable programming in Python, this packages provides a command line interface for work in the terminal, and a web interface.
+* brightway2-speedups: A few small utilities that can make calculations faster. Requires Cython.
+The configuration for brightway2 (which is currently only the location of the data directory) is implemented as a singleton class that is created when ``brightway2`` is imported.
+.. autoclass:: brightway2._config.Config
+	:members:
+.. autoclass:: brightway2.meta.Databases
+	:members:
+	:inherited-members:
+.. autoclass:: brightway2.meta.Methods
+	:members:
+	:inherited-members:
+.. autoclass:: brightway2.meta.Mapping
+	:members:
+	:inherited-members:
+Documentation is uses `Sphinx <>`_ to build the source files into other forms. Building is as simple as changing to the docs directory, and running ``make.bat html`` in Windows and ``make html`` in OS X and Linux.