<commit_before>"""
Stock database model definitions
"""

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ValidationError
from django.urls import reverse

from django.db import models, transaction
from django.core.validators import MinValueValidator
from django.contrib.auth.models import User
from django.db.models.signals import pre_delete
from django.dispatch import receiver

from datetime import datetime
from InvenTree import helpers

from InvenTree.models import InvenTreeTree

from part.models import Part

class StockLocation(InvenTreeTree):
    """ Organization tree for StockItem objects
    A "StockLocation" can be considered a warehouse, or storage location
    Stock locations can be heirarchical as required
    """

    def get_absolute_url(self):
        return reverse('stock-location-detail', kwargs={'pk': self.id})

    def has_items(self):
        return self.stock_items.count() > 0

    def format_barcode(self):
        """ Return a JSON string for formatting a barcode for this StockLocation object """

        return helpers.MakeBarcode(
            'StockLocation',
            self.id,
            reverse('api-location-detail', kwargs={'pk': self.id}),
            {
                'name': self.name,
            }
        )

    @property
    def stock_item_count(self):
        """ Return the number of StockItem objects which live in or under this category
        """

        return len(StockItem.objects.filter(location__in=self.getUniqueChildren()))

    @property
    def item_count(self):

        return self.stock_item_count

@receiver(pre_delete, sender=StockLocation, dispatch_uid='stocklocation_delete_log')
def before_delete_stock_location(sender, instance, using, **kwargs):

    # Update each part in the stock location
    for item in instance.stock_items.all():
        item.location = instance.parent
        item.save()

    # Update each child category
    for child in instance.children.all():
        child.parent = instance.parent
        child.save()

class StockItem(models.Model):
    """
    A StockItem object represents a quantity of physical instances of a part.

    Attributes:
        part: Link to the master abstract part that this StockItem is an instance of
        supplier_part: Link to a specific SupplierPart (optional)
        location: Where this StockItem is located
        quantity: Number of stocked units
        batch: Batch number for this StockItem
        URL: Optional URL to link to external resource
        updated: Date that this stock item was last updated (auto)
        stocktake_date: Date of last stocktake for this item
        stocktake_user: User that performed the most recent stocktake
        review_needed: Flag if StockItem needs review
        delete_on_deplete: If True, StockItem will be deleted when the stock level gets to zero
        status: Status of this StockItem (ref: ITEM_STATUS_CODES)
        notes: Extra notes field
        infinite: If True this StockItem can never be exhausted
    """

    def save(self, *args, **kwargs):
        if not self.pk:
            add_note = True
        else:
            add_note = False

        super(StockItem, self).save(*args, **kwargs)

        if add_note:
            # This StockItem is being saved for the first time
            self.addTransactionNote(
                'Created stock item',
                None,
                notes="Created new stock item for part '{p}'".format(p=str(self.part)),
                system=True
            )

    def clean(self):
        """ Validate the StockItem object (separate to field validation)

        The following validation checks are performed:

        - The 'part' and 'supplier_part.part' fields cannot point to the same Part object
        - The 'part' does not belong to itself
        - Quantity must be 1 if the StockItem has a serial number
        """

        # The 'supplier_part' field must point to the same part!
        try:
            if self.supplier_part is not None:
                if not self.supplier_part.part == self.part:
                    raise ValidationError({'supplier_part': _("Part type ('{pf}') must be {pe}").format(
                                           pf=str(self.supplier_part.part),
                                           pe=str(self.part))
                                           })

            if self.part is not None:
                if self.part.trackable and not self.serial:
                    raise ValidationError({
                        'serial': _('Serial number must be set for trackable items')
                    })

        except Part.DoesNotExist:
            # This gets thrown if self.supplier_part is null
            # TODO - Find a test than can be perfomed...
            pass

        if self.belongs_to and self.belongs_to.pk == self.pk:
            raise ValidationError({
                'belongs_to': _('Item cannot belong to itself')
            })

        # Serial number cannot be set for items with quantity greater than 1
        if not self.quantity == 1 and self.serial:
            raise ValidationError({
                'quantity': _("Quantity must be set to 1 for item with a serial number"),
                'serial': _("Serial number cannot be set if quantity > 1")
            })

    def get_absolute_url(self):
        return reverse('stock-item-detail', kwargs={'pk': self.id})

    class Meta:
        unique_together = [
            ('part', 'serial'),
        ]

    def format_barcode(self):
        """ Return a JSON string for formatting a barcode for this StockItem.
        Can be used to perform lookup of a stockitem using barcode

        Contains the following data:

        { type: 'StockItem', stock_id: <pk>, part_id: <part_pk> }

        Voltagile data (e.g. stock quantity) should be looked up using the InvenTree API (as it may change)
        """

        return helpers.MakeBarcode(
            'StockItem',
            self.id,
            reverse('api-stock-detail', kwargs={'pk': self.id}),
            {
                'part_id': self.part.id,
                'part_name': self.part.name
            }
        )

    part = models.ForeignKey('part.Part', on_delete=models.CASCADE, related_name='locations', help_text='Base part')

    supplier_part = models.ForeignKey('part.SupplierPart', blank=True, null=True, on_delete=models.SET_NULL,
                                      help_text='Select a matching supplier part for this stock item')

    location = models.ForeignKey(StockLocation, on_delete=models.DO_NOTHING,
                                 related_name='stock_items', blank=True, null=True,
                                 help_text='Where is this stock item located?')

    belongs_to = models.ForeignKey('self', on_delete=models.DO_NOTHING,
                                   related_name='owned_parts', blank=True, null=True,
                                   help_text='Is this item installed in another item?')

    customer = models.ForeignKey('company.Company', on_delete=models.SET_NULL,
                                 related_name='stockitems', blank=True, null=True,
                                 help_text='Item assigned to customer?')

    serial = models.PositiveIntegerField(blank=True, null=True,
                                         help_text='Serial number for this item')

    URL = models.URLField(max_length=125, blank=True)

    batch = models.CharField(max_length=100, blank=True, null=True,
                             help_text='Batch code for this stock item')

    quantity = models.PositiveIntegerField(validators=[MinValueValidator(0)], default=1)

    updated = models.DateField(auto_now=True)

    # last time the stock was checked / counted
    stocktake_date = models.DateField(blank=True, null=True)

    stocktake_user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True,
                                       related_name='stocktake_stock')

    review_needed = models.BooleanField(default=False)

    delete_on_deplete = models.BooleanField(default=True, help_text='Delete this Stock Item when stock is depleted')

    ITEM_OK = 10
    ITEM_ATTENTION = 50
    ITEM_DAMAGED = 55
    ITEM_DESTROYED = 60

    ITEM_STATUS_CODES = {
        ITEM_OK: _("OK"),
        ITEM_ATTENTION: _("Attention needed"),
        ITEM_DAMAGED: _("Damaged"),
        ITEM_DESTROYED: _("Destroyed")
    }

    status = models.PositiveIntegerField(
        default=ITEM_OK,
        choices=ITEM_STATUS_CODES.items(),
        validators=[MinValueValidator(0)])

    notes = models.CharField(max_length=250, blank=True, help_text='Stock Item Notes')

    # If stock item is incoming, an (optional) ETA field
    # expected_arrival = models.DateField(null=True, blank=True)

    infinite = models.BooleanField(default=False)

    def can_delete(self):
        # TODO - Return FALSE if this item cannot be deleted!
        return True

    @property
    def in_stock(self):

        if self.belongs_to or self.customer:
            return False

        return True

    @property
    def has_tracking_info(self):
        return self.tracking_info.count() > 0

    def addTransactionNote(self, title, user, notes='', system=True):
        """ Generation a stock transaction note for this item.

        Brief automated note detailing a movement or quantity change.
        """
        track = StockItemTracking.objects.create(
            item=self,
            title=title,
            user=user,
            quantity=self.quantity,
            date=datetime.now().date(),
            notes=notes,
            system=system
        )

        track.save()

    @transaction.atomic
    def move(self, location, notes, user):

        if location is None:
            # TODO - Raise appropriate error (cannot move to blank location)
            return False
        elif self.location and (location.pk == self.location.pk):
            # TODO - Raise appropriate error (cannot move to same location)
            return False

        msg = "Moved to {loc}".format(loc=str(location))

        if self.location:
            msg += " (from {loc})".format(loc=str(self.location))

        self.location = location

        self.addTransactionNote(msg,
                                user,
                                notes=notes,
                                system=True)

        self.save()

        return True

    @transaction.atomic
    def updateQuantity(self, quantity):
        """ Update stock quantity for this item.

        If the quantity has reached zero, this StockItem will be deleted.

        Returns:
            - True if the quantity was saved
            - False if the StockItem was deleted
        """

        if quantity < 0:
            quantity = 0

        self.quantity = quantity

        if quantity <= 0 and self.delete_on_deplete:
            self.delete()
            return False
        else:
            self.save()
            return True

    @transaction.atomic
    def stocktake(self, count, user, notes=''):
        """ Perform item stocktake.
        When the quantity of an item is counted,
        record the date of stocktake
        """

        count = int(count)

        if count < 0 or self.infinite:
            return False

        self.stocktake_date = datetime.now().date()
        self.stocktake_user = user

        if self.updateQuantity(count):

            self.addTransactionNote('Stocktake - counted {n} items'.format(n=count),
                                    user,
                                    notes=notes,
                                    system=True)

        return True

    @transaction.atomic
    def add_stock(self, quantity, user, notes=''):
        """ Add items to stock
        This function can be called by initiating a ProjectRun,
        or by manually adding the items to the stock location
        """

        quantity = int(quantity)

        # Ignore amounts that do not make sense
        if quantity <= 0 or self.infinite:
            return False

        if self.updateQuantity(self.quantity + quantity):

            self.addTransactionNote('Added {n} items to stock'.format(n=quantity),
                                    user,
                                    notes=notes,
                                    system=True)

        return True

    @transaction.atomic
    def take_stock(self, quantity, user, notes=''):
        """ Remove items from stock
        """

        if self.quantity == 0:
            return False

        quantity = int(quantity)

        if quantity <= 0 or self.infinite:
            return False

        if self.updateQuantity(self.quantity - quantity):

            self.addTransactionNote('Removed {n} items from stock'.format(n=quantity),
                                    user,
                                    notes=notes,
                                    system=True)

        return True

    def __str__(self):
        s = '{n} x {part}'.format(
            n=self.quantity,
            part=self.part.name)

        if self.location:
            s += ' @ {loc}'.format(loc=self.location.name)

        return s

class StockItemTracking(models.Model):
    """ Stock tracking entry - breacrumb for keeping track of automated stock transactions

    Attributes:
        item: Link to StockItem
        date: Date that this tracking info was created
        title: Title of this tracking info (generated by system)
        notes: Associated notes (input by user)
        user: The user associated with this tracking info
        quantity: The StockItem quantity at this point in time
    """

    def get_absolute_url(self):
        return '/stock/track/{pk}'.format(pk=self.id)
        # return reverse('stock-tracking-detail', kwargs={'pk': self.id})

    item = models.ForeignKey(StockItem, on_delete=models.CASCADE,
                             related_name='tracking_info')

    date = models.DateTimeField(auto_now_add=True, editable=False)

    title = models.CharField(blank=False, max_length=250)

    notes = models.TextField(blank=True)

    user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)

    system = models.BooleanField(default=False)

    quantity = models.PositiveIntegerField(validators=[MinValueValidator(0)], default=1)

    # TODO
    # image = models.ImageField(upload_to=func, max_length=255, null=True, blank=True)

    # TODO
    # file = models.FileField()
<commit_msg>Added function to split stock<commit_after>"""
Stock database model definitions
"""

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ValidationError
from django.urls import reverse

from django.db import models, transaction
from django.core.validators import MinValueValidator
from django.contrib.auth.models import User
from django.db.models.signals import pre_delete
from django.dispatch import receiver

from datetime import datetime
from InvenTree import helpers

from InvenTree.models import InvenTreeTree

from part.models import Part

class StockLocation(InvenTreeTree):
    """ Organization tree for StockItem objects
    A "StockLocation" can be considered a warehouse, or storage location
    Stock locations can be heirarchical as required
    """

    def get_absolute_url(self):
        return reverse('stock-location-detail', kwargs={'pk': self.id})

    def has_items(self):
        return self.stock_items.count() > 0

    def format_barcode(self):
        """ Return a JSON string for formatting a barcode for this StockLocation object """

        return helpers.MakeBarcode(
            'StockLocation',
            self.id,
            reverse('api-location-detail', kwargs={'pk': self.id}),
            {
                'name': self.name,
            }
        )

    @property
    def stock_item_count(self):
        """ Return the number of StockItem objects which live in or under this category
        """

        return len(StockItem.objects.filter(location__in=self.getUniqueChildren()))

    @property
    def item_count(self):

        return self.stock_item_count

@receiver(pre_delete, sender=StockLocation, dispatch_uid='stocklocation_delete_log')
def before_delete_stock_location(sender, instance, using, **kwargs):

    # Update each part in the stock location
    for item in instance.stock_items.all():
        item.location = instance.parent
        item.save()

    # Update each child category
    for child in instance.children.all():
        child.parent = instance.parent
        child.save()

class StockItem(models.Model):
    """
    A StockItem object represents a quantity of physical instances of a part.

    Attributes:
        part: Link to the master abstract part that this StockItem is an instance of
        supplier_part: Link to a specific SupplierPart (optional)
        location: Where this StockItem is located
        quantity: Number of stocked units
        batch: Batch number for this StockItem
        URL: Optional URL to link to external resource
        updated: Date that this stock item was last updated (auto)
        stocktake_date: Date of last stocktake for this item
        stocktake_user: User that performed the most recent stocktake
        review_needed: Flag if StockItem needs review
        delete_on_deplete: If True, StockItem will be deleted when the stock level gets to zero
        status: Status of this StockItem (ref: ITEM_STATUS_CODES)
        notes: Extra notes field
        infinite: If True this StockItem can never be exhausted
    """

    def save(self, *args, **kwargs):
        if not self.pk:
            add_note = True
        else:
            add_note = False

        super(StockItem, self).save(*args, **kwargs)

        if add_note:
            # This StockItem is being saved for the first time
            self.addTransactionNote(
                'Created stock item',
                None,
                notes="Created new stock item for part '{p}'".format(p=str(self.part)),
                system=True
            )

    def clean(self):
        """ Validate the StockItem object (separate to field validation)

        The following validation checks are performed:

        - The 'part' and 'supplier_part.part' fields cannot point to the same Part object
        - The 'part' does not belong to itself
        - Quantity must be 1 if the StockItem has a serial number
        """

        # The 'supplier_part' field must point to the same part!
        try:
            if self.supplier_part is not None:
                if not self.supplier_part.part == self.part:
                    raise ValidationError({'supplier_part': _("Part type ('{pf}') must be {pe}").format(
                                           pf=str(self.supplier_part.part),
                                           pe=str(self.part))
                                           })

            if self.part is not None:
                if self.part.trackable and not self.serial:
                    raise ValidationError({
                        'serial': _('Serial number must be set for trackable items')
                    })

        except Part.DoesNotExist:
            # This gets thrown if self.supplier_part is null
            # TODO - Find a test than can be perfomed...
            pass

        if self.belongs_to and self.belongs_to.pk == self.pk:
            raise ValidationError({
                'belongs_to': _('Item cannot belong to itself')
            })

        # Serial number cannot be set for items with quantity greater than 1
        if not self.quantity == 1 and self.serial:
            raise ValidationError({
                'quantity': _("Quantity must be set to 1 for item with a serial number"),
                'serial': _("Serial number cannot be set if quantity > 1")
            })

    def get_absolute_url(self):
        return reverse('stock-item-detail', kwargs={'pk': self.id})

    class Meta:
        unique_together = [
            ('part', 'serial'),
        ]

    def format_barcode(self):
        """ Return a JSON string for formatting a barcode for this StockItem.
        Can be used to perform lookup of a stockitem using barcode

        Contains the following data:

        { type: 'StockItem', stock_id: <pk>, part_id: <part_pk> }

        Voltagile data (e.g. stock quantity) should be looked up using the InvenTree API (as it may change)
        """

        return helpers.MakeBarcode(
            'StockItem',
            self.id,
            reverse('api-stock-detail', kwargs={'pk': self.id}),
            {
                'part_id': self.part.id,
                'part_name': self.part.name
            }
        )

    part = models.ForeignKey('part.Part', on_delete=models.CASCADE, related_name='locations', help_text='Base part')

    supplier_part = models.ForeignKey('part.SupplierPart', blank=True, null=True, on_delete=models.SET_NULL,
                                      help_text='Select a matching supplier part for this stock item')

    location = models.ForeignKey(StockLocation, on_delete=models.DO_NOTHING,
                                 related_name='stock_items', blank=True, null=True,
                                 help_text='Where is this stock item located?')

    belongs_to = models.ForeignKey('self', on_delete=models.DO_NOTHING,
                                   related_name='owned_parts', blank=True, null=True,
                                   help_text='Is this item installed in another item?')

    customer = models.ForeignKey('company.Company', on_delete=models.SET_NULL,
                                 related_name='stockitems', blank=True, null=True,
                                 help_text='Item assigned to customer?')

    serial = models.PositiveIntegerField(blank=True, null=True,
                                         help_text='Serial number for this item')

    URL = models.URLField(max_length=125, blank=True)

    batch = models.CharField(max_length=100, blank=True, null=True,
                             help_text='Batch code for this stock item')

    quantity = models.PositiveIntegerField(validators=[MinValueValidator(0)], default=1)

    updated = models.DateField(auto_now=True)

    # last time the stock was checked / counted
    stocktake_date = models.DateField(blank=True, null=True)

    stocktake_user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True,
                                       related_name='stocktake_stock')

    review_needed = models.BooleanField(default=False)

    delete_on_deplete = models.BooleanField(default=True, help_text='Delete this Stock Item when stock is depleted')

    ITEM_OK = 10
    ITEM_ATTENTION = 50
    ITEM_DAMAGED = 55
    ITEM_DESTROYED = 60

    ITEM_STATUS_CODES = {
        ITEM_OK: _("OK"),
        ITEM_ATTENTION: _("Attention needed"),
        ITEM_DAMAGED: _("Damaged"),
        ITEM_DESTROYED: _("Destroyed")
    }

    status = models.PositiveIntegerField(
        default=ITEM_OK,
        choices=ITEM_STATUS_CODES.items(),
        validators=[MinValueValidator(0)])

    notes = models.CharField(max_length=250, blank=True, help_text='Stock Item Notes')

    # If stock item is incoming, an (optional) ETA field
    # expected_arrival = models.DateField(null=True, blank=True)

    infinite = models.BooleanField(default=False)

    def can_delete(self):
        # TODO - Return FALSE if this item cannot be deleted!
        return True

    @property
    def in_stock(self):

        if self.belongs_to or self.customer:
            return False

        return True

    @property
    def has_tracking_info(self):
        return self.tracking_info.count() > 0

    def addTransactionNote(self, title, user, notes='', system=True):
        """ Generation a stock transaction note for this item.

        Brief automated note detailing a movement or quantity change.
        """
        track = StockItemTracking.objects.create(
            item=self,
            title=title,
            user=user,
            quantity=self.quantity,
            date=datetime.now().date(),
            notes=notes,
            system=system
        )

        track.save()

    @transaction.atomic
    def splitStock(self, quantity, user):
        """ Split this stock item into two items, in the same location.
        Stock tracking notes for this StockItem will be duplicated,
        and added to the new StockItem.

        Args:
            quantity: Number of stock items to remove from this entity, and pass to the next

        Notes:
            The provided quantity will be subtracted from this item and given to the new one.
            The new item will have a different StockItem ID, while this will remain the same.
        """

        # Doesn't make sense for a zero quantity
        if quantity <= 0:
            return

        # Also doesn't make sense to split the full amount
        if quantity >= self.quantity:
            return

        # Create a new StockItem object, duplicating relevant fields
        new_stock = StockItem.objects.create(
            part=self.part,
            quantity=quantity,
            supplier_part=self.supplier_part,
            location=self.location,
            batch=self.batch,
            delete_on_deplete=self.delete_on_deplete
        )

        new_stock.save()

        # Add a new tracking item for the new stock item
        new_stock.addTransactionNote(
            "Split from existing stock",
            user,
            "Split {n} from existing stock item".format(n=quantity))

        # Remove the specified quantity from THIS stock item
        self.take_stock(quantity, user, 'Split {n} items into new stock item'.format(n=quantity))

        if location is None:
            # TODO - Raise appropriate error (cannot move to blank location)
            return False
        elif self.location and (location.pk == self.location.pk):
            # TODO - Raise appropriate error (cannot move to same location)
            return False

        msg = "Moved to {loc}".format(loc=str(location))

        if self.location:
            msg += " (from {loc})".format(loc=str(self.location))

        self.location = location

        self.addTransactionNote(msg,
                                user,
                                notes=notes,
                                system=True)

        self.save()

        return True

    @transaction.atomic
    def updateQuantity(self, quantity):
        """ Update stock quantity for this item.

        If the quantity has reached zero, this StockItem will be deleted.

        Returns:
            - True if the quantity was saved
            - False if the StockItem was deleted
        """

        if quantity < 0:
            quantity = 0

        self.quantity = quantity

        if quantity <= 0 and self.delete_on_deplete:
            self.delete()
            return False
        else:
            self.save()
            return True

    @transaction.atomic
    def stocktake(self, count, user, notes=''):
        """ Perform item stocktake.
        When the quantity of an item is counted,
        record the date of stocktake
        """

        count = int(count)

        if count < 0 or self.infinite:
            return False

        self.stocktake_date = datetime.now().date()
        self.stocktake_user = user

        if self.updateQuantity(count):

            self.addTransactionNote('Stocktake - counted {n} items'.format(n=count),
                                    user,
                                    notes=notes,
                                    system=True)

        return True

    @transaction.atomic
    def add_stock(self, quantity, user, notes=''):
        """ Add items to stock
        This function can be called by initiating a ProjectRun,
        or by manually adding the items to the stock location
        """

        quantity = int(quantity)

        # Ignore amounts that do not make sense
        if quantity <= 0 or self.infinite:
            return False

        if self.updateQuantity(self.quantity + quantity):

            self.addTransactionNote('Added {n} items to stock'.format(n=quantity),
                                    user,
                                    notes=notes,
                                    system=True)

        return True

    @transaction.atomic
    def take_stock(self, quantity, user, notes=''):
        """ Remove items from stock
        """

        if self.quantity == 0:
            return False

        quantity = int(quantity)

        if quantity <= 0 or self.infinite:
            return False

        if self.updateQuantity(self.quantity - quantity):

            self.addTransactionNote('Removed {n} items from stock'.format(n=quantity),
                                    user,
                                    notes=notes,
                                    system=True)

        return True

    def __str__(self):
        s = '{n} x {part}'.format(
            n=self.quantity,
            part=self.part.name)

        if self.location:
            s += ' @ {loc}'.format(loc=self.location.name)

        return s

class StockItemTracking(models.Model):
    """ Stock tracking entry - breacrumb for keeping track of automated stock transactions

    Attributes:
        item: Link to StockItem
        date: Date that this tracking info was created
        title: Title of this tracking info (generated by system)
        notes: Associated notes (input by user)
        user: The user associated with this tracking info
        quantity: The StockItem quantity at this point in time
    """

    def get_absolute_url(self):
        return '/stock/track/{pk}'.format(pk=self.id)
        # return reverse('stock-tracking-detail', kwargs={'pk': self.id})

    item = models.ForeignKey(StockItem, on_delete=models.CASCADE,
                             related_name='tracking_info')

    date = models.DateTimeField(auto_now_add=True, editable=False)

    title = models.CharField(blank=False, max_length=250)

    notes = models.TextField(blank=True)

    user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)

    system = models.BooleanField(default=False)

    quantity = models.PositiveIntegerField(validators=[MinValueValidator(0)], default=1)

    # TODO
    # image = models.ImageField(upload_to=func, max_length=255, null=True, blank=True)

    # TODO
    # file = models.FileField()
<|endoftext|>


<commit_before>from sympy import *
from sympy.specfun.factorials import *

x = Symbol('x')
y = Symbol('y')
z = Symbol('z')

fs = factorial_simplify
fac = factorial

def test_factorial1():
    assert [fac(t) for t in [0,1,2,3,4]] == [1,1,2,6,24]
    assert (fac(-1) == oo) == True
    assert fac(Rational(1,2)) == Rational(1,2)*sqrt(pi)
    assert fac(Rational(3,2)) == Rational(3,4)*sqrt(pi)
    assert fac(Rational(5,2)) == Rational(15,8)*sqrt(pi)
    assert fac(Rational(-1,2)) == sqrt(pi)
    assert fac(Rational(-3,2)) == -2*sqrt(pi)
    assert fac(Rational(-5,2)) == Rational(4,3)*sqrt(pi)
    assert fac(Rational(-17,2)) == Rational(256,2027025)*sqrt(pi)

def test_factorial_evalf():
    def relcmp(a,b):
        from operator import abs    # workaround for abs vs sympy.abs conflict
        return abs(a-b)/abs(a)
    for i in range(20):
        assert relcmp(unfac(i).evalf(), fac(i)) < Real(1e-10)
    for i in range(-7, 7, 2):
        x = Rational(i)/2
        assert relcmp(unfac(x).evalf(), fac(x).evalf()) < Real(1e-10)
    assert relcmp(unfac(165).evalf(), fac(165)) < Real(1e-10)
    assert relcmp(fac(-0.75).evalf(), 3.6256099082219083) < Real(1e-10)
    assert relcmp((1-fac(1e-8).evalf())*10**8, 0.5772157) < Real(1e-5)
    assert relcmp((fac(-1e-8).evalf()-1)*10**8, 0.5772157) < Real(1e-5)
    #re, im = fac(7+8*I).evalf().as_real_imag()
    #assert relcmp(re, 1.84428481562553) < Real(1e-10)
    #assert relcmp(im, -125.96060801751909) < Real(1e-10)

def test_multifactorials():
    # OEIS: A006882
    assert [factorial(n, 2) for n in range(10)] == [1, 1, 2, 3, 8, 15, 48, 105, 384, 945]

    assert (factorial(-2, 2) == oo) == True
    assert (factorial(-4, 2) == oo) == True
    assert factorial(-1, 2) == 1
    assert factorial(-3, 2) == -1
    assert factorial(-7, 2) == Rational(-1,15)
    assert factorial(-9, 2) == Rational(1,105)
    #assert latex(factorial2(x, evaluate=False)) == "$x!!$"
    #assert latex(factorial2(-4, evaluate=False)) == "$(-4)!!$"
    #assert latex(factorial2(-x, evaluate=False)) == "$(- x)!!$"

    # OEIS: A007661
    assert [factorial(n, 3) for n in range(10)] == [1, 1, 2, 3, 4, 10, 18, 28, 80, 162]
    # OEIS: A007662
    assert [factorial(n, 4) for n in range(10)] == [1, 1, 2, 3, 4, 5, 12, 21, 32, 45]

def test_factorial_simplify():
    assert fs(fac(x+5)/fac(x+5)) == 1
    assert fs(fac(x+1)/fac(x)) == 1+x
    assert fs(fac(x+2)/fac(x)) == (1+x)*(2+x)
    assert fs(fac(x+3)/fac(x)) == (1+x)*(2+x)*(3+x)
    assert fs(fac(x-1)/fac(x)) == (1/x)
    assert fs(fac(x-2)/fac(x)) == 1/(x*(-1+x))
    assert fs(fac(x-3)/fac(x)) == 1/(x*(-1+x)*(-2+x))
    assert fs(fac(x)*(x+1)*(x+2)) == fac(x+2)
    assert fs(fac(x)/x/(x-1)) == fac(x-2)
    assert fs(x*(x-1)/fac(x)) == 1/fac(x-2)
    assert fs((1/(x+1))/fac(x)) == 1/fac(x+1)
    assert fs(fac(x)*fac(y-2)*fac(z+2)/fac(z)/fac(y+1)) == fac(x)*(z+1)*(z+2)/(y-1)/y/(y+1)
    assert fs(fac(x)*fac(y+1)*fac(z+2)/fac(z)/fac(y-2)) == fac(x)*(z+1)*(z+2)*(y-1)*y*(y+1)

def test_rising_falling():
    assert rising_factorial(x, 0) == 1
    assert rising_factorial(x, 1) == x
    assert rising_factorial(x, 2) == x*(x+1)
    assert rising_factorial(x, 3) == x*(x+1)*(x+2)
    assert falling_factorial(x, 0) == 1
    assert falling_factorial(x, 1) == x
    assert falling_factorial(x, 2) == x*(x-1)
    assert falling_factorial(x, 3) == x*(x-1)*(x-2)
    assert rising_factorial(1, x) == fac(x)
    assert falling_factorial(1, x) == 1/fac(1-x)
    assert falling_factorial(15, 8) == 259459200
    assert falling_factorial(-3,4) == 360
    assert falling_factorial(3,-4) == Rational(1,840)
    assert rising_factorial(15, 8) == 12893126400
    assert rising_factorial(-3,4) == 0
    #n = Symbol('n')
    #assert latex(rising_factorial(x, n, evaluate=False)) == "${(x)}^{(n)}$"
    #assert latex(falling_factorial(x, n, evaluate=False)) == "${(x)}_{(n)}$"

def test_binomial2():
    assert binomial2(x, 0) == 1
    assert binomial2(x, x) == 1
    assert binomial2(0, 0) == 1
    assert binomial2(0, 1) == 0
    assert binomial2(0, x) == sin(pi*x)/(pi*x)
    assert binomial2(x, 1) == x
    assert binomial2(x, 2) == Rational(1,2)*x*(x-1)
    assert binomial2(x, 3) == Rational(1,6)*x*(x-1)*(x-2)
    assert [binomial2(4,k) for k in range(5)] == [1,4,6,4,1]
    assert [binomial2(5,k) for k in range(6)] == [1,5,10,10,5,1]
    assert sum(binomial2(20, k) for k in range(21)) == 2**20
    assert binomial2(10**20, 10**20 - 2) == \
        4999999999999999999950000000000000000000
    #assert latex(binomial(8,3,evaluate=False)) == r"${{8}\choose{3}}$"

def test_gamma():
    assert gamma(0) == zoo
    assert gamma(1) == 1
    assert gamma(2) == 1
    assert gamma(3) == 2
    assert gamma(Rational(1,2)) == sqrt(pi)
    #assert latex(gamma(3+x)) == "$\Gamma(3+x)$"
    assert uppergamma(4,0) == 6
    assert uppergamma(3,oo) == 0
    assert lowergamma(1,x) + uppergamma(1,x) == gamma(1)
    assert lowergamma(5,x) + uppergamma(5,x) == gamma(5)

def test_derivatives():
    x = Symbol('x')
    from sympy.functions import polygamma
    assert gamma(4*x).diff(x) == 4*gamma(4*x)*polygamma(0, 4*x)
    assert fac(4*x).diff(x) == 4*gamma(1+4*x)*polygamma(0, 1+4*x)
    assert log(gamma(x)).diff(x, 5) == polygamma(4, x)
    assert fac(x).diff(x).subs(x, 0) == -EulerGamma
    assert fac(x).diff(x).subs(x, 4) == 24*(Rational(25, 12)-EulerGamma)

def test_binomial3():
    assert binomial2(15,8) == 6435
    assert [binomial2(0,k) for k in range(1)] == [1]
    assert [binomial2(1,k) for k in range(2)] == [1, 1]
    assert [binomial2(2,k) for k in range(3)] == [1, 2, 1]
    assert [binomial2(3,k) for k in range(4)] == [1, 3, 3, 1]
    assert binomial2(Rational(5,4), 3) == -Integer(5)/128
    x = Symbol('x')
    assert binomial2(x, 3) == x*(1 - x)*(2 - x)/6
<commit_msg>Fixes the test_factorials.py test by using explicit imports.<commit_after>from sympy import oo, Symbol, Rational, Integer, gamma, log, \
        EulerGamma, zoo, sqrt, pi, uppergamma, lowergamma, sin, Real
from sympy.specfun.factorials import factorial_simplify, binomial2, \
        rising_factorial, falling_factorial, unfac, factorial

x = Symbol('x')
y = Symbol('y')
z = Symbol('z')

fs = factorial_simplify
fac = factorial

def test_factorial1():
    assert [fac(t) for t in [0,1,2,3,4]] == [1,1,2,6,24]
    assert (fac(-1) == oo) == True
    assert fac(Rational(1,2)) == Rational(1,2)*sqrt(pi)
    assert fac(Rational(3,2)) == Rational(3,4)*sqrt(pi)
    assert fac(Rational(5,2)) == Rational(15,8)*sqrt(pi)
    assert fac(Rational(-1,2)) == sqrt(pi)
    assert fac(Rational(-3,2)) == -2*sqrt(pi)
    assert fac(Rational(-5,2)) == Rational(4,3)*sqrt(pi)
    assert fac(Rational(-17,2)) == Rational(256,2027025)*sqrt(pi)

def test_factorial_evalf():
    def relcmp(a,b):
        from operator import abs    # workaround for abs vs sympy.abs conflict
        return abs(a-b)/abs(a)
    for i in range(20):
        assert relcmp(unfac(i).evalf(), fac(i)) < Real(1e-10)
    for i in range(-7, 7, 2):
        x = Rational(i)/2
        assert relcmp(unfac(x).evalf(), fac(x).evalf()) < Real(1e-10)
    assert relcmp(unfac(165).evalf(), fac(165)) < Real(1e-10)
    assert relcmp(fac(-0.75).evalf(), 3.6256099082219083) < Real(1e-10)
    assert relcmp((1-fac(1e-8).evalf())*10**8, 0.5772157) < Real(1e-5)
    assert relcmp((fac(-1e-8).evalf()-1)*10**8, 0.5772157) < Real(1e-5)
    #re, im = fac(7+8*I).evalf().as_real_imag()
    #assert relcmp(re, 1.84428481562553) < Real(1e-10)
    #assert relcmp(im, -125.96060801751909) < Real(1e-10)

def test_multifactorials():
    # OEIS: A006882
    assert [factorial(n, 2) for n in range(10)] == [1, 1, 2, 3, 8, 15, 48, 105, 384, 945]

    assert (factorial(-2, 2) == oo) == True
    assert (factorial(-4, 2) == oo) == True
    assert factorial(-1, 2) == 1
    assert factorial(-3, 2) == -1
    assert factorial(-7, 2) == Rational(-1,15)
    assert factorial(-9, 2) == Rational(1,105)
    #assert latex(factorial2(x, evaluate=False)) == "$x!!$"
    #assert latex(factorial2(-4, evaluate=False)) == "$(-4)!!$"
    #assert latex(factorial2(-x, evaluate=False)) == "$(- x)!!$"

    # OEIS: A007661
    assert [factorial(n, 3) for n in range(10)] == [1, 1, 2, 3, 4, 10, 18, 28, 80, 162]
    # OEIS: A007662
    assert [factorial(n, 4) for n in range(10)] == [1, 1, 2, 3, 4, 5, 12, 21, 32, 45]

def test_factorial_simplify():
    assert fs(fac(x+5)/fac(x+5)) == 1
    assert fs(fac(x+1)/fac(x)) == 1+x
    assert fs(fac(x+2)/fac(x)) == (1+x)*(2+x)
    assert fs(fac(x+3)/fac(x)) == (1+x)*(2+x)*(3+x)
    assert fs(fac(x-1)/fac(x)) == (1/x)
    assert fs(fac(x-2)/fac(x)) == 1/(x*(-1+x))
    assert fs(fac(x-3)/fac(x)) == 1/(x*(-1+x)*(-2+x))
    assert fs(fac(x)*(x+1)*(x+2)) == fac(x+2)
    assert fs(fac(x)/x/(x-1)) == fac(x-2)
    assert fs(x*(x-1)/fac(x)) == 1/fac(x-2)
    assert fs((1/(x+1))/fac(x)) == 1/fac(x+1)
    assert fs(fac(x)*fac(y-2)*fac(z+2)/fac(z)/fac(y+1)) == fac(x)*(z+1)*(z+2)/(y-1)/y/(y+1)
    assert fs(fac(x)*fac(y+1)*fac(z+2)/fac(z)/fac(y-2)) == fac(x)*(z+1)*(z+2)*(y-1)*y*(y+1)

def test_rising_falling():
    assert rising_factorial(x, 0) == 1
    assert rising_factorial(x, 1) == x
    assert rising_factorial(x, 2) == x*(x+1)
    assert rising_factorial(x, 3) == x*(x+1)*(x+2)
    assert falling_factorial(x, 0) == 1
    assert falling_factorial(x, 1) == x
    assert falling_factorial(x, 2) == x*(x-1)
    assert falling_factorial(x, 3) == x*(x-1)*(x-2)
    assert rising_factorial(1, x) == fac(x)
    assert falling_factorial(1, x) == 1/fac(1-x)
    assert falling_factorial(15, 8) == 259459200
    assert falling_factorial(-3,4) == 360
    assert falling_factorial(3,-4) == Rational(1,840)
    assert rising_factorial(15, 8) == 12893126400
    assert rising_factorial(-3,4) == 0
    #n = Symbol('n')
    #assert latex(rising_factorial(x, n, evaluate=False)) == "${(x)}^{(n)}$"
    #assert latex(falling_factorial(x, n, evaluate=False)) == "${(x)}_{(n)}$"

def test_binomial2():
    assert binomial2(x, 0) == 1
    assert binomial2(x, x) == 1
    assert binomial2(0, 0) == 1
    assert binomial2(0, 1) == 0
    assert binomial2(0, x) == sin(pi*x)/(pi*x)
    assert binomial2(x, 1) == x
    assert binomial2(x, 2) == Rational(1,2)*x*(x-1)
    assert binomial2(x, 3) == Rational(1,6)*x*(x-1)*(x-2)
    assert [binomial2(4,k) for k in range(5)] == [1,4,6,4,1]
    assert [binomial2(5,k) for k in range(6)] == [1,5,10,10,5,1]
    assert sum(binomial2(20, k) for k in range(21)) == 2**20
    assert binomial2(10**20, 10**20 - 2) == \
        4999999999999999999950000000000000000000
    #assert latex(binomial(8,3,evaluate=False)) == r"${{8}\choose{3}}$"

def test_gamma():
    assert gamma(0) == zoo
    assert gamma(1) == 1
    assert gamma(2) == 1
    assert gamma(3) == 2
    assert gamma(Rational(1,2)) == sqrt(pi)
    #assert latex(gamma(3+x)) == "$\Gamma(3+x)$"
    assert uppergamma(4,0) == 6
    assert uppergamma(3,oo) == 0
    assert lowergamma(1,x) + uppergamma(1,x) == gamma(1)
    assert lowergamma(5,x) + uppergamma(5,x) == gamma(5)

def test_derivatives():
    x = Symbol('x')
    from sympy.functions import polygamma
    assert gamma(4*x).diff(x) == 4*gamma(4*x)*polygamma(0, 4*x)
    assert fac(4*x).diff(x) == 4*gamma(1+4*x)*polygamma(0, 1+4*x)
    assert log(gamma(x)).diff(x, 5) == polygamma(4, x)
    assert fac(x).diff(x).subs(x, 0) == -EulerGamma
    assert fac(x).diff(x).subs(x, 4) == 24*(Rational(25, 12)-EulerGamma)

def test_binomial3():
    assert binomial2(15,8) == 6435
    assert [binomial2(0,k) for k in range(1)] == [1]
    assert [binomial2(1,k) for k in range(2)] == [1, 1]
    assert [binomial2(2,k) for k in range(3)] == [1, 2, 1]
    assert [binomial2(3,k) for k in range(4)] == [1, 3, 3, 1]
    assert binomial2(Rational(5,4), 3) == -Integer(5)/128
    x = Symbol('x')
    assert binomial2(x, 3) == x*(1 - x)*(2 - x)/6
<|endoftext|>


<commit_before>import json

from tendrl.commons import objects

class Job(objects.BaseObject):
    def __init__(self, job_id=None, payload=None,
                 status=None, errors=None, children=None,
                 locked_by=None, output=None, *args, **kwargs):
        super(Job, self).__init__(*args, **kwargs)
        self.job_id = job_id
        self.status = status
        self.payload = payload
        self.errors = errors
        self.children = children
        self.locked_by = locked_by
        self.output = output or {"_None":"_None"}
        self.value = 'queue/{0}'

    def save(self):
        super(Job, self).save()
        if "parent" in self.payload:
            # Load parent job
            _parent = Job(job_id=self.payload['parent']).load()
            _children = []

            if _parent.children:
                # Load existing child job ids
                _children = _parent.children

            _children += [self.job_id]
            _parent.children = list(set(_children))
            _parent.save()

        if self.status == "failed":
            if "parent" in self.payload::
                _parent = Job(job_id=self.payload['parent']).load()
                _msg = "\n Child job %s failed" % self.job_id
                if _parent.errors:
                    _parent.errors += _msg
                else:
                    _parent.errors = _msg
                _parent.status = "failed"
                _parent.save()

    def render(self):
        self.value = self.value.format(self.job_id)
        return super(Job, self).render()
<commit_msg>Update __init__.py<commit_after>import json

from tendrl.commons import objects

class Job(objects.BaseObject):
    def __init__(self, job_id=None, payload=None,
                 status=None, errors=None, children=None,
                 locked_by=None, output=None, *args, **kwargs):
        super(Job, self).__init__(*args, **kwargs)
        self.job_id = job_id
        self.status = status
        self.payload = payload
        self.errors = errors
        self.children = children
        self.locked_by = locked_by
        self.output = output or {"_None":"_None"}
        self.value = 'queue/{0}'

    def save(self):
        super(Job, self).save()
        if "parent" in self.payload:
            # Load parent job
            _parent = Job(job_id=self.payload['parent']).load()
            _children = []

            if _parent.children:
                # Load existing child job ids
                _children = _parent.children

            _children += [self.job_id]
            _parent.children = list(set(_children))
            _parent.save()

        if self.status == "failed":
            if "parent" in self.payload:
                _parent = Job(job_id=self.payload['parent']).load()
                _msg = "\n Child job %s failed" % self.job_id
                if _parent.errors:
                    _parent.errors += _msg
                else:
                    _parent.errors = _msg
                _parent.status = "failed"
                _parent.save()

    def render(self):
        self.value = self.value.format(self.job_id)
        return super(Job, self).render()
<|endoftext|>


<commit_before># Copyright 2015 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================

"""Momentum for TensorFlow."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from tensorflow.python.framework import ops
from tensorflow.python.ops import math_ops
from tensorflow.python.training import optimizer
from tensorflow.python.training import training_ops
from tensorflow.python.util.tf_export import tf_export

@tf_export("train.MomentumOptimizer")
class MomentumOptimizer(optimizer.Optimizer):
  """Optimizer that implements the Momentum algorithm.

  Computes (if `use_nesterov = False`):

  ```
  accumulation = momentum * accumulation + gradient
  variable -= learning_rate * accumulation
  ```

  Note that in the dense version of this algorithm, `accumulation` is updated
  and applied regardless of a gradient's value, whereas the sparse version (when
  the gradient is an `IndexedSlices`, typically because of `tf.gather` or an
  embedding) only updates variable slices and corresponding `accumulation` terms
  when that part of the variable was used in the forward pass.
  """

  def __init__(self, learning_rate, momentum,
               use_locking=False, name="Momentum", use_nesterov=False):
    """Construct a new Momentum optimizer.

    Args:
      learning_rate: A `Tensor` or a floating point value.  The learning rate.
      momentum: A `Tensor` or a floating point value.  The momentum.
      use_locking: If `True` use locks for update operations.
      name: Optional name prefix for the operations created when applying
        gradients.  Defaults to "Momentum".
      use_nesterov: If `True` use Nesterov Momentum.
        See [Sutskever et al., 2013](
        http://jmlr.org/proceedings/papers/v28/sutskever13.pdf).
        This implementation always computes gradients at the value of the
        variable(s) passed to the optimizer. Using Nesterov Momentum makes the
        variable(s) track the values called `theta_t + mu*v_t` in the paper.
        This implementation is an approximation of the original formula, valid
        for high values of momentum. It will compute the "adjusted gradient" in NAG
        by assuming that the new gradient will be estimated by the current
        average gradient plus the product of momentum and the change in the average gradient.

    @compatibility(eager)
    When eager execution is enabled, `learning_rate` and `momentum` can each be
    a callable that takes no arguments and returns the actual value to use. This
    can be useful for changing these values across different invocations of
    optimizer functions.
    @end_compatibility
    """
    super(MomentumOptimizer, self).__init__(use_locking, name)
    self._learning_rate = learning_rate
    self._momentum = momentum
    self._use_nesterov = use_nesterov

  def _create_slots(self, var_list):
    for v in var_list:
      self._zeros_slot(v, "momentum", self._name)

  def _prepare(self):
    learning_rate = self._learning_rate
    if callable(learning_rate):
      learning_rate = learning_rate()
    self._learning_rate_tensor = ops.convert_to_tensor(learning_rate,
                                                       name="learning_rate")
    momentum = self._momentum
    if callable(momentum):
      momentum = momentum()
    self._momentum_tensor = ops.convert_to_tensor(momentum, name="momentum")

  def _apply_dense(self, grad, var):
    mom = self.get_slot(var, "momentum")
    return training_ops.apply_momentum(
        var, mom,
        math_ops.cast(self._learning_rate_tensor, var.dtype.base_dtype),
        grad,
        math_ops.cast(self._momentum_tensor, var.dtype.base_dtype),
        use_locking=self._use_locking,
        use_nesterov=self._use_nesterov).op

  def _resource_apply_dense(self, grad, var):
    mom = self.get_slot(var, "momentum")
    return training_ops.resource_apply_momentum(
        var.handle, mom.handle,
        math_ops.cast(self._learning_rate_tensor, grad.dtype.base_dtype),
        grad,
        math_ops.cast(self._momentum_tensor, grad.dtype.base_dtype),
        use_locking=self._use_locking,
        use_nesterov=self._use_nesterov)

  def _apply_sparse(self, grad, var):
    mom = self.get_slot(var, "momentum")
    return training_ops.sparse_apply_momentum(
        var, mom,
        math_ops.cast(self._learning_rate_tensor, var.dtype.base_dtype),
        grad.values, grad.indices,
        math_ops.cast(self._momentum_tensor, var.dtype.base_dtype),
        use_locking=self._use_locking,
        use_nesterov=self._use_nesterov).op

  def _resource_apply_sparse(self, grad, var, indices):
    mom = self.get_slot(var, "momentum")
    return training_ops.resource_sparse_apply_momentum(
        var.handle, mom.handle,
        math_ops.cast(self._learning_rate_tensor, grad.dtype),
        grad, indices,
        math_ops.cast(self._momentum_tensor, grad.dtype),
        use_locking=self._use_locking,
        use_nesterov=self._use_nesterov)
<commit_msg>Update momentum.py<commit_after># Copyright 2015 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================

"""Momentum for TensorFlow."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from tensorflow.python.framework import ops
from tensorflow.python.ops import math_ops
from tensorflow.python.training import optimizer
from tensorflow.python.training import training_ops
from tensorflow.python.util.tf_export import tf_export

@tf_export("train.MomentumOptimizer")
class MomentumOptimizer(optimizer.Optimizer):
  """Optimizer that implements the Momentum algorithm.

  Computes (if `use_nesterov = False`):

  ```
  accumulation = momentum * accumulation + gradient
  variable -= learning_rate * accumulation
  ```

  Note that in the dense version of this algorithm, `accumulation` is updated
  and applied regardless of a gradient's value, whereas the sparse version (when
  the gradient is an `IndexedSlices`, typically because of `tf.gather` or an
  embedding) only updates variable slices and corresponding `accumulation` terms
  when that part of the variable was used in the forward pass.
  """

  def __init__(self, learning_rate, momentum,
               use_locking=False, name="Momentum", use_nesterov=False):
    """Construct a new Momentum optimizer.

    Args:
      learning_rate: A `Tensor` or a floating point value.  The learning rate.
      momentum: A `Tensor` or a floating point value.  The momentum.
      use_locking: If `True` use locks for update operations.
      name: Optional name prefix for the operations created when applying
        gradients.  Defaults to "Momentum".
      use_nesterov: If `True` use Nesterov Momentum.
        See [Sutskever et al., 2013](
        http://jmlr.org/proceedings/papers/v28/sutskever13.pdf).
        This implementation always computes gradients at the value of the
        variable(s) passed to the optimizer. Using Nesterov Momentum makes the
        variable(s) track the values called `theta_t + mu*v_t` in the paper.
        This implementation is an approximation of the original formula, valid
        for high values of momentum. It will compute the "adjusted gradient"
        in NAG by assuming that the new gradient will be estimated by the
        current average gradient plus the product of momentum and the change
        in the average gradient.

    @compatibility(eager)
    When eager execution is enabled, `learning_rate` and `momentum` can each be
    a callable that takes no arguments and returns the actual value to use. This
    can be useful for changing these values across different invocations of
    optimizer functions.
    @end_compatibility
    """
    super(MomentumOptimizer, self).__init__(use_locking, name)
    self._learning_rate = learning_rate
    self._momentum = momentum
    self._use_nesterov = use_nesterov

  def _create_slots(self, var_list):
    for v in var_list:
      self._zeros_slot(v, "momentum", self._name)

  def _prepare(self):
    learning_rate = self._learning_rate
    if callable(learning_rate):
      learning_rate = learning_rate()
    self._learning_rate_tensor = ops.convert_to_tensor(learning_rate,
                                                       name="learning_rate")
    momentum = self._momentum
    if callable(momentum):
      momentum = momentum()
    self._momentum_tensor = ops.convert_to_tensor(momentum, name="momentum")

  def _apply_dense(self, grad, var):
    mom = self.get_slot(var, "momentum")
    return training_ops.apply_momentum(
        var, mom,
        math_ops.cast(self._learning_rate_tensor, var.dtype.base_dtype),
        grad,
        math_ops.cast(self._momentum_tensor, var.dtype.base_dtype),
        use_locking=self._use_locking,
        use_nesterov=self._use_nesterov).op

  def _resource_apply_dense(self, grad, var):
    mom = self.get_slot(var, "momentum")
    return training_ops.resource_apply_momentum(
        var.handle, mom.handle,
        math_ops.cast(self._learning_rate_tensor, grad.dtype.base_dtype),
        grad,
        math_ops.cast(self._momentum_tensor, grad.dtype.base_dtype),
        use_locking=self._use_locking,
        use_nesterov=self._use_nesterov)

  def _apply_sparse(self, grad, var):
    mom = self.get_slot(var, "momentum")
    return training_ops.sparse_apply_momentum(
        var, mom,
        math_ops.cast(self._learning_rate_tensor, var.dtype.base_dtype),
        grad.values, grad.indices,
        math_ops.cast(self._momentum_tensor, var.dtype.base_dtype),
        use_locking=self._use_locking,
        use_nesterov=self._use_nesterov).op

  def _resource_apply_sparse(self, grad, var, indices):
    mom = self.get_slot(var, "momentum")
    return training_ops.resource_sparse_apply_momentum(
        var.handle, mom.handle,
        math_ops.cast(self._learning_rate_tensor, grad.dtype),
        grad, indices,
        math_ops.cast(self._momentum_tensor, grad.dtype),
        use_locking=self._use_locking,
        use_nesterov=self._use_nesterov)
<|endoftext|>


<commit_before>import unittest.test

from test import support

def test_main():
    support.run_unittest(unittest.test.suite())
    support.reap_children()

if __name__ == "__main__":
    test_main()
<commit_msg>Fix so that test.test_unittest can be executed by unittest and not just regrtest<commit_after>import unittest.test

from test import support

def test_main():
    # used by regrtest
    support.run_unittest(unittest.test.suite())
    support.reap_children()

def load_tests(*_):
    # used by unittest
    return unittest.test.suite()

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


<commit_before>"""Tests for graphmode_tensornetwork."""
import builtins
import sys
import pytest

@pytest.fixture(autouse=True)
def clean_backend_import():
  #never do this outside testing
  sys.modules.pop('tensornetwork.backends.pytorch.pytorch_backend', None)
  sys.modules.pop('tensornetwork.backends.jax.jax_backend', None)
  sys.modules.pop('tensornetwork.backends.tensorflow.tensorflow_backend', None)
  yield # use as teardown
  sys.modules.pop('tensornetwork', None)

@pytest.fixture
def no_backend_dependency(monkeypatch):
  import_orig = builtins.__import__
  # pylint: disable=redefined-builtin
  def mocked_import(name, globals, locals, fromlist, level):
    if name in ['torch', 'tensorflow', 'jax']:
      raise ImportError()
    return import_orig(name, globals, locals, fromlist, level)
  monkeypatch.setattr(builtins, '__import__', mocked_import)

@pytest.mark.usefixtures('no_backend_dependency')
def test_backend_pytorch_missing_cannot_initialize_backend():
  with pytest.raises(ImportError):
    from tensornetwork.backends.pytorch.pytorch_backend import PyTorchBackend
    PyTorchBackend()

@pytest.mark.usefixtures('no_backend_dependency')
def test_backend_tensorflow_missing_cannot_initialize_backend():
  with pytest.raises(ImportError):
    from tensornetwork.backends.tensorflow.tensorflow_backend \
      import TensorFlowBackend
    TensorFlowBackend()

@pytest.mark.usefixtures('no_backend_dependency')
def test_backend_jax_missing_cannot_initialize_backend():
  with pytest.raises(ImportError):
    from tensornetwork.backends.jax.jax_backend import JaxBackend
    JaxBackend()

@pytest.mark.usefixtures('no_backend_dependency')
def test_config_pytorch_missing_can_import_config():
  import tensornetwork.config
  with pytest.raises(ImportError):
    import torch

@pytest.mark.usefixtures('no_backend_dependency')
def test_config_tensorflow_missing_can_import_config():
  import tensornetwork.config
  with pytest.raises(ImportError):
    import tensorflow as tf

@pytest.mark.usefixtures('no_backend_dependency')
def test_import_tensornetwork_without_backends():
  with pytest.raises(ImportError):
    import torch
  with pytest.raises(ImportError):
    import tensorflow as tf
  with pytest.raises(ImportError):
    import jax
  import tensornetwork
  import tensornetwork.backends.pytorch.pytorch_backend
  import tensornetwork.backends.tensorflow.tensorflow_backend
  import tensornetwork.backends.jax.jax_backend
  import tensornetwork.backends.numpy.numpy_backend<commit_msg>redesigned tests for optional backends (#256)<commit_after>"""Tests for graphmode_tensornetwork."""
import builtins
import sys
import pytest
import numpy as np

def clean_tensornetwork_modules():
  for mod in list(sys.modules.keys()):
    if mod.startswith('tensornetwork'):
      sys.modules.pop(mod, None)

@pytest.fixture(autouse=True)
def clean_backend_import():
  #never do this outside testing
  clean_tensornetwork_modules()
  yield # use as teardown
  clean_tensornetwork_modules()

@pytest.fixture
def no_backend_dependency(monkeypatch):
  import_orig = builtins.__import__
  # pylint: disable=redefined-builtin
  def mocked_import(name, globals, locals, fromlist, level):
    if name in ['torch', 'tensorflow', 'jax']:
      raise ImportError()
    return import_orig(name, globals, locals, fromlist, level)
  monkeypatch.setattr(builtins, '__import__', mocked_import)

@pytest.mark.usefixtures('no_backend_dependency')
def test_backend_pytorch_missing_cannot_initialize_backend():
  with pytest.raises(ImportError):
    from tensornetwork.backends.pytorch.pytorch_backend import PyTorchBackend
    PyTorchBackend()

@pytest.mark.usefixtures('no_backend_dependency')
def test_backend_tensorflow_missing_cannot_initialize_backend():
  with pytest.raises(ImportError):
    from tensornetwork.backends.tensorflow.tensorflow_backend \
      import TensorFlowBackend
    TensorFlowBackend()

@pytest.mark.usefixtures('no_backend_dependency')
def test_backend_jax_missing_cannot_initialize_backend():
  with pytest.raises(ImportError):
    from tensornetwork.backends.jax.jax_backend import JaxBackend
    JaxBackend()

@pytest.mark.usefixtures('no_backend_dependency')
def test_config_backend_missing_can_import_config():
  import tensornetwork.config
  with pytest.raises(ImportError):
    import torch
  with pytest.raises(ImportError):
    import tensorflow as tf
  with pytest.raises(ImportError):
    import jax

@pytest.mark.usefixtures('no_backend_dependency')
def test_import_tensornetwork_without_backends():
  import tensornetwork
  import tensornetwork.backends.pytorch.pytorch_backend
  import tensornetwork.backends.tensorflow.tensorflow_backend
  import tensornetwork.backends.jax.jax_backend
  import tensornetwork.backends.numpy.numpy_backend
  with pytest.raises(ImportError):
    import torch
  with pytest.raises(ImportError):
    import tensorflow as tf
  with pytest.raises(ImportError):
    import jax

@pytest.mark.usefixtures('no_backend_dependency')
def test_basic_numpy_network_without_backends():
  import tensornetwork
  net = tensornetwork.TensorNetwork(backend="numpy")
  a = net.add_node(np.ones((10,)))
  b = net.add_node(np.ones((10,)))
  edge = net.connect(a[0], b[0])
  final_node = net.contract(edge)
  assert final_node.tensor == np.array(10.)
  with pytest.raises(ImportError):
    import torch
  with pytest.raises(ImportError):
    import tensorflow as tf
  with pytest.raises(ImportError):
    import jax

@pytest.mark.usefixtures('no_backend_dependency')
def test_basic_network_without_backends_raises_error():
  import tensornetwork
  with pytest.raises(ImportError):
    tensornetwork.TensorNetwork(backend="jax")
  with pytest.raises(ImportError):
    tensornetwork.TensorNetwork(backend="tensorflow")
  with pytest.raises(ImportError):
    tensornetwork.TensorNetwork(backend="pytorch")
<|endoftext|>


<commit_before>import warnings
import os
import unittest
from test import test_support

# The warnings module isn't easily tested, because it relies on module
# globals to store configuration information.  setUp() and tearDown()
# preserve the current settings to avoid bashing them while running tests.

# To capture the warning messages, a replacement for showwarning() is
# used to save warning information in a global variable.

class WarningMessage:
    "Holds results of latest showwarning() call"
    pass

def showwarning(message, category, filename, lineno, file=None):
    msg.message = str(message)
    msg.category = category.__name__
    msg.filename = os.path.basename(filename)
    msg.lineno = lineno

class TestModule(unittest.TestCase):

    def setUp(self):
        global msg
        msg = WarningMessage()
        self._filters = warnings.filters[:]
        self._showwarning = warnings.showwarning
        warnings.showwarning = showwarning
        self.ignored = [w[2].__name__ for w in self._filters
            if w[0]=='ignore' and w[1] is None and w[3] is None]

    def tearDown(self):
        warnings.filters = self._filters[:]
        warnings.showwarning = self._showwarning

    def test_warn_default_category(self):
        for i in range(4):
            text = 'multi %d' %i    # Different text on each call
            warnings.warn(text)
            self.assertEqual(msg.message, text)
            self.assertEqual(msg.category, 'UserWarning')

    def test_warn_specific_category(self):
        text = 'None'
        # XXX OverflowWarning should go away for Python 2.5.
        for category in [DeprecationWarning, FutureWarning, OverflowWarning,
                    PendingDeprecationWarning, RuntimeWarning,
                    SyntaxWarning, UserWarning, Warning]:
            if category.__name__ in self.ignored:
                text = 'filtered out' + category.__name__
                warnings.warn(text, category)
                self.assertNotEqual(msg.message, text)
            else:
                text = 'unfiltered %s' % category.__name__
                warnings.warn(text, category)
                self.assertEqual(msg.message, text)
                self.assertEqual(msg.category, category.__name__)

    def test_filtering(self):

        warnings.filterwarnings("error", "", Warning, "", 0)
        self.assertRaises(UserWarning, warnings.warn, 'convert to error')

        warnings.resetwarnings()
        text = 'handle normally'
        warnings.warn(text)
        self.assertEqual(msg.message, text)
        self.assertEqual(msg.category, 'UserWarning')

        warnings.filterwarnings("ignore", "", Warning, "", 0)
        text = 'filtered out'
        warnings.warn(text)
        self.assertNotEqual(msg.message, text)

        warnings.resetwarnings()
        warnings.filterwarnings("error", "hex*", Warning, "", 0)
        self.assertRaises(UserWarning, warnings.warn, 'hex/oct')
        text = 'nonmatching text'
        warnings.warn(text)
        self.assertEqual(msg.message, text)
        self.assertEqual(msg.category, 'UserWarning')

def test_main(verbose=None):
    test_support.run_unittest(TestModule)

if __name__ == "__main__":
    test_main(verbose=True)
<commit_msg>Don't filter out OverflowWarning; should be a test failure if it is raised by the interpreter in 2.5 .<commit_after>import warnings
import os
import unittest
from test import test_support

# The warnings module isn't easily tested, because it relies on module
# globals to store configuration information.  setUp() and tearDown()
# preserve the current settings to avoid bashing them while running tests.

# To capture the warning messages, a replacement for showwarning() is
# used to save warning information in a global variable.

class WarningMessage:
    "Holds results of latest showwarning() call"
    pass

def showwarning(message, category, filename, lineno, file=None):
    msg.message = str(message)
    msg.category = category.__name__
    msg.filename = os.path.basename(filename)
    msg.lineno = lineno

class TestModule(unittest.TestCase):

    def setUp(self):
        global msg
        msg = WarningMessage()
        self._filters = warnings.filters[:]
        self._showwarning = warnings.showwarning
        warnings.showwarning = showwarning
        self.ignored = [w[2].__name__ for w in self._filters
            if w[0]=='ignore' and w[1] is None and w[3] is None]

    def tearDown(self):
        warnings.filters = self._filters[:]
        warnings.showwarning = self._showwarning

    def test_warn_default_category(self):
        for i in range(4):
            text = 'multi %d' %i    # Different text on each call
            warnings.warn(text)
            self.assertEqual(msg.message, text)
            self.assertEqual(msg.category, 'UserWarning')

    def test_warn_specific_category(self):
        text = 'None'
        for category in [DeprecationWarning, FutureWarning,
                    PendingDeprecationWarning, RuntimeWarning,
                    SyntaxWarning, UserWarning, Warning]:
            if category.__name__ in self.ignored:
                text = 'filtered out' + category.__name__
                warnings.warn(text, category)
                self.assertNotEqual(msg.message, text)
            else:
                text = 'unfiltered %s' % category.__name__
                warnings.warn(text, category)
                self.assertEqual(msg.message, text)
                self.assertEqual(msg.category, category.__name__)

    def test_filtering(self):

        warnings.filterwarnings("error", "", Warning, "", 0)
        self.assertRaises(UserWarning, warnings.warn, 'convert to error')

        warnings.resetwarnings()
        text = 'handle normally'
        warnings.warn(text)
        self.assertEqual(msg.message, text)
        self.assertEqual(msg.category, 'UserWarning')

        warnings.filterwarnings("ignore", "", Warning, "", 0)
        text = 'filtered out'
        warnings.warn(text)
        self.assertNotEqual(msg.message, text)

        warnings.resetwarnings()
        warnings.filterwarnings("error", "hex*", Warning, "", 0)
        self.assertRaises(UserWarning, warnings.warn, 'hex/oct')
        text = 'nonmatching text'
        warnings.warn(text)
        self.assertEqual(msg.message, text)
        self.assertEqual(msg.category, 'UserWarning')

def test_main(verbose=None):
    test_support.run_unittest(TestModule)

if __name__ == "__main__":
    test_main(verbose=True)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# © 2016-TODAY LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

{
    "name": "Website Form - ReCaptcha",
    "summary": 'Provides a ReCaptcha field for Website Forms',
    "version": "9.0.1.0.0",
    "category": "Website",
    "website": "https://laslabs.com/",
    "author": "LasLabs, Odoo Community Association",
    "license": "AGPL-3",
    "application": False,
    "installable": True,
    "depends": [
        "website_form",
    ],
    "data": [
        "data/ir_config_parameter_data.xml",
        'views/assets.xml',
    ],
}
<commit_msg>[MIG] Make modules uninstallable<commit_after># -*- coding: utf-8 -*-
# © 2016-TODAY LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

{
    "name": "Website Form - ReCaptcha",
    "summary": 'Provides a ReCaptcha field for Website Forms',
    "version": "9.0.1.0.0",
    "category": "Website",
    "website": "https://laslabs.com/",
    "author": "LasLabs, Odoo Community Association",
    "license": "AGPL-3",
    "application": False,
    'installable': False,
    "depends": [
        "website_form",
    ],
    "data": [
        "data/ir_config_parameter_data.xml",
        'views/assets.xml',
    ],
}
<|endoftext|>


<commit_before>import shlex

from gunicorn.app.base import BaseApplication, Config
from django.core.management.base import BaseCommand
from django.core.wsgi import get_wsgi_application
from django.conf import settings
from whitenoise.django import DjangoWhiteNoise
from whitenoise.utils import decode_path_info

class DefaultFileServer(DjangoWhiteNoise):
    def __call__(self, environ, start_response):
        """
        Serve index.html if not /api/ or a static file

        This allows users to navigate directly to a URL like http://127.0.0.1:8000/workflows/2
        and we return index.html, and then react-router interprets the path.
        """
        path = decode_path_info(environ['PATH_INFO'])
        if path.startswith('/api'):
            return self.application(environ, start_response)
        static_file = self.files.get(path)
        if static_file is None:
            # serve the homepage on non-existent file
            static_file = self.files.get('/index.html')
        return self.serve(static_file, environ, start_response)

class WSGIApplication(BaseApplication):
    def __init__(self, options):
        self.options = options
        super().__init__()

    def load_config(self):
        parser = self.cfg.parser()

        # by default, log access to stdout
        self.cfg.set('accesslog', '-')

        env_vars = self.cfg.get_cmd_args_from_env()
        if env_vars:
            env_args = parser.parse_args(env_vars)
            self._set_cfg(env_args)

        if self.options:
            cmd_args = parser.parse_args(shlex.split(self.options))
            self._set_cfg(cmd_args)

    def _set_cfg(self, args):
        """Given an argparse namespace, set cfg variables"""
        for k, v in vars(args).items():
            if v is None:
                continue
            if k == "args":
                continue
            self.cfg.set(k.lower(), v)

    def load(self):
        app = get_wsgi_application()
        whitenoise = DefaultFileServer(app, settings)
        return whitenoise

class Command(BaseCommand):
    help = 'Run the webserver.'
    requires_migrations_checks = True

    def add_arguments(self, parser):
        """Adds the Gunicorn command line args to YAWN"""
        parser.add_argument('--gunicorn', type=str,
                            help='Arguments to pass to gunicorn. See `gunicorn -h` for documentation. '
                                 'Alternatively put them in the GUNICORN_CMD_ARGS env variable.')

    def handle(self, *args, **options):
        print('  Invoking gunicorn YAWN webserver')

        # Run Gunicorn
        gunicorn_args = options.get('gunicorn')
        app = WSGIApplication(gunicorn_args)
        app.run()
<commit_msg>fix flake8<commit_after>import shlex

from gunicorn.app.base import BaseApplication
from django.core.management.base import BaseCommand
from django.core.wsgi import get_wsgi_application
from django.conf import settings
from whitenoise.django import DjangoWhiteNoise
from whitenoise.utils import decode_path_info

class DefaultFileServer(DjangoWhiteNoise):
    def __call__(self, environ, start_response):
        """
        Serve index.html if not /api/ or a static file

        This allows users to navigate directly to a URL like http://127.0.0.1:8000/workflows/2
        and we return index.html, and then react-router interprets the path.
        """
        path = decode_path_info(environ['PATH_INFO'])
        if path.startswith('/api'):
            return self.application(environ, start_response)
        static_file = self.files.get(path)
        if static_file is None:
            # serve the homepage on non-existent file
            static_file = self.files.get('/index.html')
        return self.serve(static_file, environ, start_response)

class WSGIApplication(BaseApplication):
    def __init__(self, options):
        self.options = options
        super().__init__()

    def load_config(self):
        parser = self.cfg.parser()

        # by default, log access to stdout
        self.cfg.set('accesslog', '-')

        env_vars = self.cfg.get_cmd_args_from_env()
        if env_vars:
            env_args = parser.parse_args(env_vars)
            self._set_cfg(env_args)

        if self.options:
            cmd_args = parser.parse_args(shlex.split(self.options))
            self._set_cfg(cmd_args)

    def _set_cfg(self, args):
        """Given an argparse namespace, set cfg variables"""
        for k, v in vars(args).items():
            if v is None:
                continue
            if k == "args":
                continue
            self.cfg.set(k.lower(), v)

    def load(self):
        app = get_wsgi_application()
        whitenoise = DefaultFileServer(app, settings)
        return whitenoise

class Command(BaseCommand):
    help = 'Run the webserver.'
    requires_migrations_checks = True

    def add_arguments(self, parser):
        """Adds the Gunicorn command line args to YAWN"""
        parser.add_argument('--gunicorn', type=str,
                            help='Arguments to pass to gunicorn. See `gunicorn -h` for documentation. '
                                 'Alternatively put them in the GUNICORN_CMD_ARGS env variable.')

    def handle(self, *args, **options):
        print('  Invoking gunicorn YAWN webserver')

        # Run Gunicorn
        gunicorn_args = options.get('gunicorn')
        app = WSGIApplication(gunicorn_args)
        app.run()
<|endoftext|>


<commit_before>import scipy as _sp
import time as _time
from scipy.spatial.distance import cdist as dist
import OpenPNM.Utilities.transformations as tr

def reflect_pts(coords,nplane):
    r'''
    Reflect points across the given plane

    Parameters
    ----------
    coords : array_like
        An Np x ndims array off [x,y,z] coordinates

    nplane : array_like
        A vector of length ndims, specifying the normal to the plane.  The tail
        of the vector is assume to lie on the plane, and the reflection will
        be applied in the direction of the vector.

    Returns
    -------
    coords : array_like
        An Np x ndmins vector of reflected point, not including the input points

    '''
    pass

def crop_pts(coords,box):
    r'''
    Drop all points lying outside the box

    Parameters
    ----------
    coords : array_like
        An Np x ndims array off [x,y,z] coordinates

    box : array_like
        A 2 x ndims array of diametrically opposed corner coordintes

    Returns
    -------
    coords : array_like
        Inputs coordinates with outliers removed

    Notes
    -----
    This needs to be made more general so that an arbitray cuboid with any
    orientation can be supplied, using Np x 8 points
    '''
    coords = coords[_sp.any(coords<box[0],axis=1)]
    coords = coords[_sp.any(coords>box[1],axis=1)]
    return coords

def iscoplanar(coords):
    r'''
    Determines if given pores are coplanar with each other

    Parameters
    ----------
    coords : array_like
        List of pore coords to check for coplanarity.  At least 3 pores are
        required.

    Returns
    -------
    A boolean value of whether given points are colplanar (True) or not (False)
    '''
    coords = _sp.array(coords,ndmin=1)
    if _sp.shape(coords)[0] < 3:
        raise Exception('At least 3 input pores are required')

    Px = coords[:,0]
    Py = coords[:,1]
    Pz = coords[:,2]

    #Do easy check first, for common coordinate
    if _sp.shape(_sp.unique(Px))[0] == 1:
        return True
    if _sp.shape(_sp.unique(Py))[0] == 1:
        return True
    if _sp.shape(_sp.unique(Pz))[0] == 1:
        return True

    #Perform rigorous check using vector algebra
    n = _sp.array((Px - Px[0],Py - Py[0],Pz - Pz[0])).T
    n0 = _sp.array((Px[-1] - Px[0],Py[-1] - Py[0],Pz[-1] - Pz[0])).T

    n_cross = _sp.cross(n0,n)
    n_dot = _sp.multiply(n0,n_cross)
    #angles=[]
    #for vec in n_cross[2:len(n_cross)]:
    #    angles.append(180*(tr.angle_between_vectors(n_cross[1],vec,directed=False)/_sp.pi))
    #angles=_sp.asarray(angles)
    #if angles.mean() < 20:
    if _sp.sum(_sp.absolute(n_dot)) == 0:
        return True
    else:
        return False

def tic():
    r'''
    Homemade version of matlab tic and toc function, tic starts or resets
    the clock, toc reports the time since the last call of tic.
    '''
    global _startTime_for_tictoc
    _startTime_for_tictoc = _time.time()

def toc(quiet=False):
    r'''
    Homemade version of matlab tic and toc function, tic starts or resets
    the clock, toc reports the time since the last call of tic.

    Parameters
    ----------
    quiet : Boolean
        If False (default) then a message is output to the console.  If True
        the message is not displayed and the elapsed time is returned.
    '''
    if '_startTime_for_tictoc' in globals():
        t = _time.time() - _startTime_for_tictoc
        if quiet == False:
            print('Elapsed time in seconds: ', t)
        else:
            return t
    else:
        print("Toc: start time not set")

class PrintableList(list):
    def __str__(self):
        count = 0
        header = '-'*79
        print('\n')
        print(header)
        self.sort()
        for item in self:
            count = count + 1
            print(count,'\t: ',item)
        return header

class PrintableDict(dict):
    def __str__(self):
        import pprint
        header = '-'*79
        print('\n')
        print(header)
        pprint.pprint(self)
        print(header)
        return ''

class ObjectView(object):
    def __init__(self, d):
        temp = {}
        for item in d:
            if type(d[item][0]) == _sp.bool_:
                key = 'label_'+item.replace('.','_')
            else:
                key = 'prop_'+item.replace('.','_')
            temp[key] =d[item]
        self.__dict__ = temp

def amalgamate_data(objs=[]):
    r"""
    Returns a dictionary containing ALL pore data from all netowrk and/or
    phase objects received as arguments
    """
    if type(objs) != list:
        objs = list(objs)
    data_amalgamated = {}
    exclusion_list = ['pore.centroid','pore.vertices','throat.centroid','throat.offset_verts','throat.verts','throat.normals','throat.perimeter']
    for item in objs:
        if item.__module__.split('.')[1] == 'Network': #if network object, combine geometry and network keys
            keys = []
            for key in item.keys():
                keys.append(key)
            for geom in item._geometries:
                for key in geom.keys():
                    if key not in keys:
                        keys.append(key)
        else:
            if item.__module__.split('.')[1] == 'Phases':
                keys = []
                for key in item.keys():
                    keys.append(key)
                for physics in item._physics:
                    for key in physics.keys():
                        if key not in keys:
                            keys.append(key)
        keys.sort()
        for key in keys:
            if key not in exclusion_list:
                if _sp.amax(item[key]) < _sp.inf:
                    dict_name = item.name+'.'+key
                    data_amalgamated.update({dict_name : item[key]})
    return data_amalgamated

<commit_msg>removed an import from misc<commit_after>import scipy as _sp
import time as _time
from scipy.spatial.distance import cdist as dist

def reflect_pts(coords,nplane):
    r'''
    Reflect points across the given plane

    Parameters
    ----------
    coords : array_like
        An Np x ndims array off [x,y,z] coordinates

    nplane : array_like
        A vector of length ndims, specifying the normal to the plane.  The tail
        of the vector is assume to lie on the plane, and the reflection will
        be applied in the direction of the vector.

    Returns
    -------
    coords : array_like
        An Np x ndmins vector of reflected point, not including the input points

    '''
    pass

def crop_pts(coords,box):
    r'''
    Drop all points lying outside the box

    Parameters
    ----------
    coords : array_like
        An Np x ndims array off [x,y,z] coordinates

    box : array_like
        A 2 x ndims array of diametrically opposed corner coordintes

    Returns
    -------
    coords : array_like
        Inputs coordinates with outliers removed

    Notes
    -----
    This needs to be made more general so that an arbitray cuboid with any
    orientation can be supplied, using Np x 8 points
    '''
    coords = coords[_sp.any(coords<box[0],axis=1)]
    coords = coords[_sp.any(coords>box[1],axis=1)]
    return coords

def iscoplanar(coords):
    r'''
    Determines if given pores are coplanar with each other

    Parameters
    ----------
    coords : array_like
        List of pore coords to check for coplanarity.  At least 3 pores are
        required.

    Returns
    -------
    A boolean value of whether given points are colplanar (True) or not (False)
    '''
    coords = _sp.array(coords,ndmin=1)
    if _sp.shape(coords)[0] < 3:
        raise Exception('At least 3 input pores are required')

    Px = coords[:,0]
    Py = coords[:,1]
    Pz = coords[:,2]

    #Do easy check first, for common coordinate
    if _sp.shape(_sp.unique(Px))[0] == 1:
        return True
    if _sp.shape(_sp.unique(Py))[0] == 1:
        return True
    if _sp.shape(_sp.unique(Pz))[0] == 1:
        return True

    #Perform rigorous check using vector algebra
    n = _sp.array((Px - Px[0],Py - Py[0],Pz - Pz[0])).T
    n0 = _sp.array((Px[-1] - Px[0],Py[-1] - Py[0],Pz[-1] - Pz[0])).T

    n_cross = _sp.cross(n0,n)
    n_dot = _sp.multiply(n0,n_cross)
    #angles=[]
    #for vec in n_cross[2:len(n_cross)]:
    #    angles.append(180*(tr.angle_between_vectors(n_cross[1],vec,directed=False)/_sp.pi))
    #angles=_sp.asarray(angles)
    #if angles.mean() < 20:
    if _sp.sum(_sp.absolute(n_dot)) == 0:
        return True
    else:
        return False

def tic():
    r'''
    Homemade version of matlab tic and toc function, tic starts or resets
    the clock, toc reports the time since the last call of tic.
    '''
    global _startTime_for_tictoc
    _startTime_for_tictoc = _time.time()

def toc(quiet=False):
    r'''
    Homemade version of matlab tic and toc function, tic starts or resets
    the clock, toc reports the time since the last call of tic.

    Parameters
    ----------
    quiet : Boolean
        If False (default) then a message is output to the console.  If True
        the message is not displayed and the elapsed time is returned.
    '''
    if '_startTime_for_tictoc' in globals():
        t = _time.time() - _startTime_for_tictoc
        if quiet == False:
            print('Elapsed time in seconds: ', t)
        else:
            return t
    else:
        print("Toc: start time not set")

class PrintableList(list):
    def __str__(self):
        count = 0
        header = '-'*79
        print('\n')
        print(header)
        self.sort()
        for item in self:
            count = count + 1
            print(count,'\t: ',item)
        return header

class PrintableDict(dict):
    def __str__(self):
        import pprint
        header = '-'*79
        print('\n')
        print(header)
        pprint.pprint(self)
        print(header)
        return ''

class ObjectView(object):
    def __init__(self, d):
        temp = {}
        for item in d:
            if type(d[item][0]) == _sp.bool_:
                key = 'label_'+item.replace('.','_')
            else:
                key = 'prop_'+item.replace('.','_')
            temp[key] =d[item]
        self.__dict__ = temp

def amalgamate_data(objs=[]):
    r"""
    Returns a dictionary containing ALL pore data from all netowrk and/or
    phase objects received as arguments
    """
    if type(objs) != list:
        objs = list(objs)
    data_amalgamated = {}
    exclusion_list = ['pore.centroid','pore.vertices','throat.centroid','throat.offset_verts','throat.verts','throat.normals','throat.perimeter']
    for item in objs:
        if item.__module__.split('.')[1] == 'Network': #if network object, combine geometry and network keys
            keys = []
            for key in item.keys():
                keys.append(key)
            for geom in item._geometries:
                for key in geom.keys():
                    if key not in keys:
                        keys.append(key)
        else:
            if item.__module__.split('.')[1] == 'Phases':
                keys = []
                for key in item.keys():
                    keys.append(key)
                for physics in item._physics:
                    for key in physics.keys():
                        if key not in keys:
                            keys.append(key)
        keys.sort()
        for key in keys:
            if key not in exclusion_list:
                if _sp.amax(item[key]) < _sp.inf:
                    dict_name = item.name+'.'+key
                    data_amalgamated.update({dict_name : item[key]})
    return data_amalgamated

<|endoftext|>


<commit_before># pkg_resources selects a suitable resource loader based on the modules's
# __loader__ attribute. In python2 it defaults to None, which maps to the
# default resource loader, but it python3 it does not. As a result,
# pkg_resources is unable to select a resource loader and load resources.
# By settings __loader__ to None, we workaround the pkg_resources bug.
__loader__ = None
<commit_msg>Old hack for python 3 seems not to work any more (may be environment-specific)<commit_after>"""
Canvas module
"""<|endoftext|>