<commit_before># -*- coding: utf-8 -*-
from plone.dexterity.fti import DexterityFTI
from plone.dexterity.fti import register
from plone.server import _
from plone.server import DEFAULT_LAYER
from plone.server import DEFAULT_PERMISSION
from plone.server import DICT_LANGUAGES
from plone.server import DICT_METHODS
from plone.server import DICT_RENDERS
from plone.server.utils import import_class
from zope.component.zcml import adapter
from zope.configuration import fields as configuration_fields
from zope.configuration.exceptions import ConfigurationError
from zope.configuration.fields import Path
from zope.interface import Interface
from zope.security.checker import Checker
from zope.security.checker import defineChecker
from zope.security.checker import getCheckerForInstancesOf
from zope.security.checker import undefineChecker

import json
import os

class IContentTypeDirective(Interface):

    portal_type = configuration_fields.MessageID(
        title=_('Portal type'),
        description='',
        required=True
    )

    class_ = configuration_fields.GlobalObject(
        title=_('Class'),
        description='',
        required=False
    )

    schema = configuration_fields.GlobalInterface(
        title='',
        description='',
        required=True
    )

    behaviors = configuration_fields.Tokens(
        title='',
        description='',
        value_type=configuration_fields.GlobalInterface(),
        required=True
    )

def contenttypeDirective(_context,
                         portal_type,
                         class_,
                         schema,
                         behaviors=[],
                         add_permission=None):
    ''' Generate a Dexterity FTI and factory for the passed schema '''
    interface_name = schema.__identifier__
    behavior_names = [a.__identifier__ for a in behaviors]
    dotted_name = None
    if class_:
        dotted_name = '{0}.{1}'.format(class_.__module__, class_.__name__)
    fti_args = {'id': portal_type,
                'content_meta_type': portal_type,
                'klass': dotted_name,
                'schema': interface_name,
                'behaviors': behavior_names}
    if add_permission is not None:
        fti_args['add_permission'] = add_permission

    fti = DexterityFTI(**fti_args)

    register(fti)

class IApi(Interface):
    '''
    '''

    file = Path(
        title='The name of a file defining the api.',
        description='Refers to a file containing a json definition.',
        required=False
    )

def register_service(
        _context,
        configuration,
        content,
        method,
        layer,
        default_permission,
        name=''):
    print(configuration)  # noqa
    factory = import_class(configuration['factory'])
    if factory is None:
        raise TypeError(
            'Factory not defined {0:s} '.format(configuration['factory']))
    if getCheckerForInstancesOf(factory):
        # in case already exist remove old checker
        undefineChecker(factory)
    if 'permission' in configuration:
        permission = configuration['permission']
    else:
        permission = default_permission
    required = {}
    for n in ('__call__', 'publishTraverse'):
        required[n] = permission

    defineChecker(factory, Checker(required))
    print('Defining adapter for '  # noqa
          '{0:s} {1:s} {2:s} to {3:s} name {4:s}'.format(
        content.__identifier__,
        DICT_METHODS[method].__identifier__,
        layer.__identifier__,
        str(factory),
        name))
    adapter(
        _context,
        factory=(factory,),
        provides=DICT_METHODS[method],
        for_=(content, layer),
        name=name
    )

def apiDirective(_context, file):  # noqa 'too complex' :)

    if file:
        file = os.path.abspath(_context.path(file))
        if not os.path.isfile(file):
            raise ConfigurationError('No such file', file)

    with open(file, 'r') as f:
        json_info = json.loads(f.read())
        f.close()

    if 'methods' in json_info:
        for method, method_interface in json_info['methods'].items():
            DICT_METHODS[method] = import_class(method_interface)

    if 'layer' in json_info:
        layer = json_info['layer']
        layer = import_class(layer)
        if len(DEFAULT_LAYER) == 0:
            DEFAULT_LAYER.append(layer)
    else:
        layer = DEFAULT_LAYER[0]

    if 'default_permission' in json_info:
        default_permission = json_info['default_permission']
        if len(DEFAULT_PERMISSION) == 0:
            DEFAULT_PERMISSION.append(default_permission)
    else:
        default_permission = DEFAULT_PERMISSION[0]

    if 'renderers' in json_info:
        for accept, renderer_interface in json_info['renderers'].items():
            # We define which Interface is for the content negotiation
            DICT_RENDERS[accept] = import_class(renderer_interface)

    if 'languages' in json_info:
        for language, language_interface in json_info['languages'].items():
            # We define which Interface is for the languages
            print(language_interface)  # noqa
            DICT_LANGUAGES[language] = import_class(language_interface)

    if 'contenttypes' in json_info:
        for contenttype, configuration in json_info['contenttypes'].items():
            content_interface = import_class(contenttype)
            for method, method_configuration in configuration.items():
                if method != 'endpoints':
                    register_service(
                        _context,
                        method_configuration,
                        content_interface,
                        method,
                        layer,
                        default_permission)

            if 'endpoints' in configuration:
                for endpoint, endpoint_configuration in configuration['endpoints'].items():  # noqa
                    for method, method_configuration in endpoint_configuration.items():  # noqa
                        register_service(
                            _context,
                            method_configuration,
                            content_interface,
                            method,
                            layer,
                            default_permission,
                            endpoint)
<commit_msg>Set class' meta_type if it's not already there<commit_after># -*- coding: utf-8 -*-
from plone.dexterity.fti import DexterityFTI
from plone.dexterity.fti import register
from plone.server import _
from plone.server import DEFAULT_LAYER
from plone.server import DEFAULT_PERMISSION
from plone.server import DICT_LANGUAGES
from plone.server import DICT_METHODS
from plone.server import DICT_RENDERS
from plone.server.utils import import_class
from zope.component.zcml import adapter
from zope.configuration import fields as configuration_fields
from zope.configuration.exceptions import ConfigurationError
from zope.configuration.fields import Path
from zope.interface import Interface
from zope.security.checker import Checker
from zope.security.checker import defineChecker
from zope.security.checker import getCheckerForInstancesOf
from zope.security.checker import undefineChecker

import json
import os

class IContentTypeDirective(Interface):

    portal_type = configuration_fields.MessageID(
        title=_('Portal type'),
        description='',
        required=True
    )

    class_ = configuration_fields.GlobalObject(
        title=_('Class'),
        description='',
        required=False
    )

    schema = configuration_fields.GlobalInterface(
        title='',
        description='',
        required=True
    )

    behaviors = configuration_fields.Tokens(
        title='',
        description='',
        value_type=configuration_fields.GlobalInterface(),
        required=True
    )

def contenttypeDirective(_context,
                         portal_type,
                         class_,
                         schema,
                         behaviors=[],
                         add_permission=None):
    ''' Generate a Dexterity FTI and factory for the passed schema '''
    interface_name = schema.__identifier__
    behavior_names = [a.__identifier__ for a in behaviors]
    dotted_name = None
    if class_:
        if not hasattr(class_, 'meta_type'):
            class_.meta_type = portal_type
        dotted_name = '{0}.{1}'.format(class_.__module__, class_.__name__)
    fti_args = {'id': portal_type,
                'klass': dotted_name,
                'schema': interface_name,
                'behaviors': behavior_names}
    if add_permission is not None:
        fti_args['add_permission'] = add_permission

    fti = DexterityFTI(**fti_args)

    register(fti)

class IApi(Interface):
    '''
    '''

    file = Path(
        title='The name of a file defining the api.',
        description='Refers to a file containing a json definition.',
        required=False
    )

def register_service(
        _context,
        configuration,
        content,
        method,
        layer,
        default_permission,
        name=''):
    print(configuration)  # noqa
    factory = import_class(configuration['factory'])
    if factory is None:
        raise TypeError(
            'Factory not defined {0:s} '.format(configuration['factory']))
    if getCheckerForInstancesOf(factory):
        # in case already exist remove old checker
        undefineChecker(factory)
    if 'permission' in configuration:
        permission = configuration['permission']
    else:
        permission = default_permission
    required = {}
    for n in ('__call__', 'publishTraverse'):
        required[n] = permission

    defineChecker(factory, Checker(required))
    print('Defining adapter for '  # noqa
          '{0:s} {1:s} {2:s} to {3:s} name {4:s}'.format(
        content.__identifier__,
        DICT_METHODS[method].__identifier__,
        layer.__identifier__,
        str(factory),
        name))
    adapter(
        _context,
        factory=(factory,),
        provides=DICT_METHODS[method],
        for_=(content, layer),
        name=name
    )

def apiDirective(_context, file):  # noqa 'too complex' :)

    if file:
        file = os.path.abspath(_context.path(file))
        if not os.path.isfile(file):
            raise ConfigurationError('No such file', file)

    with open(file, 'r') as f:
        json_info = json.loads(f.read())
        f.close()

    if 'methods' in json_info:
        for method, method_interface in json_info['methods'].items():
            DICT_METHODS[method] = import_class(method_interface)

    if 'layer' in json_info:
        layer = json_info['layer']
        layer = import_class(layer)
        if len(DEFAULT_LAYER) == 0:
            DEFAULT_LAYER.append(layer)
    else:
        layer = DEFAULT_LAYER[0]

    if 'default_permission' in json_info:
        default_permission = json_info['default_permission']
        if len(DEFAULT_PERMISSION) == 0:
            DEFAULT_PERMISSION.append(default_permission)
    else:
        default_permission = DEFAULT_PERMISSION[0]

    if 'renderers' in json_info:
        for accept, renderer_interface in json_info['renderers'].items():
            # We define which Interface is for the content negotiation
            DICT_RENDERS[accept] = import_class(renderer_interface)

    if 'languages' in json_info:
        for language, language_interface in json_info['languages'].items():
            # We define which Interface is for the languages
            print(language_interface)  # noqa
            DICT_LANGUAGES[language] = import_class(language_interface)

    if 'contenttypes' in json_info:
        for contenttype, configuration in json_info['contenttypes'].items():
            content_interface = import_class(contenttype)
            for method, method_configuration in configuration.items():
                if method != 'endpoints':
                    register_service(
                        _context,
                        method_configuration,
                        content_interface,
                        method,
                        layer,
                        default_permission)

            if 'endpoints' in configuration:
                for endpoint, endpoint_configuration in configuration['endpoints'].items():  # noqa
                    for method, method_configuration in endpoint_configuration.items():  # noqa
                        register_service(
                            _context,
                            method_configuration,
                            content_interface,
                            method,
                            layer,
                            default_permission,
                            endpoint)
<|endoftext|>


<commit_before>#!/usr/bin/python

from __future__ import division, print_function, absolute_import, unicode_literals
import btrfs
import hilbert
import png
import sys

try:
    xrange
except NameError:
    xrange = range

debug = False

def device_size_offsets(fs):
    bytes_seen = 0
    offsets = {}
    for device in fs.devices():
        offsets[device.devid] = bytes_seen
        bytes_seen += device.total_bytes
    return bytes_seen, offsets

def finish_pixel(png_grid, pos):
    used_pct = png_grid[pos.y][pos.x]
    if isinstance(used_pct, int) and used_pct == 0:
        return
    brightness = 16 + int(round(used_pct * (255 - 16)))
    png_grid[pos.y][pos.x] = brightness
    if debug is True:
        print("{0} value {1}".format(pos, brightness))

def main():
    nargs = len(sys.argv)
    if nargs < 3 or nargs > 4:
        sys.stderr.write("usage: {0} mountpoint pngfile [order]\n".format(sys.argv[0]))
        sys.exit(1)
    if nargs == 4:
        order = int(sys.argv[3])
    else:
        order = 10
    path = sys.argv[1]
    pngfile = sys.argv[2]

    fs = btrfs.FileSystem(path)
    total_size, dev_offset = device_size_offsets(fs)

    walk = hilbert.curve(order)
    pos = next(walk)
    png_grid = [[0 for x in xrange(pos.width)] for y in xrange(pos.height)]
    bytes_per_pixel = total_size / pos.num_steps
    print("order {0} total_size {1} bytes per pixel {2} pixels {3}".format(
        order, total_size, bytes_per_pixel, pos.num_steps))

    block_group_cache = {}
    for dev_extent in fs.dev_extents():
        if dev_extent.vaddr in block_group_cache:
            block_group = block_group_cache[dev_extent.vaddr]
        else:
            block_group = fs.block_group(dev_extent.vaddr)
            if block_group.flags & btrfs.BLOCK_GROUP_PROFILE_MASK != 0:
                block_group_cache[dev_extent.vaddr] = fs.block_group(dev_extent.vaddr)
        used_pct = block_group.used / block_group.length

        first_byte = dev_offset[dev_extent.devid] + dev_extent.paddr
        last_byte = first_byte + dev_extent.length
        first_pixel = int(first_byte / bytes_per_pixel)
        last_pixel = int(last_byte / bytes_per_pixel)

        if pos.linear < first_pixel:
            finish_pixel(png_grid, pos)
            while pos.linear < first_pixel:
                pos = next(walk)

        if first_pixel == last_pixel:
            pct_of_pixel = dev_extent.length / bytes_per_pixel
            print("devid {0} pstart {1} pend {2} used_pct {3} type {4} in_pixel {5} {6}%".format(
                dev_extent.devid, dev_extent.paddr, dev_extent.paddr + dev_extent.length,
                int(round(used_pct * 100)),
                btrfs.utils.block_group_flags_str(block_group.flags),
                first_pixel, int(round(pct_of_pixel * 100))))
            png_grid[pos.y][pos.x] += pct_of_pixel * used_pct
        else:
            pct_of_first_pixel = \
                (bytes_per_pixel - (first_byte % bytes_per_pixel)) / bytes_per_pixel
            pct_of_last_pixel = (last_byte % bytes_per_pixel) / bytes_per_pixel
            print("devid {0} pstart {1} pend {2} used_pct {3} type {4} "
                  "first_pixel {5} {6}% last_pixel {7} {8}%".format(
                      dev_extent.devid, dev_extent.paddr, dev_extent.paddr + dev_extent.length,
                      int(round(used_pct * 100)),
                      btrfs.utils.block_group_flags_str(block_group.flags),
                      first_pixel, int(round(pct_of_first_pixel * 100)),
                      last_pixel, int(round(pct_of_last_pixel * 100))))
            png_grid[pos.y][pos.x] += pct_of_first_pixel * used_pct
            finish_pixel(png_grid, pos)
            for _ in xrange(first_pixel + 1, last_pixel):
                pos = next(walk)
                png_grid[pos.y][pos.x] = used_pct
                finish_pixel(png_grid, pos)
            pos = next(walk)
            png_grid[pos.y][pos.x] += pct_of_last_pixel * used_pct
    finish_pixel(png_grid, pos)
    png.from_array(png_grid, 'L').save(pngfile)

if __name__ == '__main__':
    main()
<commit_msg>Add some argparse<commit_after>#!/usr/bin/python

from __future__ import division, print_function, absolute_import, unicode_literals
import argparse
import btrfs
import hilbert
import png

try:
    xrange
except NameError:
    xrange = range

def device_size_offsets(fs):
    bytes_seen = 0
    offsets = {}
    for device in fs.devices():
        offsets[device.devid] = bytes_seen
        bytes_seen += device.total_bytes
    return bytes_seen, offsets

def finish_pixel(png_grid, pos, debug):
    used_pct = png_grid[pos.y][pos.x]
    if isinstance(used_pct, int) and used_pct == 0:
        return
    brightness = 16 + int(round(used_pct * (255 - 16)))
    png_grid[pos.y][pos.x] = brightness
    if debug is True:
        print("{0} value {1}".format(pos, brightness))

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--order",
        type=int,
        default=10,
        help="Hilbert curve order (default: 10)",
    )
    parser.add_argument(
        "-v",
        "--verbose",
        action="count",
        help="increase debug output verbosity",
    )
    parser.add_argument(
        "-o",
        "--output",
        dest="pngfile",
        help="Output png file name",
    )
    parser.add_argument(
        "mountpoint",
        help="Btrfs filesystem mountpoint",
    )
    return parser.parse_args()

def main():
    args = parse_args()
    order = args.order
    debug = args.verbose > 0
    path = args.mountpoint
    pngfile = args.pngfile

    fs = btrfs.FileSystem(path)
    total_size, dev_offset = device_size_offsets(fs)

    walk = hilbert.curve(order)
    pos = next(walk)
    png_grid = [[0 for x in xrange(pos.width)] for y in xrange(pos.height)]
    bytes_per_pixel = total_size / pos.num_steps
    print("order {0} total_size {1} bytes per pixel {2} pixels {3}".format(
        order, total_size, bytes_per_pixel, pos.num_steps))

    block_group_cache = {}
    for dev_extent in fs.dev_extents():
        if dev_extent.vaddr in block_group_cache:
            block_group = block_group_cache[dev_extent.vaddr]
        else:
            block_group = fs.block_group(dev_extent.vaddr)
            if block_group.flags & btrfs.BLOCK_GROUP_PROFILE_MASK != 0:
                block_group_cache[dev_extent.vaddr] = fs.block_group(dev_extent.vaddr)
        used_pct = block_group.used / block_group.length

        first_byte = dev_offset[dev_extent.devid] + dev_extent.paddr
        last_byte = first_byte + dev_extent.length
        first_pixel = int(first_byte / bytes_per_pixel)
        last_pixel = int(last_byte / bytes_per_pixel)

        if pos.linear < first_pixel:
            finish_pixel(png_grid, pos, debug)
            while pos.linear < first_pixel:
                pos = next(walk)

        if first_pixel == last_pixel:
            pct_of_pixel = dev_extent.length / bytes_per_pixel
            print("devid {0} pstart {1} pend {2} used_pct {3} type {4} in_pixel {5} {6}%".format(
                dev_extent.devid, dev_extent.paddr, dev_extent.paddr + dev_extent.length,
                int(round(used_pct * 100)),
                btrfs.utils.block_group_flags_str(block_group.flags),
                first_pixel, int(round(pct_of_pixel * 100))))
            png_grid[pos.y][pos.x] += pct_of_pixel * used_pct
        else:
            pct_of_first_pixel = \
                (bytes_per_pixel - (first_byte % bytes_per_pixel)) / bytes_per_pixel
            pct_of_last_pixel = (last_byte % bytes_per_pixel) / bytes_per_pixel
            print("devid {0} pstart {1} pend {2} used_pct {3} type {4} "
                  "first_pixel {5} {6}% last_pixel {7} {8}%".format(
                      dev_extent.devid, dev_extent.paddr, dev_extent.paddr + dev_extent.length,
                      int(round(used_pct * 100)),
                      btrfs.utils.block_group_flags_str(block_group.flags),
                      first_pixel, int(round(pct_of_first_pixel * 100)),
                      last_pixel, int(round(pct_of_last_pixel * 100))))
            png_grid[pos.y][pos.x] += pct_of_first_pixel * used_pct
            finish_pixel(png_grid, pos, debug)
            for _ in xrange(first_pixel + 1, last_pixel):
                pos = next(walk)
                png_grid[pos.y][pos.x] = used_pct
                finish_pixel(png_grid, pos, debug)
            pos = next(walk)
            png_grid[pos.y][pos.x] += pct_of_last_pixel * used_pct
    finish_pixel(png_grid, pos, debug)
    if pngfile is not None:
        png.from_array(png_grid, 'L').save(pngfile)

if __name__ == '__main__':
    main()
<|endoftext|>


<commit_before>"""
Main module
"""

import os
import func_json as fj
import display
import exceptions as exc
from datetime import date

def pDir():
    """
    gives the present working directory
    """
    return os.getcwd()

def full_path_to(fName, dire=pDir()):
    """
    joins the filename and the directory path
    """
    path = os.path.join(dire, fName)
    return path

def fileExists(fName):
    """
    Check if a file exists
    """
    if os.path.isfile(fName):
        return True
    return False

def add(json_str, sub):
    """
    Add a subject
    creates a new sub.json file
    """
    if fileExists(sub):
        raise exc.SubjectExists("Records for this subject are already present")

    with open(sub, "w") as recordFile:
        recordFile.write(json_str)

def update_json_file(tag, sub, date=date.today()):
    """
    Update a subject
    """
    if not fileExists(sub):
        raise exc.SubjectError("Subject does not exit")

    if tag not in fj.TAGS.keys():
        raise exc.UnknownTag("Tag UNKNOWN")

    with open(sub, "r") as recordFile:
        json_string = recordFile.read()

    newdata = fj.update_json_string(json_string, date, fj.TAGS[tag])
    with open(sub, "w") as recordFile:
        recordFile.write(newdata)
    return True

def display_names(ext='.json', dire=pDir()):
    """
    yields all subject names
    """
    for filename in os.listdir(dire):
        name, extension = os.path.splitext(filename)
        if extension == ext:
            yield filename

def fileDelete(fName):
    """
    Delete a file and return status
    """
    if fileExists(fName):
        os.remove(fName)
        return True
    return False

def delete(sub):
    """
    Delete a subject
    """
    if fileDelete(sub):
        return True
    return False

def reset(ext='.json', dire=pDir()):
    """
    removes all subjects
    a clean fresh start
    """
    for filename in display.display_names(ext, dire):
        path = full_path_to(filename, dire)
        os.remove(path)
<commit_msg>fixing reset<commit_after>"""
Main module
"""

import os
import func_json as fj
import display
import exceptions as exc
from datetime import date

def pDir():
    """
    gives the present working directory
    """
    return os.getcwd()

def full_path_to(fName, dire=pDir()):
    """
    joins the filename and the directory path
    """
    path = os.path.join(dire, fName)
    return path

def fileExists(fName):
    """
    Check if a file exists
    """
    if os.path.isfile(fName):
        return True
    return False

def add(json_str, sub):
    """
    Add a subject
    creates a new sub.json file
    """
    if fileExists(sub):
        raise exc.SubjectExists("Records for this subject are already present")

    with open(sub, "w") as recordFile:
        recordFile.write(json_str)

def update_json_file(tag, sub, date=date.today()):
    """
    Update a subject
    """
    if not fileExists(sub):
        raise exc.SubjectError("Subject does not exit")

    if tag not in fj.TAGS.keys():
        raise exc.UnknownTag("Tag UNKNOWN")

    with open(sub, "r") as recordFile:
        json_string = recordFile.read()

    newdata = fj.update_json_string(json_string, date, fj.TAGS[tag])
    with open(sub, "w") as recordFile:
        recordFile.write(newdata)
    return True

def display_names(ext='.json', dire=pDir()):
    """
    yields all subject names
    """
    for filename in os.listdir(dire):
        name, extension = os.path.splitext(filename)
        if extension == ext:
            yield filename

def fileDelete(fName):
    """
    Delete a file and return status
    """
    if fileExists(fName):
        os.remove(fName)
        return True
    return False

def delete(sub):
    """
    Delete a subject
    """
    if fileDelete(sub):
        return True
    return False

def reset(ext='.json', dire=pDir()):
    """
    removes all subjects
    a clean fresh start
    """
    for filename in display_names(ext, dire):
        path = full_path_to(filename, dire)
        os.remove(path)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Maximum flow (and minimum cut) algorithms on capacitated graphs.
"""

__author__ = """Loïc Séguin-C. <loicseguin@gmail.com>"""
# Copyright (C) 2010 Loïc Séguin-C. <loicseguin@gmail.com>
# All rights reserved.
# BSD license.

__all__ = ['ford_fulkerson',
           'ford_fulkerson_flow',
           'max_flow',
           'min_cut']

import networkx as nx

def _create_auxiliary_digraph(G, capacity = 'capacity'):
    """Initialize an auxiliary digraph and dict of infinite capacity
    edges for a given graph G.
    Ignore edges with capacity <= 0.
    """
    auxiliary = nx.DiGraph()
    infcapFlows = {}

    if nx.is_directed(G):
        for edge in G.edges(data = True):
            if capacity in edge[2]:
                if edge[2][capacity] > 0:
                    auxiliary.add_edge(*edge)
            else:
                auxiliary.add_edge(*edge)
                infcapFlows[(edge[0], edge[1])] = 0
    else:
        for edge in G.edges(data = True):
            if capacity in edge[2]:
                if edge[2][capacity] > 0:
                    auxiliary.add_edge(*edge)
                    auxiliary.add_edge(edge[1], edge[0], edge[2])
            else:
                auxiliary.add_edge(*edge)
                auxiliary.add_edge(edge[1], edge[0], edge[2])
                infcapFlows[(edge[0], edge[1])] = 0
                infcapFlows[(edge[1], edge[0])] = 0

    return auxiliary, infcapFlows

def _create_flow_graph(G, H, infcapFlows, capacity = 'capacity'):
    """Creates the flow graph on G corresponding to the auxiliary
    digraph H and infinite capacity edges flows infcapFlows.
    """
    if nx.is_directed(G):
        flowGraph = nx.DiGraph(G)
    else:
        flowGraph = nx.Graph(G)

    for (u, v) in flowGraph.edges():
        if H.has_edge(u, v):
            try:
                flowGraph[u][v]['flow'] = abs(G[u][v][capacity]
                                              - H[u][v][capacity])
            except KeyError: # (u, v) has infinite capacity
                try:
                    flowGraph[u][v]['flow'] = H[v][u][capacity]
                except KeyError:
                    # Infinite capacity digon in the original graph.
                    if nx.is_directed(G):
                        flowGraph[u][v]['flow'] = max(infcapFlows[(u, v)]
                                                    - infcapFlows[(v, u)], 0)
                    else:
                        flowGraph[u][v]['flow'] = abs(infcapFlows[(u, v)]
                                                    - infcapFlows[(v, u)])
        else:
            flowGraph[u][v]['flow'] = G[u][v][capacity]

    return flowGraph

def _create_flow_dict(G, H, infcapFlows, capacity = 'capacity'):
    """Creates the flow dict of dicts on G corresponding to the
    auxiliary digraph H and infinite capacity edges flows infcapFlows.
    """
    flowDict = {}

    for u in G.nodes_iter():
        if not u in flowDict:
            flowDict[u] = {}
        for v in G.neighbors(u):
            if H.has_edge(u, v):
                try:
                    flowDict[u][v] = abs(G[u][v][capacity]
                                         - H[u][v][capacity])
                except KeyError: # (u, v) has infinite capacity
                    try:
                        flowDict[u][v] = H[v][u][capacity]
                    except KeyError:
                        # Infinite capacity digon in the original graph.
                        if nx.is_directed(G):
                            flowDict[u][v] = max(infcapFlows[(u, v)]
                                                 - infcapFlows[(v, u)], 0)
                        else:
                            flowDict[u][v] = abs(infcapFlows[(u, v)]
                                                 - infcapFlows[(v, u)])
            else:
                flowDict[u][v] = G[u][v][capacity]
    return flowDict

def ford_fulkerson(G, s, t, capacity = 'capacity'):
    """Find a maximum single-commodity flow using the Ford-Fulkerson algorithm.

    This algorithm uses Edmonds-Karp-Dinitz path selection rule which
    guarantees a running time of O(nm^2) for n nodes and m edges.

    Parameters
    ----------
    G : NetworkX graph
        Edges of the graph are expected to have an attribute called
        'capacity'. If this attribute is not present, the edge is
        considered to have infinite capacity.

    s : node
        Source node for the flow.

    t : node
        Sink node for the flow.

    capacity: string
        Edges of the graph G are expected to have an attribute capacity
        that indicates how much flow the edge can support. If this
        attribute is not present, the edge is considered to have
        infinite capacity. Default value: 'capacity'.

    Returns
    -------
    flowValue : integer, float
        Value of the maximum flow, i.e., net outflow from the source.

    flowDict : dictionary
        Dictionary of dictionaries keyed by nodes such that
        flowDict[u][v] is the flow edge (u, v).

    Raises
    ------
    NetworkXError
        The algorithm does not support MultiGraph and MultiDiGraph. If
        the input graph is an instance of one of these two classes, a
        NetworkXError is raised.

    NetworkXUnbounded
        If the graph has a path of infinite capacity, the value of a
        feasible flow on the graph is unbounded above and the function
        raises a NetworkXUnbounded.

    Examples
    --------
    >>> import networkx as nx
    >>> G = nx.DiGraph()
    >>> G.add_edge('x','a', capacity = 3.0)
    >>> G.add_edge('x','b', capacity = 1.0)
    >>> G.add_edge('a','c', capacity = 3.0)
    >>> G.add_edge('b','c', capacity = 5.0)
    >>> G.add_edge('b','d', capacity = 4.0)
    >>> G.add_edge('d','e', capacity = 2.0)
    >>> G.add_edge('c','y', capacity = 2.0)
    >>> G.add_edge('e','y', capacity = 3.0)
    >>> flow,F=nx.ford_fulkerson(G, 'x', 'y')
    >>> flow
    3.0
    """
    if G.is_multigraph():
        raise nx.NetworkXError(
                'MultiGraph and MultiDiGraph not supported (yet).')

    auxiliary, infcapFlows = _create_auxiliary_digraph(G, capacity = capacity)
    flowValue = 0   # Initial feasible flow.

    # As long as there is an (s, t)-path in the auxiliary digraph, find
    # the shortest (with respect to the number of arcs) such path and
    # augment the flow on this path.
    while True:
        pathNodes = nx.bidirectional_shortest_path(auxiliary, s, t)
        if not pathNodes:
            break

        # Get the list of edges in the shortest path.
        pathEdges = []
        for i, u in enumerate(pathNodes[:-1]):
            v = pathNodes[i + 1]
            pathEdges.append((u, v, auxiliary[u][v]))

        # Find the minimum capacity of an edge in the path.
        try:
            pathCapacity = min([c[capacity]
                            for (u, v, c) in pathEdges
                            if capacity in c])
        except ValueError:
            # path of infinite capacity implies no max flow
            raise nx.NetworkXUnbounded(
                    "Infinite capacity path, flow unbounded above.")

        flowValue += pathCapacity

        # Augment the flow along the path.
        for (u, v, c) in pathEdges:
            auxEdgeAttr = auxiliary[u][v]
            if capacity in auxEdgeAttr:
                auxEdgeAttr[capacity] -= pathCapacity
                if auxEdgeAttr[capacity] == 0:
                    auxiliary.remove_edge(u, v)
            else:
                infcapFlows[(u, v)] += pathCapacity

            if auxiliary.has_edge(v, u):
                if capacity in auxiliary[v][u]:
                    auxiliary[v][u][capacity] += pathCapacity
            else:
                auxiliary.add_edge(v, u, {capacity: pathCapacity})

    flowDict = _create_flow_dict(G, auxiliary, infcapFlows,
                                 capacity = capacity)
    return flowValue, flowDict

def ford_fulkerson_flow(G, s, t, capacity = 'capacity'):
    """Return a maximum flow for a single-commodity flow problem.

    Parameters
    ----------
    G : NetworkX graph
        Edges of the graph are expected to have an attribute called
        'capacity'. If this attribute is not present, the edge is
        considered to have infinite capacity.

    s : node
        Source node for the flow.

    t : node
        Sink node for the flow.

    capacity: string
        Edges of the graph G are expected to have an attribute capacity
        that indicates how much flow the edge can support. If this
        attribute is not present, the edge is considered to have
        infinite capacity. Default value: 'capacity'.

    Returns
    -------
    flowDict : dictionary
        Dictionary of dictionaries keyed by nodes such that
        flowDict[u][v] is the flow edge (u, v).

    Raises
    ------
    NetworkXError
        The algorithm does not support MultiGraph and MultiDiGraph. If
        the input graph is an instance of one of these two classes, a
        NetworkXError is raised.

    NetworkXUnbounded
        If the graph has a path of infinite capacity, the value of a
        feasible flow on the graph is unbounded above and the function
        raises a NetworkXUnbounded.

    Examples
    --------
    >>> import networkx as nx
    >>> G = nx.DiGraph()
    >>> G.add_edge('x','a', capacity = 3.0)
    >>> G.add_edge('x','b', capacity = 1.0)
    >>> G.add_edge('a','c', capacity = 3.0)
    >>> G.add_edge('b','c', capacity = 5.0)
    >>> G.add_edge('b','d', capacity = 4.0)
    >>> G.add_edge('d','e', capacity = 2.0)
    >>> G.add_edge('c','y', capacity = 2.0)
    >>> G.add_edge('e','y', capacity = 3.0)
    >>> F=nx.ford_fulkerson_flow(G, 'x', 'y')
    >>> for u, v in G.edges_iter():
    ...     print('(%s, %s) %.2f' % (u, v, F[u][v]))
    ...
    (a, c) 2.00
    (c, y) 2.00
    (b, c) 0.00
    (b, d) 1.00
    (e, y) 1.00
    (d, e) 1.00
    (x, a) 2.00
    (x, b) 1.00
    """
    return ford_fulkerson(G, s, t, capacity = capacity)[1]

def max_flow(G, s, t, capacity = 'capacity'):
    """Find the value of a maximum single-commodity flow.

    Parameters
    ----------
    G : NetworkX graph
        Edges of the graph are expected to have an attribute called
        'capacity'. If this attribute is not present, the edge is
        considered to have infinite capacity.

    s : node
        Source node for the flow.

    t : node
        Sink node for the flow.

    capacity: string
        Edges of the graph G are expected to have an attribute capacity
        that indicates how much flow the edge can support. If this
        attribute is not present, the edge is considered to have
        infinite capacity. Default value: 'capacity'.

    Returns
    -------
    flowValue : integer, float
        Value of the maximum flow, i.e., net outflow from the source.

    Raises
    ------
    NetworkXError
        The algorithm does not support MultiGraph and MultiDiGraph. If
        the input graph is an instance of one of these two classes, a
        NetworkXError is raised.

    NetworkXUnbounded
        If the graph has a path of infinite capacity, the value of a
        feasible flow on the graph is unbounded above and the function
        raises a NetworkXUnbounded.

    Examples
    --------
    >>> import networkx as nx
    >>> G = nx.DiGraph()
    >>> G.add_edge('x','a', capacity = 3.0)
    >>> G.add_edge('x','b', capacity = 1.0)
    >>> G.add_edge('a','c', capacity = 3.0)
    >>> G.add_edge('b','c', capacity = 5.0)
    >>> G.add_edge('b','d', capacity = 4.0)
    >>> G.add_edge('d','e', capacity = 2.0)
    >>> G.add_edge('c','y', capacity = 2.0)
    >>> G.add_edge('e','y', capacity = 3.0)
    >>> flow=nx.max_flow(G, 'x', 'y')
    >>> flow
    3.0
    """
    return ford_fulkerson(G, s, t, capacity = capacity)[0]

def min_cut(G, s, t, capacity = 'capacity'):
    """Compute the value of a minimum (s, t)-cut.

    Use the max-flow min-cut theorem, i.e., the capacity of a minimum
    capacity cut is equal to the flow value of a maximum flow.

    Parameters
    ----------
    G : NetworkX graph
        Edges of the graph are expected to have an attribute called
        'capacity'. If this attribute is not present, the edge is
        considered to have infinite capacity.

    s : node
        Source node for the flow.

    t : node
        Sink node for the flow.

    capacity: string
        Edges of the graph G are expected to have an attribute capacity
        that indicates how much flow the edge can support. If this
        attribute is not present, the edge is considered to have
        infinite capacity. Default value: 'capacity'.

    Returns
    -------
    cutValue : integer, float
        Value of the minimum cut.

    Raises
    ------
    NetworkXUnbounded
        If the graph has a path of infinite capacity, all cuts have
        infinite capacity and the function raises a NetworkXError.

    Examples
    --------
    >>> import networkx as nx
    >>> G = nx.DiGraph()
    >>> G.add_edge('x','a', capacity = 3.0)
    >>> G.add_edge('x','b', capacity = 1.0)
    >>> G.add_edge('a','c', capacity = 3.0)
    >>> G.add_edge('b','c', capacity = 5.0)
    >>> G.add_edge('b','d', capacity = 4.0)
    >>> G.add_edge('d','e', capacity = 2.0)
    >>> G.add_edge('c','y', capacity = 2.0)
    >>> G.add_edge('e','y', capacity = 3.0)
    >>> nx.min_cut(G, 'x', 'y')
    3.0
    """

    try:
        return ford_fulkerson(G, s, t, capacity = capacity)[0]
    except nx.NetworkXUnbounded:
        raise nx.NetworkXUnbounded(
                "Infinite capacity path, no minimum cut.")

<commit_msg>Fixed bug in handling of infinite capacity edges with no flow.<commit_after># -*- coding: utf-8 -*-
"""
Maximum flow (and minimum cut) algorithms on capacitated graphs.
"""

__author__ = """Loïc Séguin-C. <loicseguin@gmail.com>"""
# Copyright (C) 2010 Loïc Séguin-C. <loicseguin@gmail.com>
# All rights reserved.
# BSD license.

__all__ = ['ford_fulkerson',
           'ford_fulkerson_flow',
           'max_flow',
           'min_cut']

import networkx as nx

def _create_auxiliary_digraph(G, capacity = 'capacity'):
    """Initialize an auxiliary digraph and dict of infinite capacity
    edges for a given graph G.
    Ignore edges with capacity <= 0.
    """
    auxiliary = nx.DiGraph()
    infcapFlows = {}

    if nx.is_directed(G):
        for edge in G.edges(data = True):
            if capacity in edge[2]:
                if edge[2][capacity] > 0:
                    auxiliary.add_edge(*edge)
            else:
                auxiliary.add_edge(*edge)
                infcapFlows[(edge[0], edge[1])] = 0
    else:
        for edge in G.edges(data = True):
            if capacity in edge[2]:
                if edge[2][capacity] > 0:
                    auxiliary.add_edge(*edge)
                    auxiliary.add_edge(edge[1], edge[0], edge[2])
            else:
                auxiliary.add_edge(*edge)
                auxiliary.add_edge(edge[1], edge[0], edge[2])
                infcapFlows[(edge[0], edge[1])] = 0
                infcapFlows[(edge[1], edge[0])] = 0

    return auxiliary, infcapFlows

def _create_flow_graph(G, H, infcapFlows, capacity = 'capacity'):
    """Creates the flow graph on G corresponding to the auxiliary
    digraph H and infinite capacity edges flows infcapFlows.
    """
    if nx.is_directed(G):
        flowGraph = nx.DiGraph(G)
    else:
        flowGraph = nx.Graph(G)

    for (u, v) in flowGraph.edges():
        if H.has_edge(u, v):
            try:
                flowGraph[u][v]['flow'] = abs(G[u][v][capacity]
                                              - H[u][v][capacity])
            except KeyError: # (u, v) has infinite capacity
                try:
                    flowGraph[u][v]['flow'] = H[v][u][capacity]
                except KeyError:
                    try: # Infinite capacity digon in the original graph.
                        if nx.is_directed(G):
                            flowDict[u][v] = max(infcapFlows[(u, v)]
                                             - infcapFlows[(v, u)], 0)
                        else:
                            flowDict[u][v] = abs(infcapFlows[(u, v)]
                                             - infcapFlows[(v, u)])
                    except KeyError: # Zero flow
                            flowDict[u][v] = 0
        else:
            flowGraph[u][v]['flow'] = G[u][v][capacity]

    return flowGraph

def _create_flow_dict(G, H, infcapFlows, capacity = 'capacity'):
    """Creates the flow dict of dicts on G corresponding to the
    auxiliary digraph H and infinite capacity edges flows infcapFlows.
    """
    flowDict = {}

    for u in G.nodes_iter():
        if not u in flowDict:
            flowDict[u] = {}
        for v in G.neighbors(u):
            if H.has_edge(u, v):
                try:
                    flowDict[u][v] = abs(G[u][v][capacity]
                                         - H[u][v][capacity])
                except KeyError: # (u, v) has infinite capacity
                    try:
                        flowDict[u][v] = H[v][u][capacity]
                    except KeyError:
                        try: # Infinite capacity digon in the original graph.
                            if nx.is_directed(G):
                                flowDict[u][v] = max(infcapFlows[(u, v)]
                                                 - infcapFlows[(v, u)], 0)
                            else:
                                flowDict[u][v] = abs(infcapFlows[(u, v)]
                                                 - infcapFlows[(v, u)])
                        except KeyError: # Zero flow
                            flowDict[u][v] = 0
            else:
                flowDict[u][v] = G[u][v][capacity]
    return flowDict

def ford_fulkerson(G, s, t, capacity = 'capacity'):
    """Find a maximum single-commodity flow using the Ford-Fulkerson algorithm.

    This algorithm uses Edmonds-Karp-Dinitz path selection rule which
    guarantees a running time of O(nm^2) for n nodes and m edges.

    Parameters
    ----------
    G : NetworkX graph
        Edges of the graph are expected to have an attribute called
        'capacity'. If this attribute is not present, the edge is
        considered to have infinite capacity.

    s : node
        Source node for the flow.

    t : node
        Sink node for the flow.

    capacity: string
        Edges of the graph G are expected to have an attribute capacity
        that indicates how much flow the edge can support. If this
        attribute is not present, the edge is considered to have
        infinite capacity. Default value: 'capacity'.

    Returns
    -------
    flowValue : integer, float
        Value of the maximum flow, i.e., net outflow from the source.

    flowDict : dictionary
        Dictionary of dictionaries keyed by nodes such that
        flowDict[u][v] is the flow edge (u, v).

    Raises
    ------
    NetworkXError
        The algorithm does not support MultiGraph and MultiDiGraph. If
        the input graph is an instance of one of these two classes, a
        NetworkXError is raised.

    NetworkXUnbounded
        If the graph has a path of infinite capacity, the value of a
        feasible flow on the graph is unbounded above and the function
        raises a NetworkXUnbounded.

    Examples
    --------
    >>> import networkx as nx
    >>> G = nx.DiGraph()
    >>> G.add_edge('x','a', capacity = 3.0)
    >>> G.add_edge('x','b', capacity = 1.0)
    >>> G.add_edge('a','c', capacity = 3.0)
    >>> G.add_edge('b','c', capacity = 5.0)
    >>> G.add_edge('b','d', capacity = 4.0)
    >>> G.add_edge('d','e', capacity = 2.0)
    >>> G.add_edge('c','y', capacity = 2.0)
    >>> G.add_edge('e','y', capacity = 3.0)
    >>> flow,F=nx.ford_fulkerson(G, 'x', 'y')
    >>> flow
    3.0
    """
    if G.is_multigraph():
        raise nx.NetworkXError(
                'MultiGraph and MultiDiGraph not supported (yet).')

    auxiliary, infcapFlows = _create_auxiliary_digraph(G, capacity = capacity)
    flowValue = 0   # Initial feasible flow.

    # As long as there is an (s, t)-path in the auxiliary digraph, find
    # the shortest (with respect to the number of arcs) such path and
    # augment the flow on this path.
    while True:
        pathNodes = nx.bidirectional_shortest_path(auxiliary, s, t)
        if not pathNodes:
            break

        # Get the list of edges in the shortest path.
        pathEdges = []
        for i, u in enumerate(pathNodes[:-1]):
            v = pathNodes[i + 1]
            pathEdges.append((u, v, auxiliary[u][v]))

        # Find the minimum capacity of an edge in the path.
        try:
            pathCapacity = min([c[capacity]
                            for (u, v, c) in pathEdges
                            if capacity in c])
        except ValueError:
            # path of infinite capacity implies no max flow
            raise nx.NetworkXUnbounded(
                    "Infinite capacity path, flow unbounded above.")

        flowValue += pathCapacity

        # Augment the flow along the path.
        for (u, v, c) in pathEdges:
            auxEdgeAttr = auxiliary[u][v]
            if capacity in auxEdgeAttr:
                auxEdgeAttr[capacity] -= pathCapacity
                if auxEdgeAttr[capacity] == 0:
                    auxiliary.remove_edge(u, v)
            else:
                infcapFlows[(u, v)] += pathCapacity

            if auxiliary.has_edge(v, u):
                if capacity in auxiliary[v][u]:
                    auxiliary[v][u][capacity] += pathCapacity
            else:
                auxiliary.add_edge(v, u, {capacity: pathCapacity})

    flowDict = _create_flow_dict(G, auxiliary, infcapFlows,
                                 capacity = capacity)
    return flowValue, flowDict

def ford_fulkerson_flow(G, s, t, capacity = 'capacity'):
    """Return a maximum flow for a single-commodity flow problem.

    Parameters
    ----------
    G : NetworkX graph
        Edges of the graph are expected to have an attribute called
        'capacity'. If this attribute is not present, the edge is
        considered to have infinite capacity.

    s : node
        Source node for the flow.

    t : node
        Sink node for the flow.

    capacity: string
        Edges of the graph G are expected to have an attribute capacity
        that indicates how much flow the edge can support. If this
        attribute is not present, the edge is considered to have
        infinite capacity. Default value: 'capacity'.

    Returns
    -------
    flowDict : dictionary
        Dictionary of dictionaries keyed by nodes such that
        flowDict[u][v] is the flow edge (u, v).

    Raises
    ------
    NetworkXError
        The algorithm does not support MultiGraph and MultiDiGraph. If
        the input graph is an instance of one of these two classes, a
        NetworkXError is raised.

    NetworkXUnbounded
        If the graph has a path of infinite capacity, the value of a
        feasible flow on the graph is unbounded above and the function
        raises a NetworkXUnbounded.

    Examples
    --------
    >>> import networkx as nx
    >>> G = nx.DiGraph()
    >>> G.add_edge('x','a', capacity = 3.0)
    >>> G.add_edge('x','b', capacity = 1.0)
    >>> G.add_edge('a','c', capacity = 3.0)
    >>> G.add_edge('b','c', capacity = 5.0)
    >>> G.add_edge('b','d', capacity = 4.0)
    >>> G.add_edge('d','e', capacity = 2.0)
    >>> G.add_edge('c','y', capacity = 2.0)
    >>> G.add_edge('e','y', capacity = 3.0)
    >>> F=nx.ford_fulkerson_flow(G, 'x', 'y')
    >>> for u, v in G.edges_iter():
    ...     print('(%s, %s) %.2f' % (u, v, F[u][v]))
    ...
    (a, c) 2.00
    (c, y) 2.00
    (b, c) 0.00
    (b, d) 1.00
    (e, y) 1.00
    (d, e) 1.00
    (x, a) 2.00
    (x, b) 1.00
    """
    return ford_fulkerson(G, s, t, capacity = capacity)[1]

def max_flow(G, s, t, capacity = 'capacity'):
    """Find the value of a maximum single-commodity flow.

    Parameters
    ----------
    G : NetworkX graph
        Edges of the graph are expected to have an attribute called
        'capacity'. If this attribute is not present, the edge is
        considered to have infinite capacity.

    s : node
        Source node for the flow.

    t : node
        Sink node for the flow.

    capacity: string
        Edges of the graph G are expected to have an attribute capacity
        that indicates how much flow the edge can support. If this
        attribute is not present, the edge is considered to have
        infinite capacity. Default value: 'capacity'.

    Returns
    -------
    flowValue : integer, float
        Value of the maximum flow, i.e., net outflow from the source.

    Raises
    ------
    NetworkXError
        The algorithm does not support MultiGraph and MultiDiGraph. If
        the input graph is an instance of one of these two classes, a
        NetworkXError is raised.

    NetworkXUnbounded
        If the graph has a path of infinite capacity, the value of a
        feasible flow on the graph is unbounded above and the function
        raises a NetworkXUnbounded.

    Examples
    --------
    >>> import networkx as nx
    >>> G = nx.DiGraph()
    >>> G.add_edge('x','a', capacity = 3.0)
    >>> G.add_edge('x','b', capacity = 1.0)
    >>> G.add_edge('a','c', capacity = 3.0)
    >>> G.add_edge('b','c', capacity = 5.0)
    >>> G.add_edge('b','d', capacity = 4.0)
    >>> G.add_edge('d','e', capacity = 2.0)
    >>> G.add_edge('c','y', capacity = 2.0)
    >>> G.add_edge('e','y', capacity = 3.0)
    >>> flow=nx.max_flow(G, 'x', 'y')
    >>> flow
    3.0
    """
    return ford_fulkerson(G, s, t, capacity = capacity)[0]

def min_cut(G, s, t, capacity = 'capacity'):
    """Compute the value of a minimum (s, t)-cut.

    Use the max-flow min-cut theorem, i.e., the capacity of a minimum
    capacity cut is equal to the flow value of a maximum flow.

    Parameters
    ----------
    G : NetworkX graph
        Edges of the graph are expected to have an attribute called
        'capacity'. If this attribute is not present, the edge is
        considered to have infinite capacity.

    s : node
        Source node for the flow.

    t : node
        Sink node for the flow.

    capacity: string
        Edges of the graph G are expected to have an attribute capacity
        that indicates how much flow the edge can support. If this
        attribute is not present, the edge is considered to have
        infinite capacity. Default value: 'capacity'.

    Returns
    -------
    cutValue : integer, float
        Value of the minimum cut.

    Raises
    ------
    NetworkXUnbounded
        If the graph has a path of infinite capacity, all cuts have
        infinite capacity and the function raises a NetworkXError.

    Examples
    --------
    >>> import networkx as nx
    >>> G = nx.DiGraph()
    >>> G.add_edge('x','a', capacity = 3.0)
    >>> G.add_edge('x','b', capacity = 1.0)
    >>> G.add_edge('a','c', capacity = 3.0)
    >>> G.add_edge('b','c', capacity = 5.0)
    >>> G.add_edge('b','d', capacity = 4.0)
    >>> G.add_edge('d','e', capacity = 2.0)
    >>> G.add_edge('c','y', capacity = 2.0)
    >>> G.add_edge('e','y', capacity = 3.0)
    >>> nx.min_cut(G, 'x', 'y')
    3.0
    """

    try:
        return ford_fulkerson(G, s, t, capacity = capacity)[0]
    except nx.NetworkXUnbounded:
        raise nx.NetworkXUnbounded(
                "Infinite capacity path, no minimum cut.")

<|endoftext|>


<commit_before>#!/usr/bin/env python

"""
LPU output visualization.
"""

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FFMpegWriter, FFMpegFileWriter
from matplotlib.colors import hsv_to_rgb
import networkx as nx
import simpleio as sio
from collections import OrderedDict
import os

class visualizer(object):
    """
    Visualize the output produced by LPU models.

    Example
    -------
    import neurokernel.LPU.utils.visualizer as vis
    V = vis.visualizer()
    config1 = {}
    config1['type'] = 'image'
    config1['shape'] = [32,24]
    config1['clim'] = [-0.6,0.5]
    config2 = config1.copy()
    config2['clim'] = [-0.55,-0.45]
    V.add_LPU('lamina_output.h5', 'lamina.gexf.gz','lamina')
    V.add_plot(config1, 'lamina', 'R1')
    V.add_plot(config1, 'lamina', 'L1')
    V._update_interval = 50
    V.out_filename = 'test.avi'
    V.run()
    """

    def __init__(self):
        self._xlim = [0,1]
        self._ylim = [-1,1]
        self._imlim = [-1, 1]
        self._update_interval = 50
        self._out_file = None
        self._fps = 5
        self._codec = 'h264'
        self._config = OrderedDict()
        self._rows = 0
        self._cols = 0
        self._figsize = (16,9)
        self._fontsize = 18
        self._t = 1
        self._dt = 1
        self._data = {}
        self._graph = {}
        self._maxt = None
        self._title = None

    def add_LPU(self, data_file, gexf_file=None, LPU=None, win=None):
        '''
        Add data associated with a specific LPU to a visualization.

        To add a plot containing neurons from a particular LPU,
        the LPU needs to be added to the visualization using this
        function. Not that outputs from multiple neurons can
        be visualized using the same visualizer object.

        Parameters
        ----------
        data_file: str
             Location of the h5 file generated by neurokernel
             containing the output of the LPU

        gexf_file: str
            Location of the gexf file describing the LPU.
            If not specified, it will be assumed that the h5 file
            contains input.

        LPU: str
            Name of the LPU. Will be used as identifier to add plots.

        '''
        if gexf_file:
            self._graph[LPU] = nx.read_gexf(gexf_file)
        else:
            if LPU:
                LPU = 'input_' + str(LPU)
            else:
                LPU = 'input_' + str(len(self._data))
        if not LPU:
            LPU = len(self._data)
        self._data[LPU] = np.transpose(sio.read_array(data_file))
        if win is not None:
            self._data[LPU] = self._data[LPU][:,win]
        if self._maxt:
            self._maxt = min(self._maxt, self._data[LPU].shape[1])
        else:
            self._maxt = self._data[LPU].shape[1]

    def run(self, final_frame_name=None, dpi=300):
        '''
        Starts the visualization process The final frame is saved to the specified
        file name; otherwise, the visualization is displayed in a window without being saved.
        '''

        self._initialize()
        self._t = self._update_interval+1
        for i in range(self._update_interval,self._maxt, self._update_interval):
            self.update()
        if final_frame_name is not None:
            self.f.savefig(final_frame_name, dpi=dpi)
        if self.out_filename:
            self.close()

    def _set_wrapper(self, obj, name, value):
        name = name.lower()
        func = getattr(obj, 'set_'+name, None)
        if func:
            try:
                func(value, fontsize=self._fontsize, weight='bold')
            except:
                try:
                    func(value)
                except:
                    pass

    def _initialize(self):

        # Count number of plots to create:
        num_plots = 0
        for config in self._config.itervalues():
            num_plots += len(config)

        # Set default grid of plot positions:
        if not self._rows*self._cols == num_plots:
            self._cols = int(np.ceil(np.sqrt(num_plots)))
            self._rows = int(np.ceil(num_plots/float(self._cols)))
        self.f, self.axarr = plt.subplots(self._rows, self._cols,
                                          figsize=self._figsize)

        # Remove unused subplots:
        for i in xrange(num_plots, self._rows*self._cols):
            plt.delaxes(self.axarr[np.unravel_index(i, (self._rows, self._cols))])
        cnt = 0
        self.handles = []
        self.types = []
        keywds = ['handle', 'ydata', 'fmt', 'type', 'ids', 'shape']
        if not isinstance(self.axarr, np.ndarray):
            self.axarr = np.asarray([self.axarr])
        for LPU, configs in self._config.iteritems():
            for plt_id, config in enumerate(configs):
                ind = np.unravel_index(cnt, self.axarr.shape)
                cnt+=1

                # Some plot types require specific numbers of
                # neuron ID arrays:
                if 'type' in config:
                    if config['type'] == 'quiver':
                        assert len(config['ids'])==2
                        config['type'] = 0
                    elif config['type'] == 'hsv':
                        assert len(config['ids'])==2
                        config['type'] = 1
                    elif config['type'] == 'image':
                        assert len(config['ids'])==1
                        config['type'] = 2
                    elif config['type'] == 'waveform':
                        config['type'] = 3
                    elif config['type'] == 'raster':
                        config['type'] = 4
                    elif config['type'] == 'rate':
                        config['type'] = 5
                    else:
                        raise ValueError('Plot type not supported')
                else:
                    if str(LPU).startswith('input') or not self._graph[LPU][str(config['ids'][0])]['spiking']:
                        config['type'] = 2
                    else:
                        config['type'] = 4

                if config['type'] < 3:
                    if not 'shape' in config:

                        # XXX This can cause problems when the number
                        # of neurons is not equal to
                        # np.prod(config['shape'])
                        num_neurons = len(config['ids'][0])
                        config['shape'] = [int(np.ceil(np.sqrt(num_neurons)))]
                        config['shape'].append(int(np.ceil(num_neurons/float(config['shape'][0]))))

                if config['type'] == 0:
                    config['handle'] = self.axarr[ind].quiver(\
                               np.reshape(self._data[LPU][config['ids'][0],0],config['shape']),\
                               np.reshape(self._data[LPU][config['ids'][1],0],config['shape']))
                elif config['type'] == 1:
                    X = np.reshape(self._data[LPU][config['ids'][0],0],config['shape'])
                    Y = np.reshape(self._data[LPU][config['ids'][1],0],config['shape'])
                    V = (X**2 + Y**2)**0.5
                    H = (np.arctan2(X,Y)+np.pi)/(2*np.pi)
                    S = np.ones_like(V)
                    HSV = np.dstack((H,S,V))
                    RGB = hsv_to_rgb(HSV)
                    config['handle'] = self.axarr[ind].imshow(RGB)
                elif config['type'] == 2:
                    temp = self.axarr[ind].imshow(np.reshape(\
                                self._data[LPU][config['ids'][0],0],config['shape']))
                    temp.set_clim(self._imlim)
                    temp.set_cmap(plt.cm.gist_gray)
                    config['handle'] = temp
                elif config['type'] == 3:
                    fmt = config['fmt'] if 'fmt' in config else ''
                    self.axarr[ind].set_xlim(self._xlim)
                    self.axarr[ind].set_ylim(self._ylim)
                    if len(config['ids'][0])==1:
                        config['handle'] = self.axarr[ind].plot([0], \
                                            [self._data[LPU][config['ids'][0][0],0]], fmt)[0]
                        config['ydata'] = [self._data[LPU][config['ids'][0][0],0]]
                    else:
                        config['handle'] = self.axarr[ind].plot(self._data[LPU][config['ids'][0],0])[0]

                elif config['type'] == 4:
                    config['handle'] = self.axarr[ind]
                    config['handle'].vlines(0, 0, 0.01)
                    config['handle'].set_ylim([.5, len(config['ids'][0]) + .5])
                    config['handle'].set_ylabel('Neurons',
                                                fontsize=self._fontsize-1, weight='bold')
                    config['handle'].set_xlabel('Time (s)',fontsize=self._fontsize-1, weight='bold')
                    config['handle'].set_xlim([0,len(self._data[LPU][config['ids'][0][0],:])*self._dt])
                    config['handle'].axes.set_yticks([])
                    config['handle'].axes.set_xticks([])
                for key in config.iterkeys():
                    if key not in keywds:
                        try:
                            self._set_wrapper(self.axarr[ind],key, config[key])
                        except:
                            pass
                        try:
                            self._set_wrapper(config['handle'],key, config[key])
                        except:
                            pass
                if config['type']<3:
                    config['handle'].axes.set_xticks([])
                    config['handle'].axes.set_yticks([])

            if self.suptitle is not None:
                self.f.suptitle(self._title, fontsize=self._fontsize+1, x=0.5,y=0.03, weight='bold')

        plt.tight_layout()

        if self.out_filename:
            self.writer = FFMpegFileWriter(fps=self.fps, codec=self.codec)

            # Use the output file to determine the name of the temporary frame
            # files so that two concurrently run visualizations don't clobber
            # each other's frames:
            self.writer.setup(self.f, self.out_filename, dpi=80,
                              frame_prefix=os.path.splitext(self.out_filename)[0]+'_')
            self.writer.frame_format = 'png'
            self.writer.grab_frame()
        else:
            self.f.show()

    def update(self):
        dt = self._dt
        t = self._t
        for key, configs in self._config.iteritems():
            data = self._data[key]
            for config in configs:
                if config['type'] == 3:
                    if len(config['ids'][0])==1:
                        config['ydata'].extend(np.reshape(np.double(\
                                        data[config['ids'][0], \
                                                  max(0,t-self._update_interval):t]),(-1,)))
                        config['handle'].set_xdata(dt*np.arange(0, t))
                        config['handle'].set_ydata(np.asarray(config['ydata']))
                    else:
                        config['handle'].set_ydata(\
                                        data[config['ids'][0], t])

                elif config['type']==4:
                    for j,id in enumerate(config['ids'][0]):
                        for time in np.where(data[id,max(0,t-self._update_interval):t])[0]:
                            config['handle'].vlines(float(t-time)*self._dt,j+0.75, j+1.25)
                else:
                    if config['type'] == 0:
                        shape = config['shape']
                        ids = config['ids']
                        config['handle'].U = np.reshape(data[ids[0], t],shape)
                        config['handle'].V = np.reshape(data[ids[1], t],shape)
                    elif config['type']==1:
                        shape = config['shape']
                        ids = config['ids']
                        X = np.reshape(data[ids[0], t],shape)
                        Y = np.reshape(data[ids[1], t],shape)
                        V = (X**2 + Y**2)**0.5
                        H = (np.arctan2(X,Y)+np.pi)/(2*np.pi)
                        S = np.ones_like(V)
                        HSV = np.dstack((H,S,V))
                        RGB = hsv_to_rgb(HSV)
                        config['handle'].set_data(RGB)
                    elif config['type'] == 2:
                        shape = config['shape']
                        ids = config['ids']
                        config['handle'].set_data(np.reshape(data[ids[0], t],shape))

        self.f.canvas.draw()
        if self.out_filename:
            self.writer.grab_frame()

        self._t+=self._update_interval

    def add_plot(self, config_dict, LPU=0, names=[''], shift=0):
        config = config_dict.copy()
        if not isinstance(names, list):
            names = [names]
        if not LPU in self._config:
            self._config[LPU] = []
        if 'ids' in config:
            # XXX should check whether the specified ids are within range
            self._config[LPU].append(config)
        elif str(LPU).startswith('input'):
            config['ids'] = [range(0, self._data[LPU].shape[0])]
            self._config[LPU].append(config)
        else:
            config['ids'] = {}
            for i,name in enumerate(names):
                config['ids'][i]=[]
                for id in range(len(self._graph[LPU].node)):
                    if self._graph[LPU].node[str(id)]['name'] == name:
                        config['ids'][i].append(id-shift)
            self._config[LPU].append(config)
        if not 'title' in config:
            if names[0]:
                config['title'] = "{0} - {1}".format(str(LPU),str(names[0]))
            else:
                if str(LPU).startswith('input_'):
                    config['title'] = LPU.split('_',1)[1] + ' - ' + 'Input'
                else:
                    config['title'] = str(LPU)

    def close(self):
        self.writer.finish()

    @property
    def xlim(self): return self._xlim

    @xlim.setter
    def xlim(self, value):
        self._xlim = value

    @property
    def ylim(self): return self._ylim

    @ylim.setter
    def ylim(self, value):
        self._ylim = value

    @property
    def imlim(self): return self._imlim

    @imlim.setter
    def imlim(self, value):
        self._imlim = value

    @property
    def out_filename(self): return self._out_file

    @out_filename.setter
    def out_filename(self, value):
        assert(isinstance(value, str))
        self._out_file = value

    @property
    def fps(self): return self._fps

    @fps.setter
    def fps(self, value):
        assert(isinstance(value, int))
        self._fps = value

    @property
    def codec(self): return self._codec

    @codec.setter
    def codec(self, value):
        assert(isinstance(value, str))
        self._codec = value

    @property
    def rows(self): return self._rows

    @rows.setter
    def rows(self, value):
        self._rows = value

    @property
    def cols(self): return self._cols

    @cols.setter
    def cols(self, value):
        self._cols = value

    @property
    def dt(self): return self._dt

    @dt.setter
    def dt(self, value):
        self._dt = value

    @property
    def figsize(self): return self._figsize

    @figsize.setter
    def figsize(self, value):
        assert(isinstance(value, tuple) and len(value)==2)
        self._figsize = value

    @property
    def fontsize(self): return self._fontsize

    @fontsize.setter
    def fontsize(self, value):
        self._fontsize = value

    @property
    def suptitle(self): return self._title

    @suptitle.setter
    def suptitle(self, value):
        self._title = value

    @property
    def update_interval(self): return self._update_interval

    @update_interval.setter
    def update_interval(self, value):
        self._update_interval = value
<commit_msg>Added a transpose attribute the visualizer for transposing images<commit_after>#!/usr/bin/env python

"""
LPU output visualization.
"""

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FFMpegWriter, FFMpegFileWriter
from matplotlib.colors import hsv_to_rgb
import networkx as nx
import simpleio as sio
from collections import OrderedDict
import os

class visualizer(object):
    """
    Visualize the output produced by LPU models.

    Example
    -------
    import neurokernel.LPU.utils.visualizer as vis
    V = vis.visualizer()
    config1 = {}
    config1['type'] = 'image'
    config1['shape'] = [32,24]
    config1['clim'] = [-0.6,0.5]
    config2 = config1.copy()
    config2['clim'] = [-0.55,-0.45]
    V.add_LPU('lamina_output.h5', 'lamina.gexf.gz','lamina')
    V.add_plot(config1, 'lamina', 'R1')
    V.add_plot(config1, 'lamina', 'L1')
    V._update_interval = 50
    V.out_filename = 'test.avi'
    V.run()
    """

    def __init__(self):
        self._xlim = [0,1]
        self._ylim = [-1,1]
        self._imlim = [-1, 1]
        self._update_interval = 50
        self._out_file = None
        self._fps = 5
        self._codec = 'h264'
        self._config = OrderedDict()
        self._rows = 0
        self._cols = 0
        self._figsize = (16,9)
        self._fontsize = 18
        self._t = 1
        self._dt = 1
        self._data = {}
        self._graph = {}
        self._maxt = None
        self._title = None

    def add_LPU(self, data_file, gexf_file=None, LPU=None, win=None):
        '''
        Add data associated with a specific LPU to a visualization.

        To add a plot containing neurons from a particular LPU,
        the LPU needs to be added to the visualization using this
        function. Not that outputs from multiple neurons can
        be visualized using the same visualizer object.

        Parameters
        ----------
        data_file: str
             Location of the h5 file generated by neurokernel
             containing the output of the LPU

        gexf_file: str
            Location of the gexf file describing the LPU.
            If not specified, it will be assumed that the h5 file
            contains input.

        LPU: str
            Name of the LPU. Will be used as identifier to add plots.

        '''
        if gexf_file:
            self._graph[LPU] = nx.read_gexf(gexf_file)
        else:
            if LPU:
                LPU = 'input_' + str(LPU)
            else:
                LPU = 'input_' + str(len(self._data))
        if not LPU:
            LPU = len(self._data)
        self._data[LPU] = np.transpose(sio.read_array(data_file))
        if win is not None:
            self._data[LPU] = self._data[LPU][:,win]
        if self._maxt:
            self._maxt = min(self._maxt, self._data[LPU].shape[1])
        else:
            self._maxt = self._data[LPU].shape[1]

    def run(self, final_frame_name=None, dpi=300):
        '''
        Starts the visualization process The final frame is saved to the specified
        file name; otherwise, the visualization is displayed in a window without being saved.
        '''

        self._initialize()
        self._t = self._update_interval+1
        for i in range(self._update_interval,self._maxt, self._update_interval):
            self.update()
        if final_frame_name is not None:
            self.f.savefig(final_frame_name, dpi=dpi)
        if self.out_filename:
            self.close()

    def _set_wrapper(self, obj, name, value):
        name = name.lower()
        func = getattr(obj, 'set_'+name, None)
        if func:
            try:
                func(value, fontsize=self._fontsize, weight='bold')
            except:
                try:
                    func(value)
                except:
                    pass

    def _initialize(self):

        # Count number of plots to create:
        num_plots = 0
        for config in self._config.itervalues():
            num_plots += len(config)

        # Set default grid of plot positions:
        if not self._rows*self._cols == num_plots:
            self._cols = int(np.ceil(np.sqrt(num_plots)))
            self._rows = int(np.ceil(num_plots/float(self._cols)))
        self.f, self.axarr = plt.subplots(self._rows, self._cols,
                                          figsize=self._figsize)

        # Remove unused subplots:
        for i in xrange(num_plots, self._rows*self._cols):
            plt.delaxes(self.axarr[np.unravel_index(i, (self._rows, self._cols))])
        cnt = 0
        self.handles = []
        self.types = []
        keywds = ['handle', 'ydata', 'fmt', 'type', 'ids', 'shape']
        if not isinstance(self.axarr, np.ndarray):
            self.axarr = np.asarray([self.axarr])
        for LPU, configs in self._config.iteritems():
            for plt_id, config in enumerate(configs):
                ind = np.unravel_index(cnt, self.axarr.shape)
                cnt+=1

                # Some plot types require specific numbers of
                # neuron ID arrays:
                if 'type' in config:
                    if config['type'] == 'quiver':
                        assert len(config['ids'])==2
                        config['type'] = 0
                    elif config['type'] == 'hsv':
                        assert len(config['ids'])==2
                        config['type'] = 1
                    elif config['type'] == 'image':
                        assert len(config['ids'])==1
                        config['type'] = 2
                    elif config['type'] == 'waveform':
                        config['type'] = 3
                    elif config['type'] == 'raster':
                        config['type'] = 4
                    elif config['type'] == 'rate':
                        config['type'] = 5
                    else:
                        raise ValueError('Plot type not supported')
                else:
                    if str(LPU).startswith('input') or not self._graph[LPU][str(config['ids'][0])]['spiking']:
                        config['type'] = 2
                    else:
                        config['type'] = 4

                if config['type'] < 3:
                    if not 'shape' in config:

                        # XXX This can cause problems when the number
                        # of neurons is not equal to
                        # np.prod(config['shape'])
                        num_neurons = len(config['ids'][0])
                        config['shape'] = [int(np.ceil(np.sqrt(num_neurons)))]
                        config['shape'].append(int(np.ceil(num_neurons/float(config['shape'][0]))))

                if config['type'] == 0:
                    config['handle'] = self.axarr[ind].quiver(\
                               np.reshape(self._data[LPU][config['ids'][0],0],config['shape']),\
                               np.reshape(self._data[LPU][config['ids'][1],0],config['shape']))
                elif config['type'] == 1:
                    X = np.reshape(self._data[LPU][config['ids'][0],0],config['shape'])
                    Y = np.reshape(self._data[LPU][config['ids'][1],0],config['shape'])
                    V = (X**2 + Y**2)**0.5
                    H = (np.arctan2(X,Y)+np.pi)/(2*np.pi)
                    S = np.ones_like(V)
                    HSV = np.dstack((H,S,V))
                    RGB = hsv_to_rgb(HSV)
                    config['handle'] = self.axarr[ind].imshow(RGB)
                elif config['type'] == 2:
                    if 'trans' in config:
                        if config['trans'] is True:
                            to_transpose = True
                        else:
                            to_transpose = False
                    else:
                        to_transpose = False
                        config['trans'] = False

                    if to_transpose:
                        temp = self.axarr[ind].imshow(np.transpose(np.reshape(\
                                self._data[LPU][config['ids'][0],0], config['shape'])))
                    else:
                        temp = self.axarr[ind].imshow(np.reshape(\
                                self._data[LPU][config['ids'][0],0], config['shape']))

                    temp.set_clim(self._imlim)
                    temp.set_cmap(plt.cm.gist_gray)
                    config['handle'] = temp
                elif config['type'] == 3:
                    fmt = config['fmt'] if 'fmt' in config else ''
                    self.axarr[ind].set_xlim(self._xlim)
                    self.axarr[ind].set_ylim(self._ylim)
                    if len(config['ids'][0])==1:
                        config['handle'] = self.axarr[ind].plot([0], \
                                            [self._data[LPU][config['ids'][0][0],0]], fmt)[0]
                        config['ydata'] = [self._data[LPU][config['ids'][0][0],0]]
                    else:
                        config['handle'] = self.axarr[ind].plot(self._data[LPU][config['ids'][0],0])[0]

                elif config['type'] == 4:
                    config['handle'] = self.axarr[ind]
                    config['handle'].vlines(0, 0, 0.01)
                    config['handle'].set_ylim([.5, len(config['ids'][0]) + .5])
                    config['handle'].set_ylabel('Neurons',
                                                fontsize=self._fontsize-1, weight='bold')
                    config['handle'].set_xlabel('Time (s)',fontsize=self._fontsize-1, weight='bold')
                    config['handle'].set_xlim([0,len(self._data[LPU][config['ids'][0][0],:])*self._dt])
                    config['handle'].axes.set_yticks([])
                    config['handle'].axes.set_xticks([])
                for key in config.iterkeys():
                    if key not in keywds:
                        try:
                            self._set_wrapper(self.axarr[ind],key, config[key])
                        except:
                            pass
                        try:
                            self._set_wrapper(config['handle'],key, config[key])
                        except:
                            pass
                if config['type']<3:
                    config['handle'].axes.set_xticks([])
                    config['handle'].axes.set_yticks([])

            if self.suptitle is not None:
                self.f.suptitle(self._title, fontsize=self._fontsize+1, x=0.5,y=0.03, weight='bold')

        plt.tight_layout()

        if self.out_filename:
            self.writer = FFMpegFileWriter(fps=self.fps, codec=self.codec)

            # Use the output file to determine the name of the temporary frame
            # files so that two concurrently run visualizations don't clobber
            # each other's frames:
            self.writer.setup(self.f, self.out_filename, dpi=80,
                              frame_prefix=os.path.splitext(self.out_filename)[0]+'_')
            self.writer.frame_format = 'png'
            self.writer.grab_frame()
        else:
            self.f.show()

    def update(self):
        dt = self._dt
        t = self._t
        for key, configs in self._config.iteritems():
            data = self._data[key]
            for config in configs:
                if config['type'] == 3:
                    if len(config['ids'][0])==1:
                        config['ydata'].extend(np.reshape(np.double(\
                                        data[config['ids'][0], \
                                                  max(0,t-self._update_interval):t]),(-1,)))
                        config['handle'].set_xdata(dt*np.arange(0, t))
                        config['handle'].set_ydata(np.asarray(config['ydata']))
                    else:
                        config['handle'].set_ydata(\
                                        data[config['ids'][0], t])

                elif config['type']==4:
                    for j,id in enumerate(config['ids'][0]):
                        for time in np.where(data[id,max(0,t-self._update_interval):t])[0]:
                            config['handle'].vlines(float(t-time)*self._dt,j+0.75, j+1.25)
                else:
                    if config['type'] == 0:
                        shape = config['shape']
                        ids = config['ids']
                        config['handle'].U = np.reshape(data[ids[0], t],shape)
                        config['handle'].V = np.reshape(data[ids[1], t],shape)
                    elif config['type']==1:
                        shape = config['shape']
                        ids = config['ids']
                        X = np.reshape(data[ids[0], t],shape)
                        Y = np.reshape(data[ids[1], t],shape)
                        V = (X**2 + Y**2)**0.5
                        H = (np.arctan2(X,Y)+np.pi)/(2*np.pi)
                        S = np.ones_like(V)
                        HSV = np.dstack((H,S,V))
                        RGB = hsv_to_rgb(HSV)
                        config['handle'].set_data(RGB)
                    elif config['type'] == 2:
                        ids = config['ids']
                        if config['trans']:
                            config['handle'].set_data(
                                np.transpose(np.reshape(data[ids[0], t], config['shape'
                            ])))
                        else:
                            config['handle'].set_data(
                                np.reshape(data[ids[0], t], config['shape']))

        self.f.canvas.draw()
        if self.out_filename:
            self.writer.grab_frame()

        self._t+=self._update_interval

    def add_plot(self, config_dict, LPU=0, names=[''], shift=0):
        config = config_dict.copy()
        if not isinstance(names, list):
            names = [names]
        if not LPU in self._config:
            self._config[LPU] = []
        if 'ids' in config:
            # XXX should check whether the specified ids are within range
            self._config[LPU].append(config)
        elif str(LPU).startswith('input'):
            config['ids'] = [range(0, self._data[LPU].shape[0])]
            self._config[LPU].append(config)
        else:
            config['ids'] = {}
            for i,name in enumerate(names):
                config['ids'][i]=[]
                for id in range(len(self._graph[LPU].node)):
                    if self._graph[LPU].node[str(id)]['name'] == name:
                        config['ids'][i].append(id-shift)
            self._config[LPU].append(config)
        if not 'title' in config:
            if names[0]:
                config['title'] = "{0} - {1}".format(str(LPU),str(names[0]))
            else:
                if str(LPU).startswith('input_'):
                    config['title'] = LPU.split('_',1)[1] + ' - ' + 'Input'
                else:
                    config['title'] = str(LPU)

    def close(self):
        self.writer.finish()

    @property
    def xlim(self): return self._xlim

    @xlim.setter
    def xlim(self, value):
        self._xlim = value

    @property
    def ylim(self): return self._ylim

    @ylim.setter
    def ylim(self, value):
        self._ylim = value

    @property
    def imlim(self): return self._imlim

    @imlim.setter
    def imlim(self, value):
        self._imlim = value

    @property
    def out_filename(self): return self._out_file

    @out_filename.setter
    def out_filename(self, value):
        assert(isinstance(value, str))
        self._out_file = value

    @property
    def fps(self): return self._fps

    @fps.setter
    def fps(self, value):
        assert(isinstance(value, int))
        self._fps = value

    @property
    def codec(self): return self._codec

    @codec.setter
    def codec(self, value):
        assert(isinstance(value, str))
        self._codec = value

    @property
    def rows(self): return self._rows

    @rows.setter
    def rows(self, value):
        self._rows = value

    @property
    def cols(self): return self._cols

    @cols.setter
    def cols(self, value):
        self._cols = value

    @property
    def dt(self): return self._dt

    @dt.setter
    def dt(self, value):
        self._dt = value

    @property
    def figsize(self): return self._figsize

    @figsize.setter
    def figsize(self, value):
        assert(isinstance(value, tuple) and len(value)==2)
        self._figsize = value

    @property
    def fontsize(self): return self._fontsize

    @fontsize.setter
    def fontsize(self, value):
        self._fontsize = value

    @property
    def suptitle(self): return self._title

    @suptitle.setter
    def suptitle(self, value):
        self._title = value

    @property
    def update_interval(self): return self._update_interval

    @update_interval.setter
    def update_interval(self, value):
        self._update_interval = value
<|endoftext|>


<commit_before>#!/usr/bin/python
import os
import subprocess
from string import uppercase
import sys

from textutil import asblocks, sanitize

DEBUG=False

def which(x):
    for p in os.environ['PATH'].split(':'):
        path = os.path.join(p, x)
        if os.path.exists(path):
            return path
    return None

def firstl(f, it, default):
    for x in it:
        t = x() if callable(x) else x
        if f(t):
            return t
    t = default() if callable(default) else default
    return t

mod_path = os.path.dirname(sys.modules[__name__].__file__)
if mod_path == '': mod_path = '.'

def local_or_system(toolname):
    return firstl(os.path.exists,
        [os.path.join(mod_path, '..', '..', '..', '..', '..', '..',
                      'parts', 'poppler', 'bin', toolname),
         os.path.join(mod_path, toolname)], lambda: which(toolname))

PDFTOTEXT=local_or_system('pdftotext')
PDFINFO=local_or_system('pdfinfo')

if DEBUG:
    print "pdftotext from %s" % PDFTOTEXT
    print "pdfinfo from %s" % PDFINFO

def capture_output(args):
    return subprocess.Popen(args, stdout=subprocess.PIPE).stdout.readlines()

def pdftotext(filename, first=None, last=None, x=0, y=0, w=0, h=0):
    params = []
    if first is not None:
        params.extend(['-f %s' % first])
    if last is not None:
        params.extend(['-l %s' % last])
    args = ("%s %s -x %d -y %d -W %d -H %d %s -" % (PDFTOTEXT,
            ' '.join(params), x, y, w, h, filename)).split()
    output = capture_output(args)
    return sanitize([unicode(l,'utf8') for l in output])

def camel_to_lower_case(s):
    t = ''.join('_' if c == ' ' else ('_'+c.lower() if c in uppercase else c) for c in s)
    if t[0] == '_': return t[1:]
    return t

def pdfinfo(filename):
    """ Example output of pdfinfo:
Creator:        Adobe InDesign CS2 (4.0.2)
Producer:       Adobe PDF Library 7.0
CreationDate:   Sun Jul  4 13:09:27 2010
ModDate:        Sun Jul  4 13:09:30 2010
Tagged:         no
Pages:          2
Encrypted:      no
Page size:      481.89 x 680.315 pts
File size:      118581 bytes
Optimized:      yes
PDF version:    1.4
    """
    class PdfInfo(object):
        def __str__(self):
            return 'PdfInfo: %s: %s, %s, %s' % (
                self.filename, self.pages, self.file_size, self.mod_date)
        __repr__ = __str__
    pdfinfo = PdfInfo()
    pdfinfo.filename = filename
    numbers = set('pages file_size'.split())
    def convert(k, v):
        if k in numbers: return int(v.split()[0])
        return v
    data = [(k, convert(k, v.strip())) for k, v in
            ((camel_to_lower_case(k), v.strip()) for k,v in
            (l.split(':',1) for l in capture_output([PDFINFO, filename])))]
    pdfinfo.__dict__.update(data)
    return pdfinfo

def isempty(filename, x=0, y=0, W=0, H=0):
    return len(asblocks(filename, x, y, W, H)) == 0

def num_blocks(filename, x=0, y=0, W=0, H=0):
    return len(asblocks(filename, x=x,y=y,W=W,H=H))

if __name__ == '__main__':
    # Test code - not used
    filename = '538.pdf'
    fulltext = asblocks(filename)
    texts = [pdftotext(filename, x=x,W=1000) for x in xrange(100)]
    checksums = [checksum(filename, x=x, W=1000) for x in xrange(100)]
    for i in xrange(len(checksums)-1):
        if checksums[i] != checksums[i+1]:
            print "change at %s" % i

<commit_msg>pdftools: add test of version for pdftotext (not executed yet)<commit_after>#!/usr/bin/python
import os
import subprocess
from string import uppercase
import sys

from textutil import asblocks, sanitize

DEBUG=False

def which(x):
    for p in os.environ['PATH'].split(':'):
        path = os.path.join(p, x)
        if os.path.exists(path):
            return path
    return None

def firstl(f, it, default):
    for x in it:
        t = x() if callable(x) else x
        if f(t):
            return t
    t = default() if callable(default) else default
    return t

mod_path = os.path.dirname(sys.modules[__name__].__file__)
if mod_path == '': mod_path = '.'

def local_or_system(toolname):
    return firstl(os.path.exists,
        [os.path.join(mod_path, '..', '..', '..', '..', '..', '..',
                      'parts', 'poppler', 'bin', toolname),
         os.path.join(mod_path, toolname)], lambda: which(toolname))

PDFTOTEXT=local_or_system('pdftotext')
PDFINFO=local_or_system('pdfinfo')

def pdftotext_version():
    p = subprocess.Popen(executable=PDFTOTEXT, args=[PDFTOTEXT, '-v'], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
    major, minor, patchlevel = p.stderr.readlines()[0].split()[-1].split('.')
    p.kill()
    return major, minor, patchlevel

PDFTOTEXT_VERSION = pdftotext_version()

if DEBUG:
    print "pdftotext from %s, version %s" % (PDFTOTEXT, str(PDFTOTEXT_VERSION))
    print "pdfinfo from %s" % PDFINFO

def pdftotext_version_pass():
    V = PDFTOTEXT_VERSION
    return V.major > 1 or (V.major == 1 and V.minor >= 4)

def capture_output(args):
    return subprocess.Popen(args, stdout=subprocess.PIPE).stdout.readlines()

def pdftotext(filename, first=None, last=None, x=0, y=0, w=0, h=0):
    params = []
    if first is not None:
        params.extend(['-f %s' % first])
    if last is not None:
        params.extend(['-l %s' % last])
    args = ("%s %s -x %d -y %d -W %d -H %d %s -" % (PDFTOTEXT,
            ' '.join(params), x, y, w, h, filename)).split()
    output = capture_output(args)
    return sanitize([unicode(l,'utf8') for l in output])

def camel_to_lower_case(s):
    t = ''.join('_' if c == ' ' else ('_'+c.lower() if c in uppercase else c) for c in s)
    if t[0] == '_': return t[1:]
    return t

def pdfinfo(filename):
    """ Example output of pdfinfo:
Creator:        Adobe InDesign CS2 (4.0.2)
Producer:       Adobe PDF Library 7.0
CreationDate:   Sun Jul  4 13:09:27 2010
ModDate:        Sun Jul  4 13:09:30 2010
Tagged:         no
Pages:          2
Encrypted:      no
Page size:      481.89 x 680.315 pts
File size:      118581 bytes
Optimized:      yes
PDF version:    1.4
    """
    class PdfInfo(object):
        def __str__(self):
            return 'PdfInfo: %s: %s, %s, %s' % (
                self.filename, self.pages, self.file_size, self.mod_date)
        __repr__ = __str__
    pdfinfo = PdfInfo()
    pdfinfo.filename = filename
    numbers = set('pages file_size'.split())
    def convert(k, v):
        if k in numbers: return int(v.split()[0])
        return v
    data = [(k, convert(k, v.strip())) for k, v in
            ((camel_to_lower_case(k), v.strip()) for k,v in
            (l.split(':',1) for l in capture_output([PDFINFO, filename])))]
    pdfinfo.__dict__.update(data)
    return pdfinfo

def isempty(filename, x=0, y=0, W=0, H=0):
    return len(asblocks(filename, x, y, W, H)) == 0

def num_blocks(filename, x=0, y=0, W=0, H=0):
    return len(asblocks(filename, x=x,y=y,W=W,H=H))

if __name__ == '__main__':
    # Test code - not used
    filename = '538.pdf'
    fulltext = asblocks(filename)
    texts = [pdftotext(filename, x=x,W=1000) for x in xrange(100)]
    checksums = [checksum(filename, x=x, W=1000) for x in xrange(100)]
    for i in xrange(len(checksums)-1):
        if checksums[i] != checksums[i+1]:
            print "change at %s" % i

<|endoftext|>


<commit_before>class ApplianceSet(object):

    def __init__(self,instances):
        '''
        Initializes an appliance set given a list of instances.
        '''
        self.instances = instances
        self.make_dataframe()

    def add_instances(self,instances):
        '''
        Adds the list of appliances to the appliance set.
        '''
        self.instances += instances
        self.add_to_dataframe(instances)

    def add_to_dataframe(self,instances):
        '''
        Adds a new list of appliances to the dataframe.
        '''
        pass

    def get_dataframe(self):
        '''
        Returns the dataframe object representing the dataset.
        '''
        return self.df

    def make_dataframe(self):
        '''
        Makes a new dataframe of the appliance instances. Throws an exception if
        if the appliance instances have traces that don't align.
        '''
        pass

    def set_instances(self,instances):
        '''
        Replaces the old instances with the new list. Makes a new dataframe
        using those instances
        '''
        self.instances = instances
        self.make_dataframe()

    def top_k(self):
        '''
        Get top k energy-consuming appliances
        '''
        pass
<commit_msg>update appliance set methods<commit_after>import pandas as pd

class ApplianceSet(object):

    def __init__(self,instances):
        '''
        Initializes an appliance set given a list of instances.
        '''
        self.instances = instances
        self.make_dataframe()

    def add_instances(self,instances):
        '''
        Adds the list of appliances to the appliance set.
        '''
        self.instances += instances
        self.add_to_dataframe(instances)

    def add_to_dataframe(self,instances):
        '''
        Adds a new list of appliances to the dataframe.
        '''
        pass

    def get_dataframe(self):
        '''
        Returns the dataframe object representing the dataset.
        '''
        return self.df

    def make_dataframe(self):
        '''
        Makes a new dataframe of the appliance instances. Throws an exception if
        if the appliance instances have traces that don't align.
        '''
        # TODO concatenate all traces into a single trace
        # TODO use real column_name
        series_dict = {"column_name":instance.traces[0].series for instance in instances}
        self.df = pd.Dataframe.from_dict(series_dict)

    def set_instances(self,instances):
        '''
        Replaces the old instances with the new list. Makes a new dataframe
        using those instances
        '''
        self.instances = instances
        self.make_dataframe()

    def top_k(self):
        '''
        Get top k energy-consuming appliances
        '''
        pass
<|endoftext|>