<commit_before>#------------------------------------------------------------------------------
# Copyright (c) 2005, Enthought, Inc.
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in enthought/LICENSE.txt and may be redistributed only
# under the conditions described in the aforementioned license.  The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
# Thanks for using Enthought open source!
#
# Author: Enthought, Inc.
# Description: <Enthought pyface package component>
#------------------------------------------------------------------------------
"""This module provides a light manager that may be used to change the
lighting of a VTK scene.

This module is largely ported from MayaVi's Lights.py but the
implementation is considerably different.

"""
# Author: Prabhu Ramachandran <prabhu_r@users.sf.net>
# Copyright (c) 2005, Enthought, Inc.
# License: BSD Style.

import sys
from math import sin, cos, atan2, pi

from enthought.traits.api import HasTraits, Range, Delegate, true, false, \
                                 Instance, Trait, List
from enthought.traits.ui.api import View, Group, Handler, ListEditor, Item
from enthought.tvtk.api import tvtk
from enthought.tvtk.tvtk_base import vtk_color_trait, TraitRevPrefixMap
from enthought.persistence import state_pickler

######################################################################
# `LightGlyph` class.
######################################################################
class LightGlyph(HasTraits):
    """Manages a glyph that represents a Light source in the scene.
    This gives the user an *idea* of where the light source is placed
    while configuring the lights.
    """
    # The version of this class.  Used for persistence.
    __version__ = 0

    def __init__(self):
        self.el = 0.0
        self.az = 0.0

        # Create an arrow.
        arrow = tvtk.ArrowSource()

        # Transform it suitably so it is oriented correctly.
        t = tvtk.Transform()
        tf = tvtk.TransformFilter()
        tf.transform = t
        t.rotate_y(90.0)
        t.translate((-2, 0, 0))
        tf.input = arrow.output

        mapper = tvtk.PolyDataMapper()
        mapper.input = tf.output

        self.actor = actor = tvtk.Follower()
        actor.mapper = mapper
        prop = actor.property
        prop.color = 0, 1, 1
        prop.ambient = 0.5
        prop.diffuse = 0.5

    def __get_pure_state__(self):
        d = self.__dict__.copy()
        for name in ['__sync_trait__',  '__traits_listener__']:
            d.pop(name, None)
        return d

    def __getstate__(self):
        return state_pickler.dumps(self)

    def __setstate__(self, str_state):
        self.__init__()
        state_pickler.set_state(self, state_pickler.loads_state(str_state))

    #################################################################
    # `LightGlyph` interface.
    #################################################################
    def add(self, ren, bounds):
        """Adds the actors to the given renderer (`ren`).  The actors
        are scaled as per the given bounds."""
        scale = max(bounds[1]-bounds[0], bounds[3] - bounds[2],
                    bounds[5]-bounds[4])*0.75
        self.actor.scale = scale, scale, scale
        ren.add_actor(self.actor)
        cam = ren.active_camera
        self.actor.camera = cam

    def remove(self, ren):
        """Removes the actors of the glyph from the given renderer
        (`ren`)."""
        ren.remove_actor(self.actor)

    def move_to(self, elevation=None, azimuth = None):
        """Move the glyphs to the specified elevation and azimuth."""
        self.actor.rotate_x(-self.el)
        self.actor.rotate_y(-self.az)
        if elevation != None:
            self.el = elevation
        if azimuth != None:
            self.az = azimuth
        self.actor.rotate_y(self.az)
        self.actor.rotate_x(self.el)

    def show(self):
        """Show the glyphs on screen."""
        self.actor.visibility = 1

    def hide(self):
        """Hide the glyphs on screen."""
        self.actor.visibility = 0

    def set_color(self, clr):
        """Change the glyphs color."""
        self.actor.property.color = clr

######################################################################
# `CameraLight` class.
######################################################################
class CameraLight(HasTraits):

    """This class manages a tvtk.Light object and a LightGlyph object."""

    # The version of this class.  Used for persistence.
    __version__ = 0

    #################################################################
    # Traits.
    #################################################################
    elevation = Range(-90.0, 90.0, 0.0,
                      desc="the elevation of the light")
    azimuth = Range(-180.0, 180.0, 0.0,
                    desc="the aziumthal angle of the light")
    activate = Trait(False, false,
                     desc="specifies if the light is enabled or not")
    source = Instance(tvtk.Light, ())

    # FIXME: Traits Delegation does not work correctly and changes to
    # this object are not reflected in the delegate nicely.
    #color = Delegate('source', modify=True)
    #intensity = Delegate('source', modify=True)

    # For now we mirror these traits from the source.
    intensity = Range(0.0, 1.0, 1.0,
                      desc="the intensity of the light")
    color = vtk_color_trait((1.0, 1.0, 1.0))
    color.desc = "the color of the light"

    default_view = View(Item(name='activate'), Item(name='elevation'),
                        Item(name='azimuth'), Item(name='intensity'),
                        Item(name='color'))

    #################################################################
    # `object` interface.
    #################################################################
    def __init__(self, renwin, **traits):
        self.glyph = LightGlyph()
        super(CameraLight, self).__init__(**traits)
        self.source.light_type = 'camera_light'
        self._intensity_changed(self.intensity)
        self._activate_changed(self.activate)
        self._color_changed(self.color)

        renwin.renderer.add_light(self.source)
        self.on_trait_change(renwin.render)

    def __get_pure_state__(self):
        d = self.__dict__.copy()
        for name in ['__sync_trait__', '__traits_listener__']:
            d.pop(name, None)
        return d

    def __getstate__(self):
        return state_pickler.dumps(self)

    def __setstate__(self, str_state):
        #self.__init__()
        state_pickler.set_state(self, state_pickler.loads_state(str_state))

    #################################################################
    # `LightGlyph` interface.
    #################################################################
    def close(self, renwin):
        """Remove the light source and the glyph from the
        renderwindow.  This is usually to be called when the Light is
        removed from the scene."""
        ren = renwin.renderer
        self.on_trait_change(renwin.render, remove=True)
        ren.remove_light(self.source)
        self.remove_glyph(ren)

    def add_glyph(self, ren, bounds):
        """Add the light glyph to the passed renderer ('ren').  Scale
        the actors using the bounds (`bounds`) provided."""
        self.glyph.add(ren, bounds)

    def remove_glyph(self, ren):
        """Remove the light glyph from the passed renderer."""
        self.glyph.remove(ren)

    def move_to(self, elevation, azimuth):
        """Move the light to the specified elevation and azimuthal
        angles (in degrees)."""
        self.elevation = elevation
        self.azimuth = azimuth

    #################################################################
    # Trait handlers.
    #################################################################
    def _activate_changed(self, val):
        if val:
            self.source.switch = 1
            self.glyph.show()
        else:
            self.source.switch = 0
            self.glyph.hide()

    def _intensity_changed(self, val):
        self.source.intensity = val

    def _color_changed(self, val):
        self.source.color = val
        self.glyph.set_color(val)

    def _elevation_changed(self, val):
        self.glyph.move_to(val, self.azimuth)
        self.source.position = self._to_pos(val, self.azimuth)

    def _azimuth_changed(self, val):
        self.glyph.move_to(self.elevation, val)
        self.source.position = self._to_pos(self.elevation, val)

    #################################################################
    # Non-public interface.
    #################################################################
    def _to_pos(self, elevation, azimuth):
        """Convert the given elevation and azimuth angles (degrees) to
        a position vector."""
        theta = azimuth*pi/180.0
        phi = (90.0-elevation)*pi/180.0
        x = sin(theta)*sin(phi)
        y = cos(phi)
        z = cos(theta)*sin(phi)
        return x, y, z

    def _from_pos(self, x, y, z):
        """Given the position vector, return an elevation and azimuth
        angle (in degrees)."""
        theta = atan2(x, z)
        phi = atan2(sqrt(x**2+z**2), y)
        az = theta*180.0/pi
        el = 90.0 - phi*180.0/pi
        return el, az

######################################################################
# `CloseHandler` class.
######################################################################
class CloseHandler(Handler):
    """This class cleans up after the UI for the Light Manager is
    closed."""
    def close(self, info, is_ok):
        """This method is invoked when the user closes the UI."""
        light_manager = info.object
        light_manager.on_ui_close()
        return True

######################################################################
# `LightManager` class.
######################################################################
class LightManager(HasTraits):

    """This class manages all the lights and presents a GUI for the
    lights.

    There are two default lighting modes possible (specified via the
    `light_mode` trait).  The 'vtk' mode uses the default lighting
    mode which is basically a single headlight.  The 'raymond' mode
    creates three lights to give better overall illumination (thanks
    to Raymond Maple).
    """

    # The version of this class.  Used for persistence.
    __version__ = 0

    #################################################################
    # Traits.
    #################################################################

    # Valid modes currently are 'vtk' and 'raymond'.  'vtk' is the
    # default VTK light setup with only one light on in headlight
    # mode. 'raymond' is Raymond Maple's default configuration with
    # three active lights.  Please note that this only specifies a
    # default mode used to initialize the lights to a sane default.
    # The user can always change the light configuration via the GUI
    # such that the mode is neither 'vtk' nor 'raymond'.
    light_mode = Trait('raymond', TraitRevPrefixMap({'raymond':1,
                                                     'vtk':2}),
                       desc='specifies a default lighting mode')

    # Specify the number of lights.  If new lights are added they are
    # by default turned off.  Similarly if the number of lights are
    # reduced the last lights alone are removed.
    number_of_lights = Range(3, 8, 4, desc='specifies the number of lights')

    # The list of added lights.
    lights = List(CameraLight, editor=ListEditor(use_notebook=True,
                                                 page_name='Light'),
                  record=True)

    view = View( Group( 'light_mode',
                        'number_of_lights', ),
                Item('lights', style='custom', show_label=False),
                resizable=True,
                buttons=['OK'])

    #################################################################
    # `object` interface.
    #################################################################
    def __init__(self, renwin, **traits):
        super(LightManager, self).__init__(**traits)

        self.ui = None
        self.renwin = renwin
        ren = self.renwin.renderer

        # VTK requires that there always be atleast one light turned
        # on (with SwitchOn).  The renderer already has one headlight
        # already enabled.  We merely set the intensity of this light
        # to zero and never change that.  Note that if this light is
        # turned off, and no other lights are "on", then VTK will
        # create a new light!
        ren.lights[0].intensity = 0.0

        # Create the lights.
        self.lights = []
        for i in range(self.number_of_lights):
            light = CameraLight(self.renwin)
            self.lights.append(light)

        # Setup the light mode.
        self._light_mode_changed(self.light_mode)

    def __get_pure_state__(self):
        d = self.__dict__.copy()
        for name in ['__sync_trait__', 'renwin', 'ui',
                     '__traits_listener__']:
            d.pop(name, None)
        return d

    def __set_pure_state__(self, state):
        first = ['light_mode', 'number_of_lights']
        state_pickler.set_state(self, state, first=first, last=['lights'])

    def __getstate__(self):
        return state_pickler.dumps(self)

    def __setstate__(self, str_state):
        # This method is unnecessary since this object will almost
        # never be pickled by itself and only via the scene, therefore
        # __init__ will be called when the scene is constructed.
        # However, setstate is defined just for completeness.
        #self.__init__()
        state = state_pickler.loads_state(str_state)
        state_pickler.update_state(state)
        self.__set_pure_state__(state)

    #################################################################
    # `LightManager` interface.
    #################################################################
    def configure(self):
        """Pops up the GUI control widget."""
        if self.ui is None:
            self._show_glyphs()
            view = View(Group(Item(name='light_mode'),
                              Item(name='number_of_lights'),
                              label='LightManager'),
                        Group(Item(name='lights', style='custom'),
                              label='Lights',
                              selected=True, show_labels=False),
                        resizable=True,
                        buttons=['OK'],
                        handler=CloseHandler())
            self.ui = view.ui(self)
        else:
            try:
                self.ui.control.Raise()
            except AttributeError:
                pass

    def on_ui_close(self):
        """This method removes the glyphs used to show the lights on
        screen when the GUI dialog is closed.  This is typically only
        called from the CloseHandler."""
        ren = self.renwin.renderer
        for l in self.lights:
            l.remove_glyph(ren)
        self.ui = None

    #################################################################
    # Non-public interface.
    #################################################################
    def _show_glyphs(self):
        """Shows the glyphs when the light config UI is shown."""
        rw = self.renwin
        ren = rw.renderer
        rw.reset_zoom()
        bounds = ren.compute_visible_prop_bounds()
        for light in self.lights:
            light.add_glyph(ren, bounds)
        rw.render()

    def _light_mode_changed(self, mode):
        lights = self.lights
        if mode == 'raymond':
            for i in range(len(lights)):
                if i < 3:
                    lights[i].activate = True
                    lights[i].intensity = 1.0
                    lights[i].color = 1.0, 1.0, 1.0
                else:
                    lights[i].activate = False
                    lights[i].move_to(0.0, 0.0)
                    lights[i].intensity = 1.0
                    lights[i].color = 1.0, 1.0, 1.0

            lights[0].move_to(45.0, 45.0)
            lights[1].move_to(-30.0,-60.0)
            lights[1].intensity = 0.6
            lights[2].move_to(-30.0, 60.0)
            lights[2].intensity = 0.5
        else:
            for i in range(len(lights)):
                lights[i].move_to(0.0, 0.0)
                lights[i].intensity = 1.0
                lights[i].color = 1.0, 1.0, 1.0
                if i == 0 :
                    lights[i].activate  = True
                else:
                    lights[i].activate = False

    def _number_of_lights_changed(self, old, new):
        ren = self.renwin.renderer
        changed = False
        if new == old:
            return
        elif new > old:
            for i in range(new - old):
                light = CameraLight(self.renwin)
                self.lights.append(light)
            changed = True
        elif new < old:
            for i in range(old - new):
                light = self.lights.pop()
                light.close(self.renwin)
            changed = True

<commit_msg>BUG: Fix trivial bug in tvtk light_manager.py<commit_after>#------------------------------------------------------------------------------
# Copyright (c) 2005, Enthought, Inc.
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in enthought/LICENSE.txt and may be redistributed only
# under the conditions described in the aforementioned license.  The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
# Thanks for using Enthought open source!
#
# Author: Enthought, Inc.
# Description: <Enthought pyface package component>
#------------------------------------------------------------------------------
"""This module provides a light manager that may be used to change the
lighting of a VTK scene.

This module is largely ported from MayaVi's Lights.py but the
implementation is considerably different.

"""
# Author: Prabhu Ramachandran <prabhu_r@users.sf.net>
# Copyright (c) 2005, Enthought, Inc.
# License: BSD Style.

import sys
from math import sin, cos, atan2, pi, sqrt

from enthought.traits.api import HasTraits, Range, Delegate, true, false, \
                                 Instance, Trait, List
from enthought.traits.ui.api import View, Group, Handler, ListEditor, Item
from enthought.tvtk.api import tvtk
from enthought.tvtk.tvtk_base import vtk_color_trait, TraitRevPrefixMap
from enthought.persistence import state_pickler

######################################################################
# `LightGlyph` class.
######################################################################
class LightGlyph(HasTraits):
    """Manages a glyph that represents a Light source in the scene.
    This gives the user an *idea* of where the light source is placed
    while configuring the lights.
    """
    # The version of this class.  Used for persistence.
    __version__ = 0

    def __init__(self):
        self.el = 0.0
        self.az = 0.0

        # Create an arrow.
        arrow = tvtk.ArrowSource()

        # Transform it suitably so it is oriented correctly.
        t = tvtk.Transform()
        tf = tvtk.TransformFilter()
        tf.transform = t
        t.rotate_y(90.0)
        t.translate((-2, 0, 0))
        tf.input = arrow.output

        mapper = tvtk.PolyDataMapper()
        mapper.input = tf.output

        self.actor = actor = tvtk.Follower()
        actor.mapper = mapper
        prop = actor.property
        prop.color = 0, 1, 1
        prop.ambient = 0.5
        prop.diffuse = 0.5

    def __get_pure_state__(self):
        d = self.__dict__.copy()
        for name in ['__sync_trait__',  '__traits_listener__']:
            d.pop(name, None)
        return d

    def __getstate__(self):
        return state_pickler.dumps(self)

    def __setstate__(self, str_state):
        self.__init__()
        state_pickler.set_state(self, state_pickler.loads_state(str_state))

    #################################################################
    # `LightGlyph` interface.
    #################################################################
    def add(self, ren, bounds):
        """Adds the actors to the given renderer (`ren`).  The actors
        are scaled as per the given bounds."""
        scale = max(bounds[1]-bounds[0], bounds[3] - bounds[2],
                    bounds[5]-bounds[4])*0.75
        self.actor.scale = scale, scale, scale
        ren.add_actor(self.actor)
        cam = ren.active_camera
        self.actor.camera = cam

    def remove(self, ren):
        """Removes the actors of the glyph from the given renderer
        (`ren`)."""
        ren.remove_actor(self.actor)

    def move_to(self, elevation=None, azimuth = None):
        """Move the glyphs to the specified elevation and azimuth."""
        self.actor.rotate_x(-self.el)
        self.actor.rotate_y(-self.az)
        if elevation != None:
            self.el = elevation
        if azimuth != None:
            self.az = azimuth
        self.actor.rotate_y(self.az)
        self.actor.rotate_x(self.el)

    def show(self):
        """Show the glyphs on screen."""
        self.actor.visibility = 1

    def hide(self):
        """Hide the glyphs on screen."""
        self.actor.visibility = 0

    def set_color(self, clr):
        """Change the glyphs color."""
        self.actor.property.color = clr

######################################################################
# `CameraLight` class.
######################################################################
class CameraLight(HasTraits):

    """This class manages a tvtk.Light object and a LightGlyph object."""

    # The version of this class.  Used for persistence.
    __version__ = 0

    #################################################################
    # Traits.
    #################################################################
    elevation = Range(-90.0, 90.0, 0.0,
                      desc="the elevation of the light")
    azimuth = Range(-180.0, 180.0, 0.0,
                    desc="the aziumthal angle of the light")
    activate = Trait(False, false,
                     desc="specifies if the light is enabled or not")
    source = Instance(tvtk.Light, ())

    # FIXME: Traits Delegation does not work correctly and changes to
    # this object are not reflected in the delegate nicely.
    #color = Delegate('source', modify=True)
    #intensity = Delegate('source', modify=True)

    # For now we mirror these traits from the source.
    intensity = Range(0.0, 1.0, 1.0,
                      desc="the intensity of the light")
    color = vtk_color_trait((1.0, 1.0, 1.0))
    color.desc = "the color of the light"

    default_view = View(Item(name='activate'), Item(name='elevation'),
                        Item(name='azimuth'), Item(name='intensity'),
                        Item(name='color'))

    #################################################################
    # `object` interface.
    #################################################################
    def __init__(self, renwin, **traits):
        self.glyph = LightGlyph()
        super(CameraLight, self).__init__(**traits)
        self.source.light_type = 'camera_light'
        self._intensity_changed(self.intensity)
        self._activate_changed(self.activate)
        self._color_changed(self.color)

        renwin.renderer.add_light(self.source)
        self.on_trait_change(renwin.render)

    def __get_pure_state__(self):
        d = self.__dict__.copy()
        for name in ['__sync_trait__', '__traits_listener__']:
            d.pop(name, None)
        return d

    def __getstate__(self):
        return state_pickler.dumps(self)

    def __setstate__(self, str_state):
        #self.__init__()
        state_pickler.set_state(self, state_pickler.loads_state(str_state))

    #################################################################
    # `LightGlyph` interface.
    #################################################################
    def close(self, renwin):
        """Remove the light source and the glyph from the
        renderwindow.  This is usually to be called when the Light is
        removed from the scene."""
        ren = renwin.renderer
        self.on_trait_change(renwin.render, remove=True)
        ren.remove_light(self.source)
        self.remove_glyph(ren)

    def add_glyph(self, ren, bounds):
        """Add the light glyph to the passed renderer ('ren').  Scale
        the actors using the bounds (`bounds`) provided."""
        self.glyph.add(ren, bounds)

    def remove_glyph(self, ren):
        """Remove the light glyph from the passed renderer."""
        self.glyph.remove(ren)

    def move_to(self, elevation, azimuth):
        """Move the light to the specified elevation and azimuthal
        angles (in degrees)."""
        self.elevation = elevation
        self.azimuth = azimuth

    #################################################################
    # Trait handlers.
    #################################################################
    def _activate_changed(self, val):
        if val:
            self.source.switch = 1
            self.glyph.show()
        else:
            self.source.switch = 0
            self.glyph.hide()

    def _intensity_changed(self, val):
        self.source.intensity = val

    def _color_changed(self, val):
        self.source.color = val
        self.glyph.set_color(val)

    def _elevation_changed(self, val):
        self.glyph.move_to(val, self.azimuth)
        self.source.position = self._to_pos(val, self.azimuth)

    def _azimuth_changed(self, val):
        self.glyph.move_to(self.elevation, val)
        self.source.position = self._to_pos(self.elevation, val)

    #################################################################
    # Non-public interface.
    #################################################################
    def _to_pos(self, elevation, azimuth):
        """Convert the given elevation and azimuth angles (degrees) to
        a position vector."""
        theta = azimuth*pi/180.0
        phi = (90.0-elevation)*pi/180.0
        x = sin(theta)*sin(phi)
        y = cos(phi)
        z = cos(theta)*sin(phi)
        return x, y, z

    def _from_pos(self, x, y, z):
        """Given the position vector, return an elevation and azimuth
        angle (in degrees)."""
        theta = atan2(x, z)
        phi = atan2(sqrt(x**2+z**2), y)
        az = theta*180.0/pi
        el = 90.0 - phi*180.0/pi
        return el, az

######################################################################
# `CloseHandler` class.
######################################################################
class CloseHandler(Handler):
    """This class cleans up after the UI for the Light Manager is
    closed."""
    def close(self, info, is_ok):
        """This method is invoked when the user closes the UI."""
        light_manager = info.object
        light_manager.on_ui_close()
        return True

######################################################################
# `LightManager` class.
######################################################################
class LightManager(HasTraits):

    """This class manages all the lights and presents a GUI for the
    lights.

    There are two default lighting modes possible (specified via the
    `light_mode` trait).  The 'vtk' mode uses the default lighting
    mode which is basically a single headlight.  The 'raymond' mode
    creates three lights to give better overall illumination (thanks
    to Raymond Maple).
    """

    # The version of this class.  Used for persistence.
    __version__ = 0

    #################################################################
    # Traits.
    #################################################################

    # Valid modes currently are 'vtk' and 'raymond'.  'vtk' is the
    # default VTK light setup with only one light on in headlight
    # mode. 'raymond' is Raymond Maple's default configuration with
    # three active lights.  Please note that this only specifies a
    # default mode used to initialize the lights to a sane default.
    # The user can always change the light configuration via the GUI
    # such that the mode is neither 'vtk' nor 'raymond'.
    light_mode = Trait('raymond', TraitRevPrefixMap({'raymond':1,
                                                     'vtk':2}),
                       desc='specifies a default lighting mode')

    # Specify the number of lights.  If new lights are added they are
    # by default turned off.  Similarly if the number of lights are
    # reduced the last lights alone are removed.
    number_of_lights = Range(3, 8, 4, desc='specifies the number of lights')

    # The list of added lights.
    lights = List(CameraLight, editor=ListEditor(use_notebook=True,
                                                 page_name='Light'),
                  record=True)

    view = View( Group( 'light_mode',
                        'number_of_lights', ),
                Item('lights', style='custom', show_label=False),
                resizable=True,
                buttons=['OK'])

    #################################################################
    # `object` interface.
    #################################################################
    def __init__(self, renwin, **traits):
        super(LightManager, self).__init__(**traits)

        self.ui = None
        self.renwin = renwin
        ren = self.renwin.renderer

        # VTK requires that there always be atleast one light turned
        # on (with SwitchOn).  The renderer already has one headlight
        # already enabled.  We merely set the intensity of this light
        # to zero and never change that.  Note that if this light is
        # turned off, and no other lights are "on", then VTK will
        # create a new light!
        ren.lights[0].intensity = 0.0

        # Create the lights.
        self.lights = []
        for i in range(self.number_of_lights):
            light = CameraLight(self.renwin)
            self.lights.append(light)

        # Setup the light mode.
        self._light_mode_changed(self.light_mode)

    def __get_pure_state__(self):
        d = self.__dict__.copy()
        for name in ['__sync_trait__', 'renwin', 'ui',
                     '__traits_listener__']:
            d.pop(name, None)
        return d

    def __set_pure_state__(self, state):
        first = ['light_mode', 'number_of_lights']
        state_pickler.set_state(self, state, first=first, last=['lights'])

    def __getstate__(self):
        return state_pickler.dumps(self)

    def __setstate__(self, str_state):
        # This method is unnecessary since this object will almost
        # never be pickled by itself and only via the scene, therefore
        # __init__ will be called when the scene is constructed.
        # However, setstate is defined just for completeness.
        #self.__init__()
        state = state_pickler.loads_state(str_state)
        state_pickler.update_state(state)
        self.__set_pure_state__(state)

    #################################################################
    # `LightManager` interface.
    #################################################################
    def configure(self):
        """Pops up the GUI control widget."""
        if self.ui is None:
            self._show_glyphs()
            view = View(Group(Item(name='light_mode'),
                              Item(name='number_of_lights'),
                              label='LightManager'),
                        Group(Item(name='lights', style='custom'),
                              label='Lights',
                              selected=True, show_labels=False),
                        resizable=True,
                        buttons=['OK'],
                        handler=CloseHandler())
            self.ui = view.ui(self)
        else:
            try:
                self.ui.control.Raise()
            except AttributeError:
                pass

    def on_ui_close(self):
        """This method removes the glyphs used to show the lights on
        screen when the GUI dialog is closed.  This is typically only
        called from the CloseHandler."""
        ren = self.renwin.renderer
        for l in self.lights:
            l.remove_glyph(ren)
        self.ui = None

    #################################################################
    # Non-public interface.
    #################################################################
    def _show_glyphs(self):
        """Shows the glyphs when the light config UI is shown."""
        rw = self.renwin
        ren = rw.renderer
        rw.reset_zoom()
        bounds = ren.compute_visible_prop_bounds()
        for light in self.lights:
            light.add_glyph(ren, bounds)
        rw.render()

    def _light_mode_changed(self, mode):
        lights = self.lights
        if mode == 'raymond':
            for i in range(len(lights)):
                if i < 3:
                    lights[i].activate = True
                    lights[i].intensity = 1.0
                    lights[i].color = 1.0, 1.0, 1.0
                else:
                    lights[i].activate = False
                    lights[i].move_to(0.0, 0.0)
                    lights[i].intensity = 1.0
                    lights[i].color = 1.0, 1.0, 1.0

            lights[0].move_to(45.0, 45.0)
            lights[1].move_to(-30.0,-60.0)
            lights[1].intensity = 0.6
            lights[2].move_to(-30.0, 60.0)
            lights[2].intensity = 0.5
        else:
            for i in range(len(lights)):
                lights[i].move_to(0.0, 0.0)
                lights[i].intensity = 1.0
                lights[i].color = 1.0, 1.0, 1.0
                if i == 0 :
                    lights[i].activate  = True
                else:
                    lights[i].activate = False

    def _number_of_lights_changed(self, old, new):
        ren = self.renwin.renderer
        changed = False
        if new == old:
            return
        elif new > old:
            for i in range(new - old):
                light = CameraLight(self.renwin)
                self.lights.append(light)
            changed = True
        elif new < old:
            for i in range(old - new):
                light = self.lights.pop()
                light.close(self.renwin)
            changed = True

<|endoftext|>


<commit_before>from __future__ import absolute_import
from __future__ import print_function
from __future__ import division

import numpy as np
import tensorflow as tf

class DynamicMemoryCell(tf.nn.rnn_cell.RNNCell):
    """
    Implementation of a dynamic memory cell as a gated recurrent network.
    The cell's hidden state is divided into blocks and each block's weights are tied.
    """

    def __init__(self, num_blocks, num_units_per_block, initializer=None, activation=tf.nn.relu):
        self._num_blocks = num_blocks # M
        self._num_units_per_block = num_units_per_block # d
        self._activation = activation # \phi
        self._initializer = initializer

    @property
    def state_size(self):
        return self._num_blocks * self._num_units_per_block

    @property
    def output_size(self):
        return self._num_blocks * self._num_units_per_block

    def get_gate(self, inputs, state_j, key_j):
        """
        Implements the gate (a scalar for each block). Equation 2:

        g_j <- \sigma(s_t^T h_j + s_t^T w_j)
        """
        a = tf.reduce_sum(inputs * state_j, reduction_indices=[1])
        b = tf.reduce_sum(inputs * key_j, reduction_indices=[1])
        return tf.sigmoid(a + b)

    def get_candidate(self, state_j, key_j, inputs, U, V, W):
        """
        Represents the new memory candidate that will be weighted by the
        gate value and combined with the existing memory. Equation 3:

        h_j^~ <- \phi(U h_j + V w_j + W s_t)
        """
        state_U = tf.matmul(state_j, U)
        inputs_W = tf.matmul(inputs, W)
        key_V = tf.matmul(tf.expand_dims(key_j, 0), V)
        return self._activation(state_U + key_V + inputs_W)

    def __call__(self, inputs, state, scope=None):
        with tf.variable_scope(scope or type(self).__name__, initializer=self._initializer):
            # Split the hidden state into blocks (each U, V, W are shared across blocks).
            state = tf.split(1, self._num_blocks, state) # TODO: split+concat is relatively expensive

            U = tf.get_variable('U', [self._num_units_per_block, self._num_units_per_block])
            V = tf.get_variable('V', [self._num_units_per_block, self._num_units_per_block])
            W = tf.get_variable('W', [self._num_units_per_block, self._num_units_per_block])

            next_states = []
            for j, state_j in enumerate(state): # Hidden State (j)
                key_j = tf.get_variable('key_{}'.format(j), [self._num_units_per_block])
                gate_j = self.get_gate(inputs, state_j, key_j)
                candidate_j = self.get_candidate(state_j, key_j, inputs, U, V, W)

                # Equation 4: h_j <- h_j + g_j * h_j^~
                # Perform an update of the hidden state (memory).
                state_j_next = state_j + tf.expand_dims(gate_j, -1) * candidate_j

                # Equation 5: h_j <- h_j / \norm{h_j}
                # Forgot previous memories by normalization.
                state_j_next = tf.nn.l2_normalize(state_j_next, -1)

                next_states.append(state_j_next)
            state_next = tf.concat(1, next_states)
        return state_next, state_next
<commit_msg>Some cleanup<commit_after>from __future__ import absolute_import
from __future__ import print_function
from __future__ import division

import numpy as np
import tensorflow as tf

class DynamicMemoryCell(tf.nn.rnn_cell.RNNCell):
    """
    Implementation of a dynamic memory cell as a gated recurrent network.
    The cell's hidden state is divided into blocks and each block's weights are tied.
    """

    def __init__(self, num_blocks, num_units_per_block, initializer=None, activation=tf.nn.relu):
        self._num_blocks = num_blocks # M
        self._num_units_per_block = num_units_per_block # d
        self._activation = activation # \phi
        self._initializer = initializer

    @property
    def state_size(self):
        return self._num_blocks * self._num_units_per_block

    @property
    def output_size(self):
        return self._num_blocks * self._num_units_per_block

    def get_gate(self, state_j, key_j, inputs):
        """
        Implements the gate (scalar for each block). Equation 2:

        g_j <- \sigma(s_t^T h_j + s_t^T w_j)
        """
        a = tf.reduce_sum(inputs * state_j, reduction_indices=[1])
        b = tf.reduce_sum(inputs * key_j, reduction_indices=[1])
        return tf.sigmoid(a + b)

    def get_candidate(self, state_j, key_j, inputs, U, V, W):
        """
        Represents the new memory candidate that will be weighted by the
        gate value and combined with the existing memory. Equation 3:

        h_j^~ <- \phi(U h_j + V w_j + W s_t)
        """
        key_V = tf.matmul(tf.expand_dims(key_j, 0), V)
        state_U = tf.matmul(state_j, U)
        inputs_W = tf.matmul(inputs, W)
        return self._activation(state_U + key_V + inputs_W)

    def __call__(self, inputs, state, scope=None):
        with tf.variable_scope(scope or type(self).__name__, initializer=self._initializer):
            # Split the hidden state into blocks (each U, V, W are shared across blocks).
            state = tf.split(1, self._num_blocks, state) # TODO: split+concat is relatively expensive

            U = tf.get_variable('U', [self._num_units_per_block, self._num_units_per_block])
            V = tf.get_variable('V', [self._num_units_per_block, self._num_units_per_block])
            W = tf.get_variable('W', [self._num_units_per_block, self._num_units_per_block])

            next_states = []
            for j, state_j in enumerate(state): # Hidden State (j)
                key_j = tf.get_variable('key_{}'.format(j), [self._num_units_per_block])
                gate_j = self.get_gate(state_j, key_j, inputs)
                candidate_j = self.get_candidate(state_j, key_j, inputs, U, V, W)

                # Equation 4: h_j <- h_j + g_j * h_j^~
                # Perform an update of the hidden state (memory).
                state_j_next = state_j + tf.expand_dims(gate_j, -1) * candidate_j

                # Equation 5: h_j <- h_j / \norm{h_j}
                # Forgot previous memories by normalization.
                state_j_next = tf.nn.l2_normalize(state_j_next, -1)

                next_states.append(state_j_next)
            state_next = tf.concat(1, next_states)
        return state_next, state_next
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import time
import netsvc
from osv import fields, osv
import tools

from tools.misc import currency
from tools.translate import _

class res_currency(osv.osv):
    def _current_rate(self, cr, uid, ids, name, arg, context=None):
        if context is None:
            context = {}
        res = {}
        if 'date' in context:
            date = context['date']
        else:
            date = time.strftime('%Y-%m-%d')
        date = date or time.strftime('%Y-%m-%d')
        # Convert False values to None ...
        currency_rate_type = context.get('currency_rate_type_id') or None
        # ... and use 'is NULL' instead of '= some-id'.
        operator = '=' if currency_rate_type else 'is'
        for id in ids:
            cr.execute("SELECT currency_id, rate FROM res_currency_rate WHERE currency_id = %s AND name <= %s AND currency_rate_type_id " + operator +" %s ORDER BY name desc LIMIT 1" ,(id, date, currency_rate_type))
            if cr.rowcount:
                id, rate = cr.fetchall()[0]
                res[id] = rate
            else:
                res[id] = 0
        return res
    _name = "res.currency"
    _description = "Currency"
    _columns = {
        # Note: 'code' column was removed as of v6.0, the 'name' should now hold the ISO code.
        'name': fields.char('Currency', size=32, required=True, help="Currency Code (ISO 4217)"),
        'symbol': fields.char('Symbol', size=3, help="Currency sign, to be used when printing amounts."),
        'rate': fields.function(_current_rate, method=True, string='Current Rate', digits=(12,6),
            help='The rate of the currency to the currency of rate 1.'),
        'rate_ids': fields.one2many('res.currency.rate', 'currency_id', 'Rates'),
        'accuracy': fields.integer('Computational Accuracy'),
        'rounding': fields.float('Rounding Factor', digits=(12,6)),
        'active': fields.boolean('Active'),
        'company_id':fields.many2one('res.company', 'Company'),
        'date': fields.date('Date'),
        'base': fields.boolean('Base'),
        'position': fields.selection([('after','After Amount'),('before','Before Amount')], 'Symbol position', help="Determines where the currency symbol should be placed after or before the amount.")
    }
    _defaults = {
        'active': lambda *a: 1,
        'position' : 'after',
    }
    _sql_constraints = [
        # this constraint does not cover all cases due to SQL NULL handling for company_id,
        # so it is complemented with a unique index (see below). The constraint and index
        # share the same prefix so that IntegrityError triggered by the index will be caught
        # and reported to the user with the constraint's error message.
        ('unique_name_company_id', 'unique (name, company_id)', 'The currency code must be unique per company!'),
    ]
    _order = "name"

    def init(self, cr):
        # CONSTRAINT/UNIQUE INDEX on (name,company_id)
        # /!\ The unique constraint 'unique_name_company_id' is not sufficient, because SQL92
        # only support field names in constraint definitions, and we need a function here:
        # we need to special-case company_id to treat all NULL company_id as equal, otherwise
        # we would allow duplicate "global" currencies (all having company_id == NULL)
        cr.execute("""SELECT indexname FROM pg_indexes WHERE indexname = 'res_currency_unique_name_company_id_idx'""")
        if not cr.fetchone():
            cr.execute("""CREATE UNIQUE INDEX res_currency_unique_name_company_id_idx
                          ON res_currency
                          (name, (COALESCE(company_id,-1)))""")

    def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
        res = super(res_currency, self).read(cr, user, ids, fields, context, load)
        currency_rate_obj = self.pool.get('res.currency.rate')
        for r in res:
            if r.__contains__('rate_ids'):
                rates=r['rate_ids']
                if rates:
                    currency_date = currency_rate_obj.read(cr, user, rates[0], ['name'])['name']
                    r['date'] = currency_date
        return res

    def name_get(self, cr, uid, ids, context=None):
        if not ids:
            return []
        if isinstance(ids, (int, long)):
            ids = [ids]
        reads = self.read(cr, uid, ids, ['name','symbol'], context=context, load='_classic_write')
        return [(x['id'], tools.ustr(x['name']) + (x['symbol'] and (' (' + tools.ustr(x['symbol']) + ')') or '')) for x in reads]

    def round(self, cr, uid, currency, amount):
        if currency.rounding == 0:
            return 0.0
        else:
            # /!\ First member below must be rounded to full unit!
            # Do not pass a rounding digits value to round()
            return round(amount / currency.rounding) * currency.rounding

    def is_zero(self, cr, uid, currency, amount):
        return abs(self.round(cr, uid, currency, amount)) < currency.rounding

    def _get_conversion_rate(self, cr, uid, from_currency, to_currency, context=None):
        if context is None:
            context = {}
        ctx = context.copy()
        ctx.update({'currency_rate_type_id': ctx.get('currency_rate_type_from')})
        from_currency = self.browse(cr, uid, from_currency.id, context=ctx)

        ctx.update({'currency_rate_type_id': ctx.get('currency_rate_type_to')})
        to_currency = self.browse(cr, uid, to_currency.id, context=ctx)

        if from_currency.rate == 0 or to_currency.rate == 0:
            date = context.get('date', time.strftime('%Y-%m-%d'))
            if from_currency.rate == 0:
                currency_symbol = from_currency.symbol
            else:
                currency_symbol = to_currency.symbol
            raise osv.except_osv(_('Error'), _('No rate found \n' \
                    'for the currency: %s \n' \
                    'at the date: %s') % (currency_symbol, date))
        return to_currency.rate/from_currency.rate

    def compute(self, cr, uid, from_currency_id, to_currency_id, from_amount,
                round=True, currency_rate_type_from=False, currency_rate_type_to=False, context=None):
        if not context:
            context = {}
        if not from_currency_id:
            from_currency_id = to_currency_id
        if not to_currency_id:
            to_currency_id = from_currency_id
        xc = self.browse(cr, uid, [from_currency_id,to_currency_id], context=context)
        from_currency = (xc[0].id == from_currency_id and xc[0]) or xc[1]
        to_currency = (xc[0].id == to_currency_id and xc[0]) or xc[1]
        if (to_currency_id == from_currency_id) and (currency_rate_type_from == currency_rate_type_to):
            if round:
                return self.round(cr, uid, to_currency, from_amount)
            else:
                return from_amount
        else:
            context.update({'currency_rate_type_from': currency_rate_type_from, 'currency_rate_type_to': currency_rate_type_to})
            rate = self._get_conversion_rate(cr, uid, from_currency, to_currency, context=context)
            if round:
                return self.round(cr, uid, to_currency, from_amount * rate)
            else:
                return (from_amount * rate)

res_currency()

class res_currency_rate_type(osv.osv):
    _name = "res.currency.rate.type"
    _description = "Currency Rate Type"
    _columns = {
        'name': fields.char('Name', size=64, required=True, translate=True),
    }

res_currency_rate_type()

class res_currency_rate(osv.osv):
    _name = "res.currency.rate"
    _description = "Currency Rate"

    _columns = {
        'name': fields.date('Date', required=True, select=True),
        'rate': fields.float('Rate', digits=(12,6), required=True,
            help='The rate of the currency to the currency of rate 1'),
        'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
        'currency_rate_type_id': fields.many2one('res.currency.rate.type', 'Currency Rate Type', help="Allow you to define your own currency rate types, like 'Average' or 'Year to Date'. Leave empty if you simply want to use the normal 'spot' rate type"),
    }
    _defaults = {
        'name': lambda *a: time.strftime('%Y-%m-%d'),
    }
    _order = "name desc"

res_currency_rate()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

<commit_msg>[IMP] res.currency: name_search() implementation to match name_get()<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import re
import time
import netsvc
from osv import fields, osv
import tools

from tools.misc import currency
from tools.translate import _

CURRENCY_DISPLAY_PATTERN = re.compile(r'(\w+)\s*(?:\((.*)\))?')

class res_currency(osv.osv):
    def _current_rate(self, cr, uid, ids, name, arg, context=None):
        if context is None:
            context = {}
        res = {}
        if 'date' in context:
            date = context['date']
        else:
            date = time.strftime('%Y-%m-%d')
        date = date or time.strftime('%Y-%m-%d')
        # Convert False values to None ...
        currency_rate_type = context.get('currency_rate_type_id') or None
        # ... and use 'is NULL' instead of '= some-id'.
        operator = '=' if currency_rate_type else 'is'
        for id in ids:
            cr.execute("SELECT currency_id, rate FROM res_currency_rate WHERE currency_id = %s AND name <= %s AND currency_rate_type_id " + operator +" %s ORDER BY name desc LIMIT 1" ,(id, date, currency_rate_type))
            if cr.rowcount:
                id, rate = cr.fetchall()[0]
                res[id] = rate
            else:
                res[id] = 0
        return res
    _name = "res.currency"
    _description = "Currency"
    _columns = {
        # Note: 'code' column was removed as of v6.0, the 'name' should now hold the ISO code.
        'name': fields.char('Currency', size=32, required=True, help="Currency Code (ISO 4217)"),
        'symbol': fields.char('Symbol', size=3, help="Currency sign, to be used when printing amounts."),
        'rate': fields.function(_current_rate, method=True, string='Current Rate', digits=(12,6),
            help='The rate of the currency to the currency of rate 1.'),
        'rate_ids': fields.one2many('res.currency.rate', 'currency_id', 'Rates'),
        'accuracy': fields.integer('Computational Accuracy'),
        'rounding': fields.float('Rounding Factor', digits=(12,6)),
        'active': fields.boolean('Active'),
        'company_id':fields.many2one('res.company', 'Company'),
        'date': fields.date('Date'),
        'base': fields.boolean('Base'),
        'position': fields.selection([('after','After Amount'),('before','Before Amount')], 'Symbol position', help="Determines where the currency symbol should be placed after or before the amount.")
    }
    _defaults = {
        'active': lambda *a: 1,
        'position' : 'after',
    }
    _sql_constraints = [
        # this constraint does not cover all cases due to SQL NULL handling for company_id,
        # so it is complemented with a unique index (see below). The constraint and index
        # share the same prefix so that IntegrityError triggered by the index will be caught
        # and reported to the user with the constraint's error message.
        ('unique_name_company_id', 'unique (name, company_id)', 'The currency code must be unique per company!'),
    ]
    _order = "name"

    def init(self, cr):
        # CONSTRAINT/UNIQUE INDEX on (name,company_id)
        # /!\ The unique constraint 'unique_name_company_id' is not sufficient, because SQL92
        # only support field names in constraint definitions, and we need a function here:
        # we need to special-case company_id to treat all NULL company_id as equal, otherwise
        # we would allow duplicate "global" currencies (all having company_id == NULL)
        cr.execute("""SELECT indexname FROM pg_indexes WHERE indexname = 'res_currency_unique_name_company_id_idx'""")
        if not cr.fetchone():
            cr.execute("""CREATE UNIQUE INDEX res_currency_unique_name_company_id_idx
                          ON res_currency
                          (name, (COALESCE(company_id,-1)))""")

    def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
        res = super(res_currency, self).read(cr, user, ids, fields, context, load)
        currency_rate_obj = self.pool.get('res.currency.rate')
        for r in res:
            if r.__contains__('rate_ids'):
                rates=r['rate_ids']
                if rates:
                    currency_date = currency_rate_obj.read(cr, user, rates[0], ['name'])['name']
                    r['date'] = currency_date
        return res

    def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=100):
        if not args:
            args = []
        if name:
            ids = self.search(cr, user, ([('name','=',name)] + args), limit=limit, context=context)
            name_match = CURRENCY_DISPLAY_PATTERN.match(name)
            if not ids and name_match:
               ids = self.search(cr, user, [('name','=', name_match.group(1))] + args, limit=limit, context=context)
        else:
            ids = self.search(cr, user, args, limit=limit, context=context)
        return self.name_get(cr, user, ids, context=context)

    def name_get(self, cr, uid, ids, context=None):
        if not ids:
            return []
        if isinstance(ids, (int, long)):
            ids = [ids]
        reads = self.read(cr, uid, ids, ['name','symbol'], context=context, load='_classic_write')
        return [(x['id'], tools.ustr(x['name']) + (x['symbol'] and (' (' + tools.ustr(x['symbol']) + ')') or '')) for x in reads]

    def round(self, cr, uid, currency, amount):
        if currency.rounding == 0:
            return 0.0
        else:
            # /!\ First member below must be rounded to full unit!
            # Do not pass a rounding digits value to round()
            return round(amount / currency.rounding) * currency.rounding

    def is_zero(self, cr, uid, currency, amount):
        return abs(self.round(cr, uid, currency, amount)) < currency.rounding

    def _get_conversion_rate(self, cr, uid, from_currency, to_currency, context=None):
        if context is None:
            context = {}
        ctx = context.copy()
        ctx.update({'currency_rate_type_id': ctx.get('currency_rate_type_from')})
        from_currency = self.browse(cr, uid, from_currency.id, context=ctx)

        ctx.update({'currency_rate_type_id': ctx.get('currency_rate_type_to')})
        to_currency = self.browse(cr, uid, to_currency.id, context=ctx)

        if from_currency.rate == 0 or to_currency.rate == 0:
            date = context.get('date', time.strftime('%Y-%m-%d'))
            if from_currency.rate == 0:
                currency_symbol = from_currency.symbol
            else:
                currency_symbol = to_currency.symbol
            raise osv.except_osv(_('Error'), _('No rate found \n' \
                    'for the currency: %s \n' \
                    'at the date: %s') % (currency_symbol, date))
        return to_currency.rate/from_currency.rate

    def compute(self, cr, uid, from_currency_id, to_currency_id, from_amount,
                round=True, currency_rate_type_from=False, currency_rate_type_to=False, context=None):
        if not context:
            context = {}
        if not from_currency_id:
            from_currency_id = to_currency_id
        if not to_currency_id:
            to_currency_id = from_currency_id
        xc = self.browse(cr, uid, [from_currency_id,to_currency_id], context=context)
        from_currency = (xc[0].id == from_currency_id and xc[0]) or xc[1]
        to_currency = (xc[0].id == to_currency_id and xc[0]) or xc[1]
        if (to_currency_id == from_currency_id) and (currency_rate_type_from == currency_rate_type_to):
            if round:
                return self.round(cr, uid, to_currency, from_amount)
            else:
                return from_amount
        else:
            context.update({'currency_rate_type_from': currency_rate_type_from, 'currency_rate_type_to': currency_rate_type_to})
            rate = self._get_conversion_rate(cr, uid, from_currency, to_currency, context=context)
            if round:
                return self.round(cr, uid, to_currency, from_amount * rate)
            else:
                return (from_amount * rate)

res_currency()

class res_currency_rate_type(osv.osv):
    _name = "res.currency.rate.type"
    _description = "Currency Rate Type"
    _columns = {
        'name': fields.char('Name', size=64, required=True, translate=True),
    }

res_currency_rate_type()

class res_currency_rate(osv.osv):
    _name = "res.currency.rate"
    _description = "Currency Rate"

    _columns = {
        'name': fields.date('Date', required=True, select=True),
        'rate': fields.float('Rate', digits=(12,6), required=True,
            help='The rate of the currency to the currency of rate 1'),
        'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
        'currency_rate_type_id': fields.many2one('res.currency.rate.type', 'Currency Rate Type', help="Allow you to define your own currency rate types, like 'Average' or 'Year to Date'. Leave empty if you simply want to use the normal 'spot' rate type"),
    }
    _defaults = {
        'name': lambda *a: time.strftime('%Y-%m-%d'),
    }
    _order = "name desc"

res_currency_rate()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

<|endoftext|>


<commit_before>#
#   Copyright (c) 2015, Scott J Maddox
#
#   This file is part of Open Band Parameters Device Simulator (OBPDS).
#
#   OBPDS is free software: you can redistribute it and/or modify
#   it under the terms of the GNU Affero General Public License as published
#   by the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   OBPDS is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU Affero General Public License for more details.
#
#   You should have received a copy of the GNU Affero General Public License
#   along with OBPDS.  If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################

import logging
logger = logging.getLogger(__name__)

import numpy
from numpy.linalg import norm
from scipy.sparse.linalg import spsolve

class NewtonResult(object):
    def __init__(self, value, num_iter, converged):
        self.value = value
        self.num_iter = num_iter
        self.converged = converged

def newton(G, A, u0, rtol=1e-8, atol=1e-4, tau=0.5, max_iter=100):
    '''
    Uses Newton's method to solve a system of non-linear equations,

        G(U) = 0,

    where the unkown vector, U, corresponds to the values of the finite
    element or volume solution, u_h, at the node points. The Jacobian matrix,

        A(U) = dG(U)/dU,

    is a sparse stiffness matrix corresponding to a linear elliptic
    boundary value problem (linearized about U). The Newton procedure used
    is described in the user manual.

    Arguments
    ---------
    G : callable
        Accepts the current guess, uk.
        Returns the residual vector of length N at uk.
    A : callable
        Accepts the current guess, uk.
        Returns the NxN Jacobian matrix linearized about uk.
    u0 : vector of length N
        Initial guess of the unkown vector, U.
    rtol : float (default: 1e-8)
        Relative tolerance for termination.
    atol : float (default: 1e-4)
        Absolute tolerance for termination.
    tau : float (default: 0.5)
        Decrease parameter, used in the algorithm to stabilize the Newton
        iteration. The value should be between 0 and 1. Values closer to 1
        increase stability, but slow down convergence.
    max_iter : int (default: 100)
        Maximum number of iterations.

    Returns
    -------
    result.value : vector of length N
        The unkown vector, U.
    result.num_iter: int
        The number of iterations used.
    result.converged:
        True if the solution converged, False if it did not.
    '''
    # Step 1. Calculate the initial values.
    sk = 1. # damping parameter
    uk = u0
    Ak = A(uk)
#     print 'Ak', Ak
    Gk = G(uk)
#     print 'Gk', Gk
    Gk_norm = norm(Gk)

    for k in xrange(1, max_iter+1):
        # Step 2. Calculate the delta.
        logger.debug('Gk = %s', Gk)
        logger.debug('Ak = %s', Ak)
        duk = spsolve(Ak, -Gk, use_umfpack=True)
        logger.debug('duk = %s', duk)
#         print 'duk', duk

        while True:
            # Step 3. Calculate the next guess.
            ukp = uk + sk*duk
            assert not numpy.isnan(ukp).any()

            Gkp = G(ukp)
            Gkp_norm = norm(Gkp)
            xi_kp = Gkp_norm / Gk_norm

            # Step 4. Adjust the damping parameter.
            if 1 - xi_kp < tau * sk:
                sk /= 2.
                logger.debug('decreasing sk to {}'.format(sk))
                continue  # go to Step 3.
            else:
                sk = sk/(sk+(1.-sk)*xi_kp/2.)
                logger.debug('increasing sk to {}'.format(sk))
                break  # go to Step 5.

        # Step 5. Quit if converged; iterate if not.
        rerr = numpy.abs(duk/ukp).max()
        aerr = numpy.abs(duk).max()
        logger.debug('rerr = {}, aerr = {}'.format(rerr, aerr))
        if rerr < rtol or aerr < atol:
            logger.info('converged after {} iterations'.format(k))
            return NewtonResult(value=ukp, num_iter=k, converged=True)
        else:
            uk = ukp
            Ak = A(uk)
            Gk = Gkp
            Gk_norm = Gkp_norm
            continue  # go to Step 2.

    # Failed to converge, but return what we have.
    logger.warn('failed to converge after {} iterations'.format(k))
    return NewtonResult(value=ukp, num_iter=k, converged=False)
<commit_msg>check for `aerr < atol` early<commit_after>#
#   Copyright (c) 2015, Scott J Maddox
#
#   This file is part of Open Band Parameters Device Simulator (OBPDS).
#
#   OBPDS is free software: you can redistribute it and/or modify
#   it under the terms of the GNU Affero General Public License as published
#   by the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   OBPDS is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU Affero General Public License for more details.
#
#   You should have received a copy of the GNU Affero General Public License
#   along with OBPDS.  If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################

import logging
logger = logging.getLogger(__name__)

import numpy
from numpy.linalg import norm
from scipy.sparse.linalg import spsolve

class NewtonResult(object):
    def __init__(self, value, num_iter, converged):
        self.value = value
        self.num_iter = num_iter
        self.converged = converged

def newton(G, A, u0, rtol=1e-8, atol=1e-4, tau=0.5, max_iter=100):
    '''
    Uses Newton's method to solve a system of non-linear equations,

        G(U) = 0,

    where the unkown vector, U, corresponds to the values of the finite
    element or volume solution, u_h, at the node points. The Jacobian matrix,

        A(U) = dG(U)/dU,

    is a sparse stiffness matrix corresponding to a linear elliptic
    boundary value problem (linearized about U). The Newton procedure used
    is described in the user manual.

    Arguments
    ---------
    G : callable
        Accepts the current guess, uk.
        Returns the residual vector of length N at uk.
    A : callable
        Accepts the current guess, uk.
        Returns the NxN Jacobian matrix linearized about uk.
    u0 : vector of length N
        Initial guess of the unkown vector, U.
    rtol : float (default: 1e-8)
        Relative tolerance for termination.
    atol : float (default: 1e-4)
        Absolute tolerance for termination.
    tau : float (default: 0.5)
        Decrease parameter, used in the algorithm to stabilize the Newton
        iteration. The value should be between 0 and 1. Values closer to 1
        increase stability, but slow down convergence.
    max_iter : int (default: 100)
        Maximum number of iterations.

    Returns
    -------
    result.value : vector of length N
        The unkown vector, U.
    result.num_iter: int
        The number of iterations used.
    result.converged:
        True if the solution converged, False if it did not.
    '''
    # Step 1. Calculate the initial values.
    sk = 1. # damping parameter
    uk = u0
    Ak = A(uk)
#     print 'Ak', Ak
    Gk = G(uk)
#     print 'Gk', Gk
    Gk_norm = norm(Gk)

    for k in xrange(1, max_iter+1):
        # Step 2. Calculate the delta.
        logger.debug('Gk = %s', Gk)
        logger.debug('Ak = %s', Ak)
        duk = spsolve(Ak, -Gk, use_umfpack=True)
        logger.debug('duk = %s', duk)
#         print 'duk', duk

        aerr = numpy.abs(duk).max()
        logger.debug('aerr = {}'.format(aerr))
        if aerr < atol:
            logger.info('converged after {} iterations'.format(k))
            return NewtonResult(value=uk + duk, num_iter=k, converged=True)

        while True:
            # Step 3. Calculate the next guess.
            ukp = uk + sk*duk
            assert not numpy.isnan(ukp).any()

            Gkp = G(ukp)
            Gkp_norm = norm(Gkp)
            xi_kp = Gkp_norm / Gk_norm

            # Step 4. Adjust the damping parameter.
            if 1 - xi_kp < tau * sk:
                sk /= 2.
                logger.debug('decreasing sk to {}'.format(sk))
                continue  # go to Step 3.
            else:
                sk = sk/(sk+(1.-sk)*xi_kp/2.)
                logger.debug('increasing sk to {}'.format(sk))
                break  # go to Step 5.

        # Step 5. Quit if converged; iterate if not.
        rerr = numpy.abs(duk/ukp).max()
        logger.debug('rerr = {}'.format(rerr))
        if rerr < rtol:
            logger.info('converged after {} iterations'.format(k))
            return NewtonResult(value=ukp, num_iter=k, converged=True)
        else:
            uk = ukp
            Ak = A(uk)
            Gk = Gkp
            Gk_norm = Gkp_norm
            continue  # go to Step 2.

    # Failed to converge, but return what we have.
    logger.warn('failed to converge after {} iterations'.format(k))
    return NewtonResult(value=ukp, num_iter=k, converged=False)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from django.contrib import admin
from django.contrib.contenttypes import generic
from django.conf import settings
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from django.forms import ModelForm
from django.forms.models import BaseInlineFormSet
from django.core.urlresolvers import reverse

from models import (
    Domain,
    Alias,
    Site,
    Template,
    Targetting,
    Circle,
    Member,
    Membership,
    Publish,
    Journal,
    Message,
    Provision,
    Publication,
)
from tasks import apply_publish, deliver_mail

def link_to_relation(self, obj, field=""):
    ''' relation field link
        - self : Admin
        - obj  : Model Instance
        - filed : Field Name
    '''
    if obj is None:
        return ""

    fobj = getattr(obj, field, None)
    if fobj:
        url = reverse("admin:%s_change" % fobj._meta.db_table,
                      args=[fobj.id])
        return '%s' % (url, fobj.__unicode__())

user_link = lambda self, obj: link_to_relation(self, obj, "user")
user_link.short_description = _(u"System User")
user_link.allow_tags = True

member_link = lambda self, obj: link_to_relation(self, obj, "member")
member_link.short_description = _(u"Member")
member_link.allow_tags = True

circle_link = lambda self, obj: link_to_relation(self, obj, "circle")
circle_link.short_description = _(u"Circle")
circle_link.allow_tags = True

publish_link = lambda self, obj: link_to_relation(self, obj, "publish")
publish_link.short_description = _(u"Publish")
publish_link.allow_tags = True

message_link = lambda self, obj: link_to_relation(self, obj, "message")
message_link.short_description = _(u"Message")
message_link.allow_tags = True

###

if settings.DEBUG:
    try:
        from kombu.transport.django.models import (
            Queue as KombuQueue,
            Message as KombuMessage
        )
        from djcelery.models import TaskMeta, TaskSetMeta

        ### KombuQueue
        class KombuQueueAdmin(admin.ModelAdmin):
            list_display = tuple([f.name for f in KombuQueue._meta.fields])
        admin.site.register(KombuQueue, KombuQueueAdmin)

        ### define __unicode__ to Queue class
        #
        #def __unicode__(self):
        #
        #   return self.name

        ### KombuMessage
        class KombuMessageAdmin(admin.ModelAdmin):
            list_display = tuple([f.name for f in KombuMessage._meta.fields])
        admin.site.register(KombuMessage, KombuMessageAdmin)

        ### TaskMeta
        class TaskMetaAdmin(admin.ModelAdmin):
            list_display = tuple([f.name for f in TaskMeta._meta.fields])
            list_filter = ('status',)
            date_hierarchy = 'date_done'
        admin.site.register(TaskMeta, TaskMetaAdmin)

        ### TaskSetMeta
        class TaskSetMetaAdmin(admin.ModelAdmin):
            list_display = tuple([f.name for f in TaskSetMeta._meta.fields])
        admin.site.register(TaskSetMeta, TaskSetMetaAdmin)

    except Exception, e:
        print e
        pass

### Domain

class DomainAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Domain._meta.fields])
admin.site.register(Domain, DomainAdmin)

### Alias

class AliasAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Alias._meta.fields])
admin.site.register(Alias, AliasAdmin)

#################################################

class SiteAdminForm(ModelForm):
    class Meta:
        model = Site

class SiteAdmin(admin.ModelAdmin):
    form = SiteAdminForm
    list_display = tuple([f.name for f in Site._meta.fields])

admin.site.register(Site, SiteAdmin)

### Targetting

class TargettingInline(generic.GenericTabularInline):
    model = Targetting
    ct_field = 'mediator_content_type'
    ct_fk_field = 'mediator_object_id'

class TargettingAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Targetting._meta.fields])
admin.site.register(Targetting, TargettingAdmin)

### Circle

class CirlceAdminMembershipForset(BaseInlineFormSet):

    def get_queryset(self):
        if not hasattr(self, '_queryset'):
            qs = super(CirlceAdminMembershipForset,
                       self).get_queryset().filter(is_admin=True)
            self._queryset = qs
        return self._queryset

class CircleAdminMembershipInline(admin.TabularInline):
#class CircleAdminMembershipInline(admin.StackedInline):
    model = Membership
    formset = CirlceAdminMembershipForset
    extra = 0
    raw_id_fields = ['member', ]
    verbose_name = _('Cicle Administrator')
    verbose_name_plural = _('Cicle Administrators')

class CircleAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Circle._meta.fields])
    inlines = [CircleAdminMembershipInline]
admin.site.register(Circle, CircleAdmin)

## Membership
class MembershipAdmin(admin.ModelAdmin):
    list_display = (
        'id', 'circle_link', 'member_link', 'user', 'is_admin',
        'is_member_active', 'is_user_active', 'is_admitted', )
    list_filter = ('circle', 'is_admin',)
    raw_id_fields = ['member', ]
    search_fields = ('member__address', 'member__user__username',)
MembershipAdmin.member_link = member_link
MembershipAdmin.circle_link = circle_link
admin.site.register(Membership, MembershipAdmin)

class MembershipInline(admin.StackedInline):
    model = Membership
    extra = 0

### Member

class MemberAdmin(admin.ModelAdmin):
    list_display = ('id', 'user_link', 'address', 'is_active', 'bounces', )
    inlines = [MembershipInline, ]
    raw_id_fields = ['user', ]
    search_fields = ('address', 'user__username',)
MemberAdmin.user_link = user_link
admin.site.register(Member, MemberAdmin)

### Publish

class PublishAdmin(admin.ModelAdmin):
#    list_display=tuple([f.name for f in Publish._meta.fields ])
    list_display = (
        'id', 'site', 'publisher', 'subject', 'text',
        'task_id', 'status', 'dt_start', 'activated_at', )

    inlines = [
        TargettingInline,
    ]
    date_hierarchy = 'dt_start'

    def save_model(self, request, obj, form, change):
        ''' Saving...

            :param request: request object to view
            :param obj: Publish instance
            :param form: Form instance
            :param change: bool
        '''
        if all(['status' in form.changed_data,
               obj.status == 'scheduled',
               any([obj.dt_start and obj.dt_start < now(),
                    obj.task_id not in [None, ""], ]),
                ]):
            #: do nothing
            return

        super(PublishAdmin, self).save_model(request, obj, form, change)
        apply_publish(obj)
admin.site.register(Publish, PublishAdmin)

### Provision
class ProvisionAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Provision._meta.fields])
    search_fields = ('prospect',)
admin.site.register(Provision, ProvisionAdmin)

### Journal

class JournalAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Journal._meta.fields])
    date_hierarchy = 'dt_created'
admin.site.register(Journal, JournalAdmin)

##############

### Template

class TemplateAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Template._meta.fields])
admin.site.register(Template, TemplateAdmin)

### Message

def send_message(modeladmin, request, queryset):
    if queryset.model is not Message:
        return

    for message in queryset.filter():
        deliver_mail(mail_obj=message)  # Sync

send_message.short_description = _('Send Message')

class MessageAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Message._meta.fields])
    date_hierarchy = 'created'
    search_fields = ('mail_message_id',)
    actions = [send_message, ]
admin.site.register(Message, MessageAdmin)

### Publication

class PublicationAdmin(admin.ModelAdmin):
    list_display = ('id', 'publish_link', 'message_link', 'message_created')
    list_filter = ('publish',)

PublicationAdmin.publish_link = publish_link
PublicationAdmin.message_link = message_link
message_created = lambda self, obj: obj.message.created
message_created.short_description = _(u"Created At")
message_created.allow_tags = True
PublicationAdmin.message_created = message_created

admin.site.register(Publication, PublicationAdmin)

#################
# rsyslog
try:
    from rsyslog import SystemeventsAdmin, SystemeventspropertiesAdmin
except:
    pass
<commit_msg>django 1.7<commit_after># -*- coding: utf-8 -*-
from django.contrib import admin
from django.contrib.contenttypes import generic
from django.conf import settings
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from django.forms import ModelForm
from django.forms.models import BaseInlineFormSet
from django.core.urlresolvers import reverse

from models import (
    Domain,
    Alias,
    Site,
    Template,
    Targetting,
    Circle,
    Member,
    Membership,
    Publish,
    Journal,
    Message,
    Provision,
    Publication,
)
from tasks import apply_publish, deliver_mail

def link_to_relation(self, obj, field=""):
    ''' relation field link
        - self : Admin
        - obj  : Model Instance
        - filed : Field Name
    '''
    if obj is None:
        return ""

    fobj = getattr(obj, field, None)
    if fobj:
        url = reverse("admin:%s_change" % fobj._meta.db_table,
                      args=[fobj.id])
        return '%s' % (url, fobj.__unicode__())

user_link = lambda self, obj: link_to_relation(self, obj, "user")
user_link.short_description = _(u"System User")
user_link.allow_tags = True

member_link = lambda self, obj: link_to_relation(self, obj, "member")
member_link.short_description = _(u"Member")
member_link.allow_tags = True

circle_link = lambda self, obj: link_to_relation(self, obj, "circle")
circle_link.short_description = _(u"Circle")
circle_link.allow_tags = True

publish_link = lambda self, obj: link_to_relation(self, obj, "publish")
publish_link.short_description = _(u"Publish")
publish_link.allow_tags = True

message_link = lambda self, obj: link_to_relation(self, obj, "message")
message_link.short_description = _(u"Message")
message_link.allow_tags = True

###

if settings.DEBUG:
    try:
        from kombu.transport.django.models import (
            Queue as KombuQueue,
            Message as KombuMessage
        )
        from djcelery.models import TaskMeta, TaskSetMeta

        ### KombuQueue
        class KombuQueueAdmin(admin.ModelAdmin):
            list_display = tuple([f.name for f in KombuQueue._meta.fields])
        admin.site.register(KombuQueue, KombuQueueAdmin)

        ### define __unicode__ to Queue class
        #
        #def __unicode__(self):
        #
        #   return self.name

        ### KombuMessage
        class KombuMessageAdmin(admin.ModelAdmin):
            list_display = tuple([f.name for f in KombuMessage._meta.fields])
        admin.site.register(KombuMessage, KombuMessageAdmin)

        ### TaskMeta
        class TaskMetaAdmin(admin.ModelAdmin):
            list_display = tuple([f.name for f in TaskMeta._meta.fields])
            list_filter = ('status',)
            date_hierarchy = 'date_done'
        admin.site.register(TaskMeta, TaskMetaAdmin)

        ### TaskSetMeta
        class TaskSetMetaAdmin(admin.ModelAdmin):
            list_display = tuple([f.name for f in TaskSetMeta._meta.fields])
        admin.site.register(TaskSetMeta, TaskSetMetaAdmin)

    except Exception, e:
        print e
        pass

### Domain

class DomainAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Domain._meta.fields])
admin.site.register(Domain, DomainAdmin)

### Alias

class AliasAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Alias._meta.fields])
admin.site.register(Alias, AliasAdmin)

#################################################

class SiteAdminForm(ModelForm):
    class Meta:
        model = Site
        exclude = []

class SiteAdmin(admin.ModelAdmin):
    form = SiteAdminForm
    list_display = tuple([f.name for f in Site._meta.fields])

admin.site.register(Site, SiteAdmin)

### Targetting

class TargettingInline(generic.GenericTabularInline):
    model = Targetting
    ct_field = 'mediator_content_type'
    ct_fk_field = 'mediator_object_id'

class TargettingAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Targetting._meta.fields])
admin.site.register(Targetting, TargettingAdmin)

### Circle

class CirlceAdminMembershipForset(BaseInlineFormSet):

    def get_queryset(self):
        if not hasattr(self, '_queryset'):
            qs = super(CirlceAdminMembershipForset,
                       self).get_queryset().filter(is_admin=True)
            self._queryset = qs
        return self._queryset

class CircleAdminMembershipInline(admin.TabularInline):
#class CircleAdminMembershipInline(admin.StackedInline):
    model = Membership
    formset = CirlceAdminMembershipForset
    extra = 0
    raw_id_fields = ['member', ]
    verbose_name = _('Cicle Administrator')
    verbose_name_plural = _('Cicle Administrators')

class CircleAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Circle._meta.fields])
    inlines = [CircleAdminMembershipInline]
admin.site.register(Circle, CircleAdmin)

## Membership
class MembershipAdmin(admin.ModelAdmin):
    list_display = (
        'id', 'circle_link', 'member_link', 'user', 'is_admin',
        'is_member_active', 'is_user_active', 'is_admitted', )
    list_filter = ('circle', 'is_admin',)
    raw_id_fields = ['member', ]
    search_fields = ('member__address', 'member__user__username',)
MembershipAdmin.member_link = member_link
MembershipAdmin.circle_link = circle_link
admin.site.register(Membership, MembershipAdmin)

class MembershipInline(admin.StackedInline):
    model = Membership
    extra = 0

### Member

class MemberAdmin(admin.ModelAdmin):
    list_display = ('id', 'user_link', 'address', 'is_active', 'bounces', )
    inlines = [MembershipInline, ]
    raw_id_fields = ['user', ]
    search_fields = ('address', 'user__username',)
MemberAdmin.user_link = user_link
admin.site.register(Member, MemberAdmin)

### Publish

class PublishAdmin(admin.ModelAdmin):
#    list_display=tuple([f.name for f in Publish._meta.fields ])
    list_display = (
        'id', 'site', 'publisher', 'subject', 'text',
        'task_id', 'status', 'dt_start', 'activated_at', )

    inlines = [
        TargettingInline,
    ]
    date_hierarchy = 'dt_start'

    def save_model(self, request, obj, form, change):
        ''' Saving...

            :param request: request object to view
            :param obj: Publish instance
            :param form: Form instance
            :param change: bool
        '''
        if all(['status' in form.changed_data,
               obj.status == 'scheduled',
               any([obj.dt_start and obj.dt_start < now(),
                    obj.task_id not in [None, ""], ]),
                ]):
            #: do nothing
            return

        super(PublishAdmin, self).save_model(request, obj, form, change)
        apply_publish(obj)
admin.site.register(Publish, PublishAdmin)

### Provision
class ProvisionAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Provision._meta.fields])
    search_fields = ('prospect',)
admin.site.register(Provision, ProvisionAdmin)

### Journal

class JournalAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Journal._meta.fields])
    date_hierarchy = 'dt_created'
admin.site.register(Journal, JournalAdmin)

##############

### Template

class TemplateAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Template._meta.fields])
admin.site.register(Template, TemplateAdmin)

### Message

def send_message(modeladmin, request, queryset):
    if queryset.model is not Message:
        return

    for message in queryset.filter():
        deliver_mail(mail_obj=message)  # Sync

send_message.short_description = _('Send Message')

class MessageAdmin(admin.ModelAdmin):
    list_display = tuple([f.name for f in Message._meta.fields])
    date_hierarchy = 'created'
    search_fields = ('mail_message_id',)
    actions = [send_message, ]
admin.site.register(Message, MessageAdmin)

### Publication

class PublicationAdmin(admin.ModelAdmin):
    list_display = ('id', 'publish_link', 'message_link', 'message_created')
    list_filter = ('publish',)

PublicationAdmin.publish_link = publish_link
PublicationAdmin.message_link = message_link
message_created = lambda self, obj: obj.message.created
message_created.short_description = _(u"Created At")
message_created.allow_tags = True
PublicationAdmin.message_created = message_created

admin.site.register(Publication, PublicationAdmin)

#################
# rsyslog
try:
    from rsyslog import SystemeventsAdmin, SystemeventspropertiesAdmin
except:
    pass
<|endoftext|>


<commit_before>"""Fetch Transitland Feed Registry feeds."""
import argparse
import os

import transitland.registry

import util

def run():
  parser = util.default_parser('Fetch Transitland Feed Registry GTFS feeds')
  parser.add_argument(
    '--noverify',
    action='store_true',
    help='Do not verify downloaded feed checksums',
  )
  args = parser.parse_args()
  #
  r = transitland.registry.FeedRegistry(path=args.registry)
  feedids = args.feedids
  if args.all:
    feedids = sorted(r.feeds())
  if len(feedids) == 0:
    raise Exception("No feeds specified! Try --all")
  #
  for feedid in feedids:
    print feedid
    feed = r.feed(feedid)
    filename = os.path.join(args.workdir, '%s.zip'%feed.onestop())
    feed.download(filename=filename, verify=(not args.noverify))

if __name__ == "__main__":
  run()<commit_msg>Better check of local data cache<commit_after>"""Fetch Transitland Feed Registry feeds."""
import argparse
import os

import transitland.registry

import util

def run():
  parser = util.default_parser('Fetch Transitland Feed Registry GTFS feeds')
  args = parser.parse_args()

  # Registry
  r = transitland.registry.FeedRegistry(path=args.registry)

  # Download feeds
  newfeeds = []
  feedids = args.feedids or r.feeds()
  for feedid in feedids:
    print "===== Feed: %s ====="%feedid
    feed = r.feed(feedid)
    filename = os.path.join(args.workdir, '%s.zip'%feed.onestop())
    if feed.verify_sha1(filename):
      print "Cached"
    else:
      print "Downloading: %s -> %s"%(feed.url(), filename)
      feed.download(filename, verify=False)
      newfeeds.append(feedid)
    if not feed.verify_sha1(filename):
      print "Warning: Incorrect SHA1 checksum."

  return newfeeds

if __name__ == "__main__":
  run()<|endoftext|>