<commit_before>from __future__ import unicode_literals

from lc8_download.lc8 import *
from indicar.process import Process

from os.path import getsize, join, isfile, exists
from os import remove
from datetime import date, timedelta
from shutil import rmtree

from django.utils.encoding import python_2_unicode_compatible
from django.contrib.gis.db import models
from django.contrib.gis.geos import Polygon
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext, ugettext_lazy as _
from django.db.models.signals import post_delete
from django.dispatch import receiver
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse

from django.conf import settings
from .utils import three_digit, calendar_date, download
from .utils import get_bounds, get_cloud_rate

try:
    bands = settings.DOWNLOAD_BANDS
except AttributeError:
    bands = [4, 5, 6, 'BQA']

try:
    srid = settings.SRID
except AttributeError:
    srid = 4326

@python_2_unicode_compatible
class Scene(models.Model):
    """Class to register the Scenes of Landsat imagery"""

    sat_options = (
        ('L8', 'Landsat 8'),
        ('L7', 'Landsat 7'),
        ('L5', 'Landsat 5'),
        )

    status_options = (
        ('created', _('Created')),
        ('downloading', _('Downloading')),
        ('dl_failed', _('Download Failed')),
        ('downloaded', _('Downloaded')),
        ('processing', _('Processing')),
        ('p_failed', _('Processing Failed')),
        ('processed', _('Processed'))
        )

    path = models.CharField(max_length=3)
    row = models.CharField(max_length=3)
    sat = models.CharField(_('Satellite'), choices=sat_options, max_length=50)
    date = models.DateField(_('Date'))
    name = models.CharField(_('Name'), max_length=21, unique=True)
    cloud_rate = models.FloatField(_('Cloud Rate'), null=True, blank=True)
    geom = models.PolygonField(srid=srid, null=True, blank=True)
    status = models.CharField(choices=status_options, max_length=50)

    def __str__(self):
        return '%s %s-%s %s' % (self.sat, self.path, self.row, self.date.strftime('%x'))

    def day(self):
        """Return the julian day of the scene's date as a 3 character string"""
        return three_digit(self.date.timetuple().tm_yday)

    def process(self):
        """Process the Scene using indicar-tools library. It will create a 654
        image composition, a NDVI and a change detection to Landsat 8 Scenes.
        To Landsat 5 and 7, it will create only a 543 composition.
        """
        if self.sat == 'L8':
            if self.images.filter(type__in=['B4', 'B5', 'B6', 'BQA']).count() == 4:
                self.status = 'processing'
                self.save()
                process = Process(self.dir())

                rgb = process.make_img([6, 5, 4])
                if rgb is not False:
                    Image.objects.get_or_create(
                        name=rgb.split('/')[-1],
                        type='r6g5b4',
                        scene=self
                    )

                ndvi = process.make_ndvi()
                if ndvi is not False:
                    Image.objects.get_or_create(
                        name=ndvi.split('/')[-1],
                        type='ndvi',
                        scene=self
                        )

                detection = process.change_detection()
                if detection is not False:
                    Image.objects.get_or_create(
                        name=detection.split('/')[-1],
                        type='detection',
                        scene=self
                        )

                if rgb and ndvi:
                    self.status = 'processed'
                    self.save()
                    return True
                else:
                    self.status = 'p_failed'
                    self.save()
                    return False
            else:
                print('Check if you have B4, B5, B6 and BQA files of this scene.')
                return False

        elif self.sat in ['L5', 'L7']:
            if self.images.filter(type__in=['B3', 'B4', 'B5']).count() == 3:
                self.status = 'processing'
                self.save()
                process = Process(self.dir())
                rgb = process.make_img([5, 4, 3])

                if rgb is not False:
                    Image.objects.get_or_create(
                        name=rgb.split('/')[-1],
                        type='r5g4b3',
                        scene=self
                        )
                    self.status = 'processed'
                    self.save()
                else:
                    self.status = 'p_failed'
                    self.save()
                    return False
            else:
                print('Check if you have B3, B4 and B5 files of this scene.')
                return False

    def quicklook(self):
        """Return the URL of the Natural View quicklook image."""
        base_url = 'http://earthexplorer.usgs.gov/browse'
        if self.sat == 'L8':
            return '%s/landsat_8/%s/%s/%s/%s.jpg' % (base_url, self.date.year,
                self.path, self.row, self.name)
        if self.sat == 'L7':
            return '%s/etm/%s/%s/%s/%s_REFL.jpg' % (base_url, int(self.path),
                int(self.row), self.date.year, self.name)
        if self.sat == 'L5':
            return '%s/tm/%s/%s/%s/%s_REFL.jpg' % (base_url, int(self.path),
                int(self.row), self.date.year, self.name)

    def dir(self):
        """Return the folder where the files of the scenes are saved."""
        return join(settings.MEDIA_ROOT, self.sat, self.name)

    def save(self, *args, **kwargs):
        self.full_clean()
        super(Scene, self).save(*args, **kwargs)

    class Meta:
        ordering = ['-date', 'path', 'row']
        verbose_name = _('Scene')
        verbose_name_plural = _('Scenes')

@receiver(post_delete, sender=Scene)
def post_delete_scene(sender, instance, *args, **kwargs):
    """Overwrites post_delete method of Scene Model to delete also the folder
    fisically in the disk.
    """
    if exists(instance.dir()):
        rmtree(instance.dir())

@python_2_unicode_compatible
class Image(models.Model):
    """Class to register the image files. All Images are associated with
    one Scene object.False
    """

    name = models.CharField(_('Name'), max_length=100, unique=True)
    type = models.CharField(_('Type'), max_length=30)
    creation_date = models.DateField(_('Creation date'), auto_now_add=True)
    scene = models.ForeignKey(Scene, related_name='images')

    def __str__(self):
        return '%s' % self.name

    def url(self):
        """URL string to be used concatenated with MEDIA_URL"""
        return join(settings.MEDIA_URL, self.scene.sat, self.scene.name, self.name)

    def file_path(self):
        """File path of the Image in the filesystem."""
        return '%s' % join(self.scene.dir(), self.name)

    def file_exists(self):
        """Test if the file exists on filesystem."""
        return isfile(self.file_path())

    def save(self, *args, **kwargs):
        self.full_clean()
        super(Image, self).save(*args, **kwargs)

    class Meta:
        verbose_name = _('Image')
        verbose_name_plural = _('Images')

@receiver(post_delete, sender=Image)
def post_delete_image(sender, instance, *args, **kwargs):
    """Overwrites post_delete method of Image Model to delete also the file
    fisically in the disk.
    """
    if instance.file_exists():
        remove(instance.file_path())

@python_2_unicode_compatible
class ScheduledDownload(models.Model):
    """Class to schedule the download of Landsat 8 imagery."""

    path = models.CharField(max_length=3)
    row = models.CharField(max_length=3)
    creation_date = models.DateField(_('Creation date'), auto_now_add=True)

    def __str__(self):
        return 'L8 %s-%s' % (self.path, self.row)

    def last_scene(self):
        """Return the last Scene of this path and row or None if there isn't
        any Scene yet.
        """
        if Scene.objects.filter(path=self.path, row=self.row, sat='L8'):
            return Scene.objects.filter(path=self.path, row=self.row, sat='L8') \
                .latest('date')
        else:
            return None

    def has_new_scene(self):
        """Return True if it has more than 16 days since the last Scene of this
        path and row or if there isn't any Scene registered for this path and
        row.
        """
        if self.last_scene() is None:
            return True
        elif date.today() - self.last_scene().date >= timedelta(16):
            return True
        else:
            return False

    def next_scene_name(self):
        """Return the name of the next Scene for this path and row. If there
        isn't any registered Scene or the last registered Scene is older than
        32 days, it will return the scene name with the date of today.
        """
        if (self.last_scene() is not None and
                (self.creation_date - self.last_scene().date <= timedelta(32))):
            first_part = self.last_scene().name[:9]
            end = self.last_scene().name[16:]
            next_date = self.last_scene().date + timedelta(days=16)
            next_day = three_digit(next_date.timetuple().tm_yday)
            return '%s%s%s%s' % (first_part, next_date.year, next_day, end)
        else:
            year = date.today().year
            day = three_digit(date.today().timetuple().tm_yday)
            return 'LC8%s%s%s%sLGN00' % (self.path, self.row, year, day)

    def create_scene(self):
        """Get or Create a new Scene object for this path and row."""
        scene_date = calendar_date(
            self.next_scene_name()[9:13],
            self.next_scene_name()[13:16]
            )

        try:
            geom = Polygon(get_bounds(self.next_scene_name()))
        except IndexError:
            geom = None

        try:
            cloud_rate = get_cloud_rate(self.next_scene_name())
        except FileNotFoundError:
            cloud_rate = None

        return Scene.objects.get_or_create(
            path=self.path,
            row=self.row,
            sat='L8',
            name=self.next_scene_name(),
            date=scene_date,
            status='downloading',
            geom=geom,
            cloud_rate=cloud_rate
            )

    def create_image(self, image_name):
        """Create a new Image object."""
        return Image.objects.get_or_create(
            name=image_name,
            type=image_name.split('_')[1].split('.')[0],
            scene=Scene.objects.get(name=image_name.split('_')[0])
            )

    def download_new_scene(self, bands):
        """Download the bands B4, B5, B6 and BQA of the next scene. """
        if self.has_new_scene():
            try:
                downloaded = download(self.next_scene_name(), bands)
                self.create_scene()
                for path, size in downloaded:
                    self.create_image(path.split('/')[-1])
                return downloaded
            except DownloaderErrors:
                return []

    def check_last_scene(self, bands):
        """Check if the last scene already has all image bands. If not, try to
        download.
        """
        last_scene = self.last_scene()
        if last_scene is not None:
            if last_scene.images.count() < len(bands) or last_scene.status == 'dl_failed':
                try:
                    downloaded = download(last_scene.name, bands)
                    for path, size in downloaded:
                        self.create_image(path.split('/')[-1])
                    return downloaded
                except RemoteFileDoesntExist:
                    if last_scene.status != 'dl_failed':
                        last_scene.status = 'dl_failed'
                        last_scene.save()
                    return []

            elif last_scene.status == 'created':
                try:
                    downloaded = download(last_scene.name, bands)
                    last_scene.status = 'downloaded'
                except RemoteFileDoesntExist:
                    if last_scene.status != 'dl_failed':
                        last_scene.status = 'dl_failed'

                try:
                    geom = Polygon(get_bounds(last_scene.name))
                except IndexError:
                    geom = None

                try:
                    cloud_rate = get_cloud_rate(last_scene.name)
                except FileNotFoundError:
                    cloud_rate = None

                last_scene.save()

                if downloaded:
                    for path, size in downloaded:
                        self.create_image(path.split('/')[-1])
                else:
                    downloaded = []

                return downloaded

            else:
                if last_scene.status == 'downloading':
                    last_scene.status = 'downloaded'
                    last_scene.save()
                return []
        else:
            print('There is not any Scenes registered for this path and row')

    def clean(self):
        self.clean_fields()
        try:
            if self != ScheduledDownload.objects.get(path=self.path, row=self.row):
                raise ValidationError(
                    _('There is already a scheduled scene with this path and row.')
                    )
        except self.DoesNotExist:
            pass

    def save(self, *args, **kwargs):
        self.full_clean()
        super(ScheduledDownload, self).save(*args, **kwargs)

    class Meta:
        verbose_name = _('Scheduled Download')
        verbose_name_plural = _('Scheduled Downloads')

def validate_scene_name(value):
    """Validator for the scene_name field of PastSceneDownload Model."""
    try:
        Scene.objects.get(name=value)
        raise ValidationError(
            _('The scene you want is already on our database.')
            )
    except Scene.DoesNotExist:
        if len(value) != 21:
            raise ValidationError(
                _('The scene name needs to have 21 characters.')
            )
        elif not value.startswith('L') or value[2] not in ['5', '7', '8']:
            raise ValidationError(
                _('Wrong scene name. Please check it.')
            )

class SceneRequest(models.Model):
    """Model to receive requests of download of past Scenes. It can download
    Landsat 5, 7 and 8 from AWS or Google Earth Engine.
    """
    status_options = (
        ('pending', _('Pending')),
        ('downloading', _('Downloading')),
        ('downloaded', _('Downloaded')),
        ('not_found', _('Not found'))
    )

    scene_name = models.CharField(_('Scene name'), max_length=21, unique=True,
        validators=[validate_scene_name])
    user = models.ForeignKey(User)
    creation_date = models.DateTimeField(_('Creation date'), auto_now_add=True)
    status = models.CharField(max_length=32, choices=status_options,
        default='pending')

    def __str__(self):
        return self.scene_name

    def scene_url(self):
        """Return the URL of the Scene if it was already downloaded."""
        if self.status == 'downloaded':
            return reverse('scene', args=[self.scene_name])
        else:
            return None

    def save(self, *args, **kwargs):
        self.validate_unique()
        super(SceneRequest, self).save(*args, **kwargs)

    class Meta:
        ordering = ['-creation_date', 'scene_name']
        verbose_name = _('Scene Request')
        verbose_name_plural = _('Scene Requests')
<commit_msg>Fixed bug<commit_after>from __future__ import unicode_literals

from lc8_download.lc8 import *
from indicar.process import Process

from os.path import getsize, join, isfile, exists
from os import remove
from datetime import date, timedelta
from shutil import rmtree

from django.utils.encoding import python_2_unicode_compatible
from django.contrib.gis.db import models
from django.contrib.gis.geos import Polygon
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext, ugettext_lazy as _
from django.db.models.signals import post_delete
from django.dispatch import receiver
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse

from django.conf import settings
from .utils import three_digit, calendar_date, download
from .utils import get_bounds, get_cloud_rate

try:
    bands = settings.DOWNLOAD_BANDS
except AttributeError:
    bands = [4, 5, 6, 'BQA']

try:
    srid = settings.SRID
except AttributeError:
    srid = 4326

@python_2_unicode_compatible
class Scene(models.Model):
    """Class to register the Scenes of Landsat imagery"""

    sat_options = (
        ('L8', 'Landsat 8'),
        ('L7', 'Landsat 7'),
        ('L5', 'Landsat 5'),
        )

    status_options = (
        ('created', _('Created')),
        ('downloading', _('Downloading')),
        ('dl_failed', _('Download Failed')),
        ('downloaded', _('Downloaded')),
        ('processing', _('Processing')),
        ('p_failed', _('Processing Failed')),
        ('processed', _('Processed'))
        )

    path = models.CharField(max_length=3)
    row = models.CharField(max_length=3)
    sat = models.CharField(_('Satellite'), choices=sat_options, max_length=50)
    date = models.DateField(_('Date'))
    name = models.CharField(_('Name'), max_length=21, unique=True)
    cloud_rate = models.FloatField(_('Cloud Rate'), null=True, blank=True)
    geom = models.PolygonField(srid=srid, null=True, blank=True)
    status = models.CharField(choices=status_options, max_length=50)

    def __str__(self):
        return '%s %s-%s %s' % (self.sat, self.path, self.row, self.date.strftime('%x'))

    def day(self):
        """Return the julian day of the scene's date as a 3 character string"""
        return three_digit(self.date.timetuple().tm_yday)

    def process(self):
        """Process the Scene using indicar-tools library. It will create a 654
        image composition, a NDVI and a change detection to Landsat 8 Scenes.
        To Landsat 5 and 7, it will create only a 543 composition.
        """
        if self.sat == 'L8':
            if self.images.filter(type__in=['B4', 'B5', 'B6', 'BQA']).count() == 4:
                self.status = 'processing'
                self.save()
                process = Process(self.dir())

                rgb = process.make_img([6, 5, 4])
                if rgb is not False:
                    Image.objects.get_or_create(
                        name=rgb.split('/')[-1],
                        type='r6g5b4',
                        scene=self
                    )

                ndvi = process.make_ndvi()
                if ndvi is not False:
                    Image.objects.get_or_create(
                        name=ndvi.split('/')[-1],
                        type='ndvi',
                        scene=self
                        )

                detection = process.change_detection()
                if detection is not False:
                    Image.objects.get_or_create(
                        name=detection.split('/')[-1],
                        type='detection',
                        scene=self
                        )

                if rgb and ndvi:
                    self.status = 'processed'
                    self.save()
                    return True
                else:
                    self.status = 'p_failed'
                    self.save()
                    return False
            else:
                print('Check if you have B4, B5, B6 and BQA files of this scene.')
                return False

        elif self.sat in ['L5', 'L7']:
            if self.images.filter(type__in=['B3', 'B4', 'B5']).count() == 3:
                self.status = 'processing'
                self.save()
                process = Process(self.dir())
                rgb = process.make_img([5, 4, 3])

                if rgb is not False:
                    Image.objects.get_or_create(
                        name=rgb.split('/')[-1],
                        type='r5g4b3',
                        scene=self
                        )
                    self.status = 'processed'
                    self.save()
                else:
                    self.status = 'p_failed'
                    self.save()
                    return False
            else:
                print('Check if you have B3, B4 and B5 files of this scene.')
                return False

    def quicklook(self):
        """Return the URL of the Natural View quicklook image."""
        base_url = 'http://earthexplorer.usgs.gov/browse'
        if self.sat == 'L8':
            return '%s/landsat_8/%s/%s/%s/%s.jpg' % (base_url, self.date.year,
                self.path, self.row, self.name)
        if self.sat == 'L7':
            return '%s/etm/%s/%s/%s/%s_REFL.jpg' % (base_url, int(self.path),
                int(self.row), self.date.year, self.name)
        if self.sat == 'L5':
            return '%s/tm/%s/%s/%s/%s_REFL.jpg' % (base_url, int(self.path),
                int(self.row), self.date.year, self.name)

    def dir(self):
        """Return the folder where the files of the scenes are saved."""
        return join(settings.MEDIA_ROOT, self.sat, self.name)

    def save(self, *args, **kwargs):
        self.full_clean()
        super(Scene, self).save(*args, **kwargs)

    class Meta:
        ordering = ['-date', 'path', 'row']
        verbose_name = _('Scene')
        verbose_name_plural = _('Scenes')

@receiver(post_delete, sender=Scene)
def post_delete_scene(sender, instance, *args, **kwargs):
    """Overwrites post_delete method of Scene Model to delete also the folder
    fisically in the disk.
    """
    if exists(instance.dir()):
        rmtree(instance.dir())

@python_2_unicode_compatible
class Image(models.Model):
    """Class to register the image files. All Images are associated with
    one Scene object.False
    """

    name = models.CharField(_('Name'), max_length=100, unique=True)
    type = models.CharField(_('Type'), max_length=30)
    creation_date = models.DateField(_('Creation date'), auto_now_add=True)
    scene = models.ForeignKey(Scene, related_name='images')

    def __str__(self):
        return '%s' % self.name

    def url(self):
        """URL string to be used concatenated with MEDIA_URL"""
        return join(settings.MEDIA_URL, self.scene.sat, self.scene.name, self.name)

    def file_path(self):
        """File path of the Image in the filesystem."""
        return '%s' % join(self.scene.dir(), self.name)

    def file_exists(self):
        """Test if the file exists on filesystem."""
        return isfile(self.file_path())

    def save(self, *args, **kwargs):
        self.full_clean()
        super(Image, self).save(*args, **kwargs)

    class Meta:
        verbose_name = _('Image')
        verbose_name_plural = _('Images')

@receiver(post_delete, sender=Image)
def post_delete_image(sender, instance, *args, **kwargs):
    """Overwrites post_delete method of Image Model to delete also the file
    fisically in the disk.
    """
    if instance.file_exists():
        remove(instance.file_path())

@python_2_unicode_compatible
class ScheduledDownload(models.Model):
    """Class to schedule the download of Landsat 8 imagery."""

    path = models.CharField(max_length=3)
    row = models.CharField(max_length=3)
    creation_date = models.DateField(_('Creation date'), auto_now_add=True)

    def __str__(self):
        return 'L8 %s-%s' % (self.path, self.row)

    def last_scene(self):
        """Return the last Scene of this path and row or None if there isn't
        any Scene yet.
        """
        if Scene.objects.filter(path=self.path, row=self.row, sat='L8'):
            return Scene.objects.filter(path=self.path, row=self.row, sat='L8') \
                .latest('date')
        else:
            return None

    def has_new_scene(self):
        """Return True if it has more than 16 days since the last Scene of this
        path and row or if there isn't any Scene registered for this path and
        row.
        """
        if self.last_scene() is None:
            return True
        elif date.today() - self.last_scene().date >= timedelta(16):
            return True
        else:
            return False

    def next_scene_name(self):
        """Return the name of the next Scene for this path and row. If there
        isn't any registered Scene or the last registered Scene is older than
        32 days, it will return the scene name with the date of today.
        """
        if (self.last_scene() is not None and
                (self.creation_date - self.last_scene().date <= timedelta(32))):
            first_part = self.last_scene().name[:9]
            end = self.last_scene().name[16:]
            next_date = self.last_scene().date + timedelta(days=16)
            next_day = three_digit(next_date.timetuple().tm_yday)
            return '%s%s%s%s' % (first_part, next_date.year, next_day, end)
        else:
            year = date.today().year
            day = three_digit(date.today().timetuple().tm_yday)
            return 'LC8%s%s%s%sLGN00' % (self.path, self.row, year, day)

    def create_scene(self):
        """Get or Create a new Scene object for this path and row."""
        scene_date = calendar_date(
            self.next_scene_name()[9:13],
            self.next_scene_name()[13:16]
            )

        try:
            geom = Polygon(get_bounds(self.next_scene_name()))
        except IndexError:
            geom = None

        try:
            cloud_rate = get_cloud_rate(self.next_scene_name())
        except FileNotFoundError:
            cloud_rate = None

        return Scene.objects.get_or_create(
            path=self.path,
            row=self.row,
            sat='L8',
            name=self.next_scene_name(),
            date=scene_date,
            status='downloading',
            geom=geom,
            cloud_rate=cloud_rate
            )

    def create_image(self, image_name):
        """Create a new Image object."""
        return Image.objects.get_or_create(
            name=image_name,
            type=image_name.split('_')[1].split('.')[0],
            scene=Scene.objects.get(name=image_name.split('_')[0])
            )

    def download_new_scene(self, bands):
        """Download the bands B4, B5, B6 and BQA of the next scene."""
        if self.has_new_scene():
            try:
                downloaded = download(self.next_scene_name(), bands)
                self.create_scene()
                for path, size in downloaded:
                    self.create_image(path.split('/')[-1])
                return downloaded
            except DownloaderErrors:
                return []

    def check_last_scene(self, bands):
        """Check if the last scene already has all image bands. If not, try to
        download.
        """
        last_scene = self.last_scene()
        if last_scene is not None:
            if last_scene.images.count() < len(bands) or last_scene.status == 'dl_failed':
                try:
                    downloaded = download(last_scene.name, bands)
                    for path, size in downloaded:
                        self.create_image(path.split('/')[-1])
                    return downloaded
                except RemoteFileDoesntExist:
                    if last_scene.status != 'dl_failed':
                        last_scene.status = 'dl_failed'
                        last_scene.save()
                    return []

            elif last_scene.status == 'created':
                try:
                    downloaded = download(last_scene.name, bands)
                    last_scene.status = 'downloaded'
                except RemoteFileDoesntExist:
                    if last_scene.status != 'dl_failed':
                        last_scene.status = 'dl_failed'

                try:
                    geom = Polygon(get_bounds(last_scene.name))
                except IndexError:
                    geom = None

                try:
                    cloud_rate = get_cloud_rate(last_scene.name)
                except FileNotFoundError:
                    cloud_rate = None

                last_scene.save()

                if downloaded:
                    for path, size in downloaded:
                        self.create_image(path.split('/')[-1])
                else:
                    downloaded = []

                return downloaded

            else:
                if last_scene.status == 'downloading':
                    last_scene.status = 'downloaded'
                    last_scene.save()
                return []
        else:
            print('There is not any Scenes registered for this path and row')

    def clean(self):
        self.clean_fields()
        try:
            if self != ScheduledDownload.objects.get(path=self.path, row=self.row):
                raise ValidationError(
                    _('There is already a scheduled scene with this path and row.')
                    )
        except self.DoesNotExist:
            pass

    def save(self, *args, **kwargs):
        self.full_clean()
        super(ScheduledDownload, self).save(*args, **kwargs)

    class Meta:
        verbose_name = _('Scheduled Download')
        verbose_name_plural = _('Scheduled Downloads')

def validate_scene_name(value):
    """Validator for the scene_name field of PastSceneDownload Model."""
    try:
        Scene.objects.get(name=value)
        raise ValidationError(
            _('The scene you want is already on our database.')
            )
    except Scene.DoesNotExist:
        if len(value) != 21:
            raise ValidationError(
                _('The scene name needs to have 21 characters.')
            )
        elif not value.startswith('L') or value[2] not in ['5', '7', '8']:
            raise ValidationError(
                _('Wrong scene name. Please check it.')
            )

class SceneRequest(models.Model):
    """Model to receive requests of download of past Scenes. It can download
    Landsat 5, 7 and 8 from AWS or Google Earth Engine.
    """
    status_options = (
        ('pending', _('Pending')),
        ('downloading', _('Downloading')),
        ('downloaded', _('Downloaded')),
        ('not_found', _('Not found'))
    )

    scene_name = models.CharField(_('Scene name'), max_length=21, unique=True,
        validators=[validate_scene_name])
    user = models.ForeignKey(User)
    creation_date = models.DateTimeField(_('Creation date'), auto_now_add=True)
    status = models.CharField(max_length=32, choices=status_options,
        default='pending')

    def __str__(self):
        return self.scene_name

    def scene_url(self):
        """Return the URL of the Scene if it was already downloaded."""
        if self.status == 'downloaded':
            return reverse('scene', args=[self.scene_name])
        else:
            return None

    def save(self, *args, **kwargs):
        self.validate_unique()
        super(SceneRequest, self).save(*args, **kwargs)

    class Meta:
        ordering = ['-creation_date', 'scene_name']
        verbose_name = _('Scene Request')
        verbose_name_plural = _('Scene Requests')
<|endoftext|>


<commit_before>import requests
from bs4 import BeautifulSoup

CAPO_URL = 'http://www.capogirogelato.com/flavors.php'
location_numbers = {}
location_numbers['13th Street'] = '1'
location_numbers['Rittenhouse'] = '2'
location_numbers['CapoYunk'] = '3'
location_numbers['CapoPenn'] = '4'

def locations():
    for location in locations.keys():
        print(location)

def get_flavor_html(location):
    """Returns a location's daily flavor list HTML."""
    if not location in location_numbers.keys():
        return None

    payload = {'location': location_numbers[location]}
    flavor_html = requests.get(CAPO_URL,params = payload)

    if flavor_html.status_code == 200:
        return flavor_html.text
    else:
        return None

def extract_flavors(location, html):
    """Takes HTML and returns dictionary flavor info"""
    flavor_info = {}

    soup = BeautifulSoup(html,'html.parser')

    flavors = soup.find_all('td','flavorbox')
    for flavor in flavors:
        flavor_name = flavor.contents[0].contents[0]
        try:
            flavor_description = flavor.contents[1].contents[0].contents[0]
        except:
            flavor_description = None
        flavor_info[flavor_name] = flavor_description

    return flavor_info

def get_location_flavors(location):
    """Returns a location's daily flavor list as a dict"""
    flavor_html = get_flavor_html(location)
    flavors = extract_flavors(location,flavor_html)
    return flavors

def get_daily_flavors():
    """Returns dict of locations : flavors available today."""
    daily_flavors = {}
    for location in location_numbers.keys():
        daily_flavors[location] = get_location_flavors(location)
    return daily_flavors<commit_msg>Added docstring for locations()<commit_after>import requests
from bs4 import BeautifulSoup

CAPO_URL = 'http://www.capogirogelato.com/flavors.php'
location_numbers = {}
location_numbers['13th Street'] = '1'
location_numbers['Rittenhouse'] = '2'
location_numbers['CapoYunk'] = '3'
location_numbers['CapoPenn'] = '4'

def locations():
    """Print location names"""
    for location in locations.keys():
        print(location)

def get_flavor_html(location):
    """Returns a location's daily flavor list HTML."""
    if not location in location_numbers.keys():
        return None

    payload = {'location': location_numbers[location]}
    flavor_html = requests.get(CAPO_URL,params = payload)

    if flavor_html.status_code == 200:
        return flavor_html.text
    else:
        return None

def extract_flavors(location, html):
    """Takes HTML and returns dictionary flavor info"""
    flavor_info = {}

    soup = BeautifulSoup(html,'html.parser')

    flavors = soup.find_all('td','flavorbox')
    for flavor in flavors:
        flavor_name = flavor.contents[0].contents[0]
        try:
            flavor_description = flavor.contents[1].contents[0].contents[0]
        except:
            flavor_description = None
        flavor_info[flavor_name] = flavor_description

    return flavor_info

def get_location_flavors(location):
    """Returns a location's daily flavor list as a dict"""
    flavor_html = get_flavor_html(location)
    flavors = extract_flavors(location,flavor_html)
    return flavors

def get_daily_flavors():
    """Returns dict of locations : flavors available today."""
    daily_flavors = {}
    for location in location_numbers.keys():
        daily_flavors[location] = get_location_flavors(location)
    return daily_flavors<|endoftext|>


<commit_before># encoding: utf-8

#   Copyright 2012 Red Hat, Inc.
#
#   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.

import uuid
import Provider
from threading import Thread
from props import prop
from NotificationCenter import NotificationCenter
from Template import Template
from PluginManager import PluginManager

class Builder(object):
    """ TODO: Docstring for Builder  """

##### PROPERTIES
    os_plugin = prop("_os_plugin")
    cloud_plugin = prop("_cloud_plugin")
    base_image = prop("_base_image")
    target_image = prop("_target_image")
    provider_image = prop("_provider_image")

##### INITIALIZER
    def __init__(self):
        super(Builder, self).init()
        self.notification_center = NotificationCenter()

#####  BUILD IMAGE
    def build_image_from_template(self, template, parameters=None):
        """
        TODO: Docstring for build_image_from_template

        @param template TODO

        @return TODO
        """
        thread_name = str(uuid.uuid4())[0:8]
        thread_kwargs = {'template':template, 'parameters':parameters}
        self.base_thread = Thread(target=self._build_image_from_template, name=thread_name, args=None, kwargs=thread_kwargs)
        self.base_thread.start()

    def _build_image_from_template(self, template, parameters=None):
        template = template if(isinstance(template, Template)) else Template(template)
        self.os_plugin = PluginManager().plugin_for_target((template.os_name, template.os_version, template.os_arch))
        self.base_image = self.os_plugin.create_base_image(self, template, parameters)

##### CUSTOMIZE IMAGE FOR TARGET
    def customize_image_for_target(self, target, image_id=None, template=None, parameters=None):
        """
        TODO: Docstring for customize_image_for_target

        @param factory_image TODO
        @param target TODO
        @param target_params TODO

        @return TODO
        """
        thread_name = str(uuid.uuid4())[0:8]
        thread_kwargs = {'target':target, 'image_id':image_id, 'template':template, 'parameters':parameters}
        self.target_thread = Thread(target=self._customize_image_for_target, name=thread_name, args=None, kwargs=thread_kwargs)
        self.target_thread.start()

    def _customize_image_for_target(self, target, image_id=None, template=None, parameters=None):
        if(image_id and (not template)):
            # TODO get the template from the base_image
            pass

        template = template if(isinstance(template, Template)) else Template(template)
        self.os_plugin = PluginManager().plugin_for_target((template.os_name, template.os_version, template.os_arch))
        self.cloud_plugin = PluginManager().plugin_for_target(target)

        try:
            _should_create = self.cloud_plugin.builder_should_create_target_image(self, target, image_id, template, parameters)
        except AttributeError:
            _should_create = True
        try:
            if _should_create : self.cloud_plugin.builder_will_create_target_image(self, target, image_id, template, parameters)
        except AttributeError:
            pass
        if(_should_create):
            try:
                self.target_image = self.os_plugin.create_target_image(self, target, image, parameters)
                self.cloud_plugin.builder_did_create_target_image(self, target, image, template, parameters)
            except AttributeError:
                pass

##### CREATE PROVIDER IMAGE
    def create_image_on_provider(self, provider, credentials, image_id=None, template=None, parameters=None):
        if(parameters.get('snapshot', False)):
            self.snapshot_image_on_provider(provider, credentials, template, parameters)
        else:
            self.push_image_to_provider(provider, credentials, image_id, template, parameters)

##### PUSH IMAGE TO PROVIDER
    def push_image_to_provider(self, provider, credentials, image_id, template, parameters):
        """
        TODO: Docstring for push_image_to_provider

        @param image TODO
        @param provider TODO
        @param credentials TODO
        @param provider_params TODO

        @return TODO
        """
        thread_name = str(uuid.uuid4())[0:8]
        thread_kwargs = {'provider':provider, 'credentials':credentials, 'image_id':image_id, 'template':template, 'parameters':parameters}
        self.push_thread = Thread(target=self._push_image_to_provider, name=thread_name, args=None, kwargs=thread_kwargs)
        self.push_thread.start()

    def _push_image_to_provider(self, provider, credentials, image_id, template, parameters):
        self.cloud_plugin = PluginManager().plugin_for_target(Provider.map_provider_to_target(provider))
        target_image = None # TODO: either retrieve the image or build one.
        self.provider_image = self.cloud_plugin.push_image_to_provider(self, provider, credentials, target_image, parameters)

##### SNAPSHOT IMAGE
    def snapshot_image(self, provider, credentials, template, parameters):
        """
        TODO: Docstring for snapshot_image

        @param template TODO
        @param target TODO
        @param provider TODO
        @param credentials TODO
        @param snapshot_params TODO

        @return TODO
        """
        thread_name = str(uuid.uuid4())[0:8]
        thread_kwargs = {'provider':provider, 'credentials':credentials, 'template':template, 'parameters':parameters}
        self.snapshot_thread = Thread(target=self._snapshot_image, name=thread_name, args=None, kwargs=thread_kwargs)
        self.snapshot_thread.start()

    def _snapshot_image(self, provider, credentials, template, parameters):
        self.cloud_plugin = PluginManager().plugin_for_target(Provider.map_provider_to_target(provider))
        self.provider_image = self.cloud_plugin.snapshot_image_on_provider(self, provider, credentials, template, parameters)
<commit_msg>added some todo comments<commit_after># encoding: utf-8

#   Copyright 2012 Red Hat, Inc.
#
#   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.

import uuid
import Provider
from threading import Thread
from props import prop
from NotificationCenter import NotificationCenter
from Template import Template
from PluginManager import PluginManager

class Builder(object):
    """ TODO: Docstring for Builder  """

##### PROPERTIES
    os_plugin = prop("_os_plugin")
    cloud_plugin = prop("_cloud_plugin")
    base_image = prop("_base_image")
    target_image = prop("_target_image")
    provider_image = prop("_provider_image")

##### INITIALIZER
    def __init__(self):
        super(Builder, self).init()
        self.notification_center = NotificationCenter()

#####  BUILD IMAGE
    def build_image_from_template(self, template, parameters=None):
        """
        TODO: Docstring for build_image_from_template

        @param template TODO

        @return TODO
        """
        thread_name = str(uuid.uuid4())[0:8]
        thread_kwargs = {'template':template, 'parameters':parameters}
        self.base_thread = Thread(target=self._build_image_from_template, name=thread_name, args=None, kwargs=thread_kwargs)
        self.base_thread.start()

    def _build_image_from_template(self, template, parameters=None):
        template = template if(isinstance(template, Template)) else Template(template)
        self.os_plugin = PluginManager().plugin_for_target((template.os_name, template.os_version, template.os_arch))
        self.base_image = self.os_plugin.create_base_image(self, template, parameters)

##### CUSTOMIZE IMAGE FOR TARGET
    def customize_image_for_target(self, target, image_id=None, template=None, parameters=None):
        """
        TODO: Docstring for customize_image_for_target

        @param factory_image TODO
        @param target TODO
        @param target_params TODO

        @return TODO
        """
        thread_name = str(uuid.uuid4())[0:8]
        thread_kwargs = {'target':target, 'image_id':image_id, 'template':template, 'parameters':parameters}
        self.target_thread = Thread(target=self._customize_image_for_target, name=thread_name, args=None, kwargs=thread_kwargs)
        self.target_thread.start()

    def _customize_image_for_target(self, target, image_id=None, template=None, parameters=None):
        if(image_id and (not template)):
            # TODO get the template from the base_image
            pass
        # TODO: if there is no base_image, we need to wait while one is built.
        # we can probably use NotificationCenter and threading.Event to wait.

        template = template if(isinstance(template, Template)) else Template(template)
        self.os_plugin = PluginManager().plugin_for_target((template.os_name, template.os_version, template.os_arch))
        self.cloud_plugin = PluginManager().plugin_for_target(target)

        try:
            _should_create = self.cloud_plugin.builder_should_create_target_image(self, target, image_id, template, parameters)
        except AttributeError:
            _should_create = True
        try:
            if _should_create : self.cloud_plugin.builder_will_create_target_image(self, target, image_id, template, parameters)
        except AttributeError:
            pass
        if(_should_create):
            try:
                self.target_image = self.os_plugin.create_target_image(self, target, image, parameters)
                self.cloud_plugin.builder_did_create_target_image(self, target, image, template, parameters)
            except AttributeError:
                pass

##### CREATE PROVIDER IMAGE
    def create_image_on_provider(self, provider, credentials, image_id=None, template=None, parameters=None):
        if(parameters.get('snapshot', False)):
            self.snapshot_image_on_provider(provider, credentials, template, parameters)
        else:
            self.push_image_to_provider(provider, credentials, image_id, template, parameters)

##### PUSH IMAGE TO PROVIDER
    def push_image_to_provider(self, provider, credentials, image_id, template, parameters):
        """
        TODO: Docstring for push_image_to_provider

        @param image TODO
        @param provider TODO
        @param credentials TODO
        @param provider_params TODO

        @return TODO
        """
        thread_name = str(uuid.uuid4())[0:8]
        thread_kwargs = {'provider':provider, 'credentials':credentials, 'image_id':image_id, 'template':template, 'parameters':parameters}
        self.push_thread = Thread(target=self._push_image_to_provider, name=thread_name, args=None, kwargs=thread_kwargs)
        self.push_thread.start()

    def _push_image_to_provider(self, provider, credentials, image_id, template, parameters):
        # TODO: if there is no target_image, we need to wait while one is built.
        # we can probably use NotificationCenter and threading.Event to wait.
        self.cloud_plugin = PluginManager().plugin_for_target(Provider.map_provider_to_target(provider))
        target_image = None # TODO: either retrieve the image or build one.
        self.provider_image = self.cloud_plugin.push_image_to_provider(self, provider, credentials, target_image, parameters)

##### SNAPSHOT IMAGE
    def snapshot_image(self, provider, credentials, template, parameters):
        """
        TODO: Docstring for snapshot_image

        @param template TODO
        @param target TODO
        @param provider TODO
        @param credentials TODO
        @param snapshot_params TODO

        @return TODO
        """
        thread_name = str(uuid.uuid4())[0:8]
        thread_kwargs = {'provider':provider, 'credentials':credentials, 'template':template, 'parameters':parameters}
        self.snapshot_thread = Thread(target=self._snapshot_image, name=thread_name, args=None, kwargs=thread_kwargs)
        self.snapshot_thread.start()

    def _snapshot_image(self, provider, credentials, template, parameters):
        self.cloud_plugin = PluginManager().plugin_for_target(Provider.map_provider_to_target(provider))
        self.provider_image = self.cloud_plugin.snapshot_image_on_provider(self, provider, credentials, template, parameters)
<|endoftext|>


<commit_before>from functools import wraps

from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS
from PIL.ImageSequence import Iterator

__author__ = 'Anton Smolin'
__copyright__ = 'Copyright (C) 2017 Anton Smolin'
__license__ = 'MIT'
__version__ = '1.1.0'

class Img:
    __MODES = {
        '1': 'black and white',
        'L': 'grayscale',
        'LA': 'grayscale with transparency',
        'P': 'color palette',
        'RGB': 'true color',
        'RGBA': 'true color with transparency',
        'RGBX': 'true color with padding',
        'RGBa': 'true color with premultiplied alpha',
        'CMYK': 'color separation',
        'YCbCr': 'color video',
        'LAB': 'l*a*b color space',
        'HSV': 'hue, saturation, value color space',
        'I': 'signed integer pixels',
        'F': 'floating point pixels'
    }
    __METHODS = ('convert', 'crop', 'filter', 'paste', 'resize', 'rotate',
                 'thumbnail', 'transform', 'transpose')

    __image = None
    __exif = None
    __frames = None

    @property
    def info(self):
        return self.__image.info

    @property
    def exif(self):
        if self.__exif is None:
            self.__exif = {}

            try:
                for key, value in self.__image._getexif().items():
                    tag = TAGS.get(key, key)
                    if tag == 'GPSInfo':
                        value = {GPSTAGS.get(key_, key_): value_
                                 for key_, value_ in value.items()}
                    self.__exif[tag] = value
            except AttributeError:
                pass

        return self.__exif

    @property
    def format(self):
        return self.__image.format

    @property
    def width(self):
        if not self.__frames:
            return self.__image.width

        return self.__frames[0].width

    @property
    def height(self):
        if not self.__frames:
            return self.__image.height

        return self.__frames[0].height

    @property
    def mode(self):
        if not self.__frames:
            return self.__image.mode

        return self.__frames[0].mode

    @property
    def mode_desc(self):
        return self.__MODES.get(self.mode)

    @property
    def n_frames(self):
        if self.__frames:
            return len(self.__frames)

        try:
            return self.__image.n_frames
        except AttributeError:
            return 1

    @property
    def animated(self):
        return self.n_frames > 1

    @property
    def frames(self):
        if self.__frames is None:
            self.__frames = [frame.copy() for frame in Iterator(self.__image)]

        return self.__frames

    def __init__(self, *, fp):
        self.__image = Image.open(fp)

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.close()

    def __getattr__(self, name):
        if name not in self.__METHODS:
            raise AttributeError

        def proxy(*args, **kwargs):
            for index, frame in enumerate(self.frames):
                res = getattr(frame, name)(*args, **kwargs)
                if isinstance(res, Image.Image):
                    self.__frames[index] = res

        return proxy

    def save(self, *, fp):
        if not self.frames:
            return

        options = {'save_all': True, 'append_images': self.__frames[1:]} \
            if self.format == 'GIF' and self.animated else {}

        self.__frames[0].save(fp, format=self.format, **options)

    def close(self):
        self.__image.close()
<commit_msg>limit frames<commit_after>import random

from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS
from PIL.ImageSequence import Iterator

__author__ = 'Anton Smolin'
__copyright__ = 'Copyright (C) 2017 Anton Smolin'
__license__ = 'MIT'
__version__ = '1.1.0'

class Img:
    __MODES = {
        '1': 'black and white',
        'L': 'grayscale',
        'LA': 'grayscale with transparency',
        'P': 'color palette',
        'RGB': 'true color',
        'RGBA': 'true color with transparency',
        'RGBX': 'true color with padding',
        'RGBa': 'true color with premultiplied alpha',
        'CMYK': 'color separation',
        'YCbCr': 'color video',
        'LAB': 'l*a*b color space',
        'HSV': 'hue, saturation, value color space',
        'I': 'signed integer pixels',
        'F': 'floating point pixels'
    }
    __METHODS = ('convert', 'crop', 'filter', 'paste', 'resize', 'rotate',
                 'thumbnail', 'transform', 'transpose')

    __image = None
    __frame_limit = None
    __exif = None
    __frames = None

    @property
    def info(self):
        return self.__image.info

    @property
    def exif(self):
        if self.__exif is None:
            self.__exif = {}

            try:
                for key, value in self.__image._getexif().items():
                    tag = TAGS.get(key, key)
                    if tag == 'GPSInfo':
                        value = {GPSTAGS.get(key_, key_): value_
                                 for key_, value_ in value.items()}
                    self.__exif[tag] = value
            except AttributeError:
                pass

        return self.__exif

    @property
    def format(self):
        return self.__image.format

    @property
    def width(self):
        if not self.__frames:
            return self.__image.width

        return self.__frames[0].width

    @property
    def height(self):
        if not self.__frames:
            return self.__image.height

        return self.__frames[0].height

    @property
    def mode(self):
        if not self.__frames:
            return self.__image.mode

        return self.__frames[0].mode

    @property
    def mode_desc(self):
        return self.__MODES.get(self.mode)

    @property
    def n_frames(self):
        if self.__frames:
            return len(self.__frames)

        try:
            return self.__image.n_frames
        except AttributeError:
            return 1

    @property
    def animated(self):
        return self.n_frames > 1

    @property
    def frames(self):
        if self.__frames is None:
            indexes = list(range(self.n_frames))
            if self.__frame_limit:
                mix = indexes[1:]
                random.shuffle(mix)
                indexes[1:] = mix
                indexes = indexes[:self.__frame_limit]

            self.__frames = [
                frame.copy()
                for index, frame in enumerate(Iterator(self.__image))
                if index in set(indexes)]

        return self.__frames

    def __init__(self, *, fp, frame_limit=None):
        self.__image = Image.open(fp)
        self.__frame_limit = frame_limit

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.close()

    def __getattr__(self, name):
        if name not in self.__METHODS:
            raise AttributeError

        def proxy(*args, **kwargs):
            for index, frame in enumerate(self.frames):
                res = getattr(frame, name)(*args, **kwargs)
                if isinstance(res, Image.Image):
                    self.__frames[index] = res

        return proxy

    def save(self, *, fp):
        if not self.frames:
            return

        options = {'save_all': True, 'append_images': self.__frames[1:]} \
            if self.format == 'GIF' and self.animated else {}

        self.__frames[0].save(fp, format=self.format, **options)

    def close(self):
        self.__image.close()
<|endoftext|>


<commit_before># SCAR - Serverless Container-aware ARchitectures
# Copyright (C) GRyCAP - I3M - UPV
#
# 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.

import urllib
import json
import os
from subprocess import call, check_output

print('Loading function')

udocker_bin="/tmp/udocker/udocker"
lambda_output="/tmp/output"
script = "/tmp/udocker/script.sh"
name="c7"

def prepare_environment(file_retriever):
    # Install udocker in /tmp
    print check_output(["ls", "-l", "/var/task/"])
    call(["mkdir", "-p", "/tmp/udocker"])
    call(["cp", "/var/task/udocker", udocker_bin])
    call(["chmod", "u+rx", udocker_bin])
    call(["mkdir", "-p", "/tmp/home/.udocker"])

def prepare_container(container_image):
    # Download and create container
    call([udocker_bin, "pull", container_image])
    call([udocker_bin, "create", "--name="+name, container_image])
    # Set container execution engine to Fakechroot
    call([udocker_bin, "setup", "--execmode=F1", name])

def create_script(content):
    with open(script,"w") as f:
        f.write(content)

def lambda_handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))
    file_retriever = urllib.URLopener()
    prepare_environment(file_retriever)
    prepare_container(os.environ['IMAGE_ID'])
    create_script(event['script'])

    # Execute script
    call([udocker_bin, "run", "-v", "/tmp", "--nosysdirs", name, "/bin/sh", script])
    return check_output(["cat", lambda_output])
<commit_msg>Redirected stdout and stderr to a file<commit_after># SCAR - Serverless Container-aware ARchitectures
# Copyright (C) GRyCAP - I3M - UPV
#
# 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.

import urllib
import json
import os
from subprocess import call, check_output, STDOUT

print('Loading function')

udocker_bin="/tmp/udocker/udocker"
lambda_output="/tmp/lambda-stdout.txt"
script = "/tmp/udocker/script.sh"
name="c7"

def prepare_environment(file_retriever):
    # Install udocker in /tmp
    print check_output(["ls", "-l", "/var/task/"])
    call(["mkdir", "-p", "/tmp/udocker"])
    call(["cp", "/var/task/udocker", udocker_bin])
    call(["chmod", "u+rx", udocker_bin])
    call(["mkdir", "-p", "/tmp/home/.udocker"])

def prepare_container(container_image):
    # Download and create container
    call([udocker_bin, "pull", container_image])
    call([udocker_bin, "create", "--name="+name, container_image])
    # Set container execution engine to Fakechroot
    call([udocker_bin, "setup", "--execmode=F1", name])

def create_script(content):
    with open(script,"w") as f:
        f.write(content)

def lambda_handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))
    file_retriever = urllib.URLopener()
    prepare_environment(file_retriever)
    prepare_container(os.environ['IMAGE_ID'])
    create_script(event['script'])

    # Execute script
    call([udocker_bin, "run", "--rm", "-v", "/tmp", "--nosysdirs", name, "/bin/sh", script],
          stderr = STDOUT,
          stdout = open(lambda_output,"w"))

    stdout = check_output(["cat", lambda_output])
    print stdout
    return stdout
<|endoftext|>


<commit_before>#! /usr/bin/env python
"""
Read data from an ESRI ASCII file into a RasterModelGrid
"""

import os
import types
import re

import numpy as np

import landlab
from landlab import RasterModelGrid

_VALID_HEADER_KEYS = [
    'ncols', 'nrows', 'xllcorner', 'xllcenter', 'yllcorner',
    'yllcenter', 'cellsize', 'nodata_value',
]
_HEADER_REGEX_PATTERN = re.compile('\s*(?P<key>\w+)\s+(?P<value>[\w.+-]+)')
_HEADER_VALUE_TESTS = {
    'nrows': (int, lambda x: x > 0),
    'ncols': (int, lambda x: x > 0),
    'cellsize': (float, lambda x: x > 0),
    'xllcorner': (float, lambda x: True),
    'xllcenter': (float, lambda x: True),
    'yllcorner': (float, lambda x: True),
    'yllcenter': (float, lambda x: True),
    'nodata_value': (float, lambda x: True),
}

class Error(Exception):
    """
    Base class for errors in this module.
    """
    pass

class BadHeaderLineError(Error):
    """
    Raise this error if a bad header is line encounter in a ESRI ASCII
    file.
    """
    def __init__(self, line):
        self._line = line

    def __str__(self):
        return self._line

class MissingRequiredKeyError(Error):
    """
    Raise this error when a header is missing a required key.
    """
    def __init__(self, key):
        self._key = key

    def __str__(self):
        return self._key

class KeyTypeError(Error):
    """
    Raise this error when a header's key value is of the wrong type.
    """
    def __init__(self, key, expected_type):
        self._key = key
        self._type = str(expected_type)

    def __str__(self):
        return 'Unable to convert %s to %s' % (self._key, self._type)

class KeyValueError(Error):
    """
    Raise this error when a header's key value has a bad value
    """
    def __init__(self, key, message):
        self._key = key
        self._msg = message

    def __str__(self):
        return '%s: %s' % (self._key, self._msg)

class DataSizeError(Error):
    """
    Raise this error if the size of the data does not match that given in
    the header.
    """
    def __init__(self, size, expected_size):
        self._actual = size
        self._expected = expected_size

    def __str__(self):
        return '%s != %s' % (self._actual, self._expected)

def _parse_header_key_value(line):
    match = _HEADER_REGEX_PATTERN.match(line)
    if match is None:
        raise BadHeaderLineError(line)

    (key, value) = (match.group('key').lower(), match.group('value'))
    try:
        assert(key in _VALID_HEADER_KEYS)
    except AssertionError:
        raise BadHeaderLineError(line)
    else:
        return (key, value)

def _header_lines(asc_file):
    pos = asc_file.tell()
    line = asc_file.readline()
    while len(line) > 0:
        if len(line.strip()) > 0:
            try:
                (key, value) = _parse_header_key_value(line)
            except BadHeaderLineError:
                asc_file.seek(pos, 0)
                break
            else:
                yield (key, value)
        pos = asc_file.tell()
        line = asc_file.readline()

def _header_is_valid(header):
    header_keys = set(header)
    required_keys = set(['ncols', 'nrows', 'cellsize'])

    try:
        assert(required_keys.issubset(header_keys))
    except AssertionError:
        raise MissingRequiredKeyError(', '.join(required_keys - header_keys))

    for keys in [('xllcenter', 'xllcorner'), ('yllcenter', 'yllcorner')]:
        try:
            assert(len(set(keys) & header_keys) == 1)
        except AssertionError:
            raise MissingRequiredKeyError('|'.join(keys))

    for (key, requires) in _HEADER_VALUE_TESTS.items():
        try:
            header[key] = requires[0](header[key])
            assert(requires[1](header[key]))
        except ValueError:
            raise KeyTypeError(key, float)
        except AssertionError:
            raise KeyValueError(key, 'Bad value')
        except KeyError:
            pass

    return True

def read_asc_header(asc_file):
    """
    Read header information from an ESRI ASCII raster file.

    The header contains the following variables,
        - *ncols*: Number of cell columns
        - *nrows*: Number of cell rows
        - *xllcenter* or *xllcorner*: X (column) coordinate of lower-left
            coordinate of grid (by center or lower-left corner of the cell)
        - *yllcenter*, *yllcorner*: Y (row) coordinate of lower-left
            coordinate of grid (by center or lower-left corner of the cell)
        - *cellsize*: Grid spacing between rows and columns
        - *nodata_value*: No-data value (optional)
    """
    header = dict()
    for (key, value) in _header_lines(asc_file):
        header[key] = value

    try:
        _header_is_valid(header)
    except Error:
        raise

    return header

def _read_asc_data(asc_file, header={}):
    """
    Read gridded data from an ESRI ASCII data file.

    :asc_file: File-like object of the data file pointing to the start of the
               data.

    .. note::
        Row 1 of the data is at the top of the raster, row 2 is just under
        row 1, and so on.
    """
    #return np.fromtxt(asc_file, skiprows=len(header))
    try:
        return np.loadtxt(asc_file)
    except ValueError as error:
        print header
        print error
    #return np.genfromtxt(asc_file)

def read_esri_ascii(asc_file, reshape=False):
    """
    Read data from *asc_file*, an ESRI_ ASCII file, into a
    :py:class:`~landlab.RasterModelGrid`.  *asc_file* is either
    the name of the data file or is a file-like object.

    The grid and data read from the file are returned as a tuple
    (*grid*, *data*) where *grid* is an instance of
    :py:class:`~landlab.RasterModelGrid` and *data* is a numpy
    array of doubles with that has been reshaped to have the number of rows
    and columns given in the header.

    .. _ESRI: http://resources.esri.com/help/9.3/arcgisengine/java/GP_ToolRef/spatial_analyst_tools/esri_ascii_raster_format.htm
    """
    if isinstance(asc_file, types.StringTypes):
        file_name = asc_file
        with open(file_name, 'r') as asc_file:
            header = read_asc_header(asc_file)
            data = _read_asc_data(asc_file, header=header)
    else:
        header = read_asc_header(asc_file)
        data = _read_asc_data(asc_file, header=header)

    shape = (header['nrows'], header['ncols'])
    spacing = (header['cellsize'], header['cellsize'])
    origin = (header['xllcorner'], header['yllcorner'])

    try:
        assert(data.size == shape[0] * shape[1])
    except AssertionError:
        raise DataSizeError(shape[0] * shape[1], data.size)

    data.shape = shape
    data = np.flipud(data)
    if not reshape:
        data = data.flatten()

    grid = RasterModelGrid(num_rows=shape[0], num_cols=shape[1],
                           dx=spacing[0])

    return (grid, data)

def write_esri_ascii(path, fields, names=None, clobber=False):
    """Write landlab fields to ESRI ASCII.

    Write the data and grid information for *fields* to *path* in the ESRI
    ASCII format.

    Parameters
    ----------
    path : str
        Path to output file.
    fields : field-like
        Landlab field object that holds a grid and associated values.
    names : iterable of str, optional
        Names of the fields to include in the output file. If not provided,
        write all fields.
    clobber : boolean
        If *path* exists, clobber the existing file, otherwise raise an
        exception.

    Examples
    --------
    >>> import numpy as np
    >>> from landlab.testing.tools import cdtemp
    >>> from landlab import RasterModelGrid
    >>> from landlab.io.esri_ascii import write_esri_ascii

    >>> grid = RasterModelGrid(4, 5, dx=2.)
    >>> _ = grid.add_field('node', 'air__temperature', np.arange(20.))
    >>> with cdtemp() as _:
    ...     files = write_esri_ascii('test.asc', grid)
    >>> files
    ['test.asc']

    >>> _ = grid.add_field('node', 'land_surface__elevation', np.arange(20.))
    >>> with cdtemp() as _:
    ...     files = write_esri_ascii('test.asc', grid)
    >>> files.sort()
    >>> files
    ['test_air__temperature.asc', 'test_land_surface__elevation.asc']
    """
    if os.path.exists(path) and not clobber:
        raise ValueError('file exists')

    if isinstance(names, types.StringTypes):
        names = [names]

    names = names or fields.at_node.keys()

    if len(names) == 1:
        paths = [path]
    elif len(names) > 1:
        (base, ext) = os.path.splitext(path)
        paths = [base + '_' + name + ext for name in names]
    else:
        raise ValueError('no node fields to write')

    bad_names = set(names) - set(fields.at_node.keys())
    if len(bad_names) > 0:
        raise ValueError('unknown field name(s): %s' % ','.join(bad_names))

    header = {
        'ncols': fields.number_of_node_columns,
        'nrows': fields.number_of_node_rows,
        'xllcorner': fields.node_x[0],
        'yllcorner': fields.node_y[0],
        'cellsize': fields.dx,
    }

    for path, name in zip(paths, names):
        with open(path, 'w') as fp:
            for key, val in header.items():
                fp.write('%s %s%s' % (key, str(val), os.linesep))
            data = fields.at_node[name].reshape(header['nrows'],
                                                header['ncols'])
            np.savetxt(fp, data)
    return paths

def write_esri_ascii_from_raster_model_grid_data(grid, data_name=None,
                                                 data_array=None, xllc=0.,
                                                 yllc=0., nodata_value=-9999,
                                                 filename='landlab_esri_ascii_grid.asc'):
    """
    Creates a new ESRI-Ascii-grid format file(s) containing data attached to a
    RasterModelGrid.

    Parameters
    ----------

    grid : RasterModelGrid
        Grid on which data are organized
    data_name : string
        Name of data item belonging to grid (must give either this or data_array)
    data_array : Numpy 1D array with data corresponding to nodes
        Data to be output (must give either this or data_name)
    xllc, yllc : float or int
        x and y coordinates of grid's lower-left corner
    nodata_value : int or float
        Code used to represent a grid cell containing invalid/no data
    filename : string
        Name of file to create

    Returns
    -------
    None
    """

    # Make sure we've been passed a RasterModelGrid
    assert (type(grid) is landlab.grid.raster.RasterModelGrid), \
           '<grid> must be a Landlab RasterModelGrid'

    # Make sure user has specified either a data-item name or an array
    assert ((data_name is not None) or (data_array is not None)), \
            'Must pass a non-None value for either data_name or data_array'

    # If data_name specified, find data with that name at nodes. If not, then
    # use data_array. If that's not specified either, throw an exception.
    if data_name is not None:
        data = grid.at_node[data_name][::-1,:]
    else:
        data = data_array[::-1,:]

    # Open a new text file
    output_file = open(filename, 'w')

    # Write the header
    output_file.write('ncols        %d\n' % (grid.number_of_node_columns))
    output_file.write('nrows        %d\n' % (grid.number_of_node_rows))
    output_file.write('xllcorner    %.3f\n' % (xllc))
    output_file.write('yllcorner    %.3f\n' % (yllc))
    output_file.write('cellsize     %.3f\n' % (grid.dx))
    output_file.write('NODATA_value %.0f\n' % (nodata_value))

    # Write the data, row by row
    n = 0
    for r in range(grid.number_of_node_rows):
        for c in range(grid.number_of_node_columns):
            output_file.write('%.3f ' % (data[n]))
            n+=1
        output_file.write('\n')

    # Close the file
    output_file.close()
<commit_msg>Flip data before writing to file.<commit_after>#! /usr/bin/env python
"""
Read data from an ESRI ASCII file into a RasterModelGrid
"""

import os
import types
import re

import numpy as np

import landlab
from landlab import RasterModelGrid

_VALID_HEADER_KEYS = [
    'ncols', 'nrows', 'xllcorner', 'xllcenter', 'yllcorner',
    'yllcenter', 'cellsize', 'nodata_value',
]
_HEADER_REGEX_PATTERN = re.compile('\s*(?P<key>\w+)\s+(?P<value>[\w.+-]+)')
_HEADER_VALUE_TESTS = {
    'nrows': (int, lambda x: x > 0),
    'ncols': (int, lambda x: x > 0),
    'cellsize': (float, lambda x: x > 0),
    'xllcorner': (float, lambda x: True),
    'xllcenter': (float, lambda x: True),
    'yllcorner': (float, lambda x: True),
    'yllcenter': (float, lambda x: True),
    'nodata_value': (float, lambda x: True),
}

class Error(Exception):
    """
    Base class for errors in this module.
    """
    pass

class BadHeaderLineError(Error):
    """
    Raise this error if a bad header is line encounter in a ESRI ASCII
    file.
    """
    def __init__(self, line):
        self._line = line

    def __str__(self):
        return self._line

class MissingRequiredKeyError(Error):
    """
    Raise this error when a header is missing a required key.
    """
    def __init__(self, key):
        self._key = key

    def __str__(self):
        return self._key

class KeyTypeError(Error):
    """
    Raise this error when a header's key value is of the wrong type.
    """
    def __init__(self, key, expected_type):
        self._key = key
        self._type = str(expected_type)

    def __str__(self):
        return 'Unable to convert %s to %s' % (self._key, self._type)

class KeyValueError(Error):
    """
    Raise this error when a header's key value has a bad value
    """
    def __init__(self, key, message):
        self._key = key
        self._msg = message

    def __str__(self):
        return '%s: %s' % (self._key, self._msg)

class DataSizeError(Error):
    """
    Raise this error if the size of the data does not match that given in
    the header.
    """
    def __init__(self, size, expected_size):
        self._actual = size
        self._expected = expected_size

    def __str__(self):
        return '%s != %s' % (self._actual, self._expected)

def _parse_header_key_value(line):
    match = _HEADER_REGEX_PATTERN.match(line)
    if match is None:
        raise BadHeaderLineError(line)

    (key, value) = (match.group('key').lower(), match.group('value'))
    try:
        assert(key in _VALID_HEADER_KEYS)
    except AssertionError:
        raise BadHeaderLineError(line)
    else:
        return (key, value)

def _header_lines(asc_file):
    pos = asc_file.tell()
    line = asc_file.readline()
    while len(line) > 0:
        if len(line.strip()) > 0:
            try:
                (key, value) = _parse_header_key_value(line)
            except BadHeaderLineError:
                asc_file.seek(pos, 0)
                break
            else:
                yield (key, value)
        pos = asc_file.tell()
        line = asc_file.readline()

def _header_is_valid(header):
    header_keys = set(header)
    required_keys = set(['ncols', 'nrows', 'cellsize'])

    try:
        assert(required_keys.issubset(header_keys))
    except AssertionError:
        raise MissingRequiredKeyError(', '.join(required_keys - header_keys))

    for keys in [('xllcenter', 'xllcorner'), ('yllcenter', 'yllcorner')]:
        try:
            assert(len(set(keys) & header_keys) == 1)
        except AssertionError:
            raise MissingRequiredKeyError('|'.join(keys))

    for (key, requires) in _HEADER_VALUE_TESTS.items():
        try:
            header[key] = requires[0](header[key])
            assert(requires[1](header[key]))
        except ValueError:
            raise KeyTypeError(key, float)
        except AssertionError:
            raise KeyValueError(key, 'Bad value')
        except KeyError:
            pass

    return True

def read_asc_header(asc_file):
    """
    Read header information from an ESRI ASCII raster file.

    The header contains the following variables,
        - *ncols*: Number of cell columns
        - *nrows*: Number of cell rows
        - *xllcenter* or *xllcorner*: X (column) coordinate of lower-left
            coordinate of grid (by center or lower-left corner of the cell)
        - *yllcenter*, *yllcorner*: Y (row) coordinate of lower-left
            coordinate of grid (by center or lower-left corner of the cell)
        - *cellsize*: Grid spacing between rows and columns
        - *nodata_value*: No-data value (optional)
    """
    header = dict()
    for (key, value) in _header_lines(asc_file):
        header[key] = value

    try:
        _header_is_valid(header)
    except Error:
        raise

    return header

def _read_asc_data(asc_file, header={}):
    """
    Read gridded data from an ESRI ASCII data file.

    :asc_file: File-like object of the data file pointing to the start of the
               data.

    .. note::
        Row 1 of the data is at the top of the raster, row 2 is just under
        row 1, and so on.
    """
    #return np.fromtxt(asc_file, skiprows=len(header))
    try:
        return np.loadtxt(asc_file)
    except ValueError as error:
        print header
        print error
    #return np.genfromtxt(asc_file)

def read_esri_ascii(asc_file, reshape=False):
    """
    Read data from *asc_file*, an ESRI_ ASCII file, into a
    :py:class:`~landlab.RasterModelGrid`.  *asc_file* is either
    the name of the data file or is a file-like object.

    The grid and data read from the file are returned as a tuple
    (*grid*, *data*) where *grid* is an instance of
    :py:class:`~landlab.RasterModelGrid` and *data* is a numpy
    array of doubles with that has been reshaped to have the number of rows
    and columns given in the header.

    .. _ESRI: http://resources.esri.com/help/9.3/arcgisengine/java/GP_ToolRef/spatial_analyst_tools/esri_ascii_raster_format.htm
    """
    if isinstance(asc_file, types.StringTypes):
        file_name = asc_file
        with open(file_name, 'r') as asc_file:
            header = read_asc_header(asc_file)
            data = _read_asc_data(asc_file, header=header)
    else:
        header = read_asc_header(asc_file)
        data = _read_asc_data(asc_file, header=header)

    shape = (header['nrows'], header['ncols'])
    spacing = (header['cellsize'], header['cellsize'])
    origin = (header['xllcorner'], header['yllcorner'])

    try:
        assert(data.size == shape[0] * shape[1])
    except AssertionError:
        raise DataSizeError(shape[0] * shape[1], data.size)

    data.shape = shape
    data = np.flipud(data)
    if not reshape:
        data = data.flatten()

    grid = RasterModelGrid(num_rows=shape[0], num_cols=shape[1],
                           dx=spacing[0])

    return (grid, data)

def write_esri_ascii(path, fields, names=None, clobber=False):
    """Write landlab fields to ESRI ASCII.

    Write the data and grid information for *fields* to *path* in the ESRI
    ASCII format.

    Parameters
    ----------
    path : str
        Path to output file.
    fields : field-like
        Landlab field object that holds a grid and associated values.
    names : iterable of str, optional
        Names of the fields to include in the output file. If not provided,
        write all fields.
    clobber : boolean
        If *path* exists, clobber the existing file, otherwise raise an
        exception.

    Examples
    --------
    >>> import numpy as np
    >>> from landlab.testing.tools import cdtemp
    >>> from landlab import RasterModelGrid
    >>> from landlab.io.esri_ascii import write_esri_ascii

    >>> grid = RasterModelGrid(4, 5, dx=2.)
    >>> _ = grid.add_field('node', 'air__temperature', np.arange(20.))
    >>> with cdtemp() as _:
    ...     files = write_esri_ascii('test.asc', grid)
    >>> files
    ['test.asc']

    >>> _ = grid.add_field('node', 'land_surface__elevation', np.arange(20.))
    >>> with cdtemp() as _:
    ...     files = write_esri_ascii('test.asc', grid)
    >>> files.sort()
    >>> files
    ['test_air__temperature.asc', 'test_land_surface__elevation.asc']
    """
    if os.path.exists(path) and not clobber:
        raise ValueError('file exists')

    if isinstance(names, types.StringTypes):
        names = [names]

    names = names or fields.at_node.keys()

    if len(names) == 1:
        paths = [path]
    elif len(names) > 1:
        (base, ext) = os.path.splitext(path)
        paths = [base + '_' + name + ext for name in names]
    else:
        raise ValueError('no node fields to write')

    bad_names = set(names) - set(fields.at_node.keys())
    if len(bad_names) > 0:
        raise ValueError('unknown field name(s): %s' % ','.join(bad_names))

    header = {
        'ncols': fields.number_of_node_columns,
        'nrows': fields.number_of_node_rows,
        'xllcorner': fields.node_x[0],
        'yllcorner': fields.node_y[0],
        'cellsize': fields.dx,
    }

    for path, name in zip(paths, names):
        with open(path, 'w') as fp:
            for key, val in header.items():
                fp.write('%s %s%s' % (key, str(val), os.linesep))
            data = fields.at_node[name].reshape(header['nrows'],
                                                header['ncols'])
            np.savetxt(fp, np.flipud(data))

    return paths

def write_esri_ascii_from_raster_model_grid_data(grid, data_name=None,
                                                 data_array=None, xllc=0.,
                                                 yllc=0., nodata_value=-9999,
                                                 filename='landlab_esri_ascii_grid.asc'):
    """
    Creates a new ESRI-Ascii-grid format file(s) containing data attached to a
    RasterModelGrid.

    Parameters
    ----------

    grid : RasterModelGrid
        Grid on which data are organized
    data_name : string
        Name of data item belonging to grid (must give either this or data_array)
    data_array : Numpy 1D array with data corresponding to nodes
        Data to be output (must give either this or data_name)
    xllc, yllc : float or int
        x and y coordinates of grid's lower-left corner
    nodata_value : int or float
        Code used to represent a grid cell containing invalid/no data
    filename : string
        Name of file to create

    Returns
    -------
    None
    """

    # Make sure we've been passed a RasterModelGrid
    assert (type(grid) is landlab.grid.raster.RasterModelGrid), \
           '<grid> must be a Landlab RasterModelGrid'

    # Make sure user has specified either a data-item name or an array
    assert ((data_name is not None) or (data_array is not None)), \
            'Must pass a non-None value for either data_name or data_array'

    # If data_name specified, find data with that name at nodes. If not, then
    # use data_array. If that's not specified either, throw an exception.
    if data_name is not None:
        data = grid.at_node[data_name][::-1,:]
    else:
        data = data_array[::-1,:]

    # Open a new text file
    output_file = open(filename, 'w')

    # Write the header
    output_file.write('ncols        %d\n' % (grid.number_of_node_columns))
    output_file.write('nrows        %d\n' % (grid.number_of_node_rows))
    output_file.write('xllcorner    %.3f\n' % (xllc))
    output_file.write('yllcorner    %.3f\n' % (yllc))
    output_file.write('cellsize     %.3f\n' % (grid.dx))
    output_file.write('NODATA_value %.0f\n' % (nodata_value))

    # Write the data, row by row
    n = 0
    for r in range(grid.number_of_node_rows):
        for c in range(grid.number_of_node_columns):
            output_file.write('%.3f ' % (data[n]))
            n+=1
        output_file.write('\n')

    # Close the file
    output_file.close()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

from pyqtgraph.Qt import QtGui, QtCore
import numpy as np

class StatsWidget(QtGui.QWidget):

    def __init__(self, driver):
        super(StatsWidget, self).__init__()

        self.driver = driver

        self.layout = QtGui.QHBoxLayout()

        self.mean_labels = []
        self.ampl_labels = []
        self.n_channels = 2
        self.window_size = 50

        self.average = np.zeros(self.n_channels)
        self.amplitude = np.zeros(self.n_channels)

        self.average_vec = np.zeros((self.n_channels, self.window_size))
        self.amplitude_vec = np.zeros((self.n_channels, self.window_size))

        for i in range(self.n_channels):
            self.average_vec[i,:] = self.get_average(i)
            self.amplitude_vec[i,:] = self.get_amplitude(i)

        for i in range(self.n_channels+1):
            self.mean_labels.append(QtGui.QLabel(''))
            self.ampl_labels.append(QtGui.QLabel(''))
            self.mean_labels[i].setAlignment(QtCore.Qt.AlignCenter)
            self.ampl_labels[i].setAlignment(QtCore.Qt.AlignCenter)

        self.mean_labels[0].setText('Average')
        self.ampl_labels[0].setText('Peak-Peak')

        self.boxes = []
        self.box_names = ['Measures', 'ADC 1', 'ADC 2']
        for i in range(self.n_channels+1):
            self.boxes.append(QtGui.QGroupBox(self.box_names[i]))
            self.boxes[i].setAlignment(5)

        self.name_layout = QtGui.QVBoxLayout()
        self.name_layout.addWidget(self.mean_labels[0])
        self.name_layout.addWidget(self.ampl_labels[0])
        self.boxes[0].setLayout(self.name_layout)

        self.adc_1_layout = QtGui.QVBoxLayout()
        self.adc_1_layout.addWidget(self.mean_labels[1])
        self.adc_1_layout.addWidget(self.ampl_labels[1])
        self.boxes[1].setLayout(self.adc_1_layout)

        self.adc_2_layout = QtGui.QVBoxLayout()
        self.adc_2_layout.addWidget(self.mean_labels[2])
        self.adc_2_layout.addWidget(self.ampl_labels[2])
        self.boxes[2].setLayout(self.adc_2_layout)

        for i in range(self.n_channels+1):
            self.layout.addWidget(self.boxes[i])

    def get_average(self, channel):
        return np.mean(self.driver.adc[channel,:])

    def get_amplitude(self, channel):
        return np.max(self.driver.adc[channel,:])-np.min(self.driver.adc[channel,:])

    def update(self):
        self.average_vec = np.roll(self.average_vec, 1, axis=1)
        self.amplitude_vec = np.roll(self.amplitude_vec, 1, axis=1)
        for i in range(self.n_channels):
            self.average_vec[i,0] = self.get_average(i)
            self.amplitude_vec[i,0] = self.get_amplitude(i)

            self.average[i] = np.mean(self.average_vec[i,:])
            if 1e-2 < abs(self.average[i]) < 1e4:
                mean_text = '{:.2f}'.format(self.average[i])
            else:
                mean_text = '%.4e'%(self.average[i])
            self.mean_labels[i+1].setText(mean_text)

            self.amplitude[i] = np.mean(self.amplitude_vec[i,:])
            if 1e-2 < self.amplitude[i] < 1e4:
                ampl_text = '{:.2f}'.format(self.amplitude[i])
            else:
                ampl_text = '%.4e'%(self.amplitude[i])
            self.ampl_labels[i+1].setText(ampl_text)

<commit_msg>Add RMS value measure<commit_after># -*- coding: utf-8 -*-

from pyqtgraph.Qt import QtGui, QtCore
import numpy as np

class StatsWidget(QtGui.QWidget):

    def __init__(self, driver):
        super(StatsWidget, self).__init__()

        self.driver = driver

        self.layout = QtGui.QHBoxLayout()

        self.mean_labels = []
        self.ampl_labels = []
        self.ampl_rms_labels = []
        self.n_channels = 2
        self.window_size = 50

        self.average = np.zeros(self.n_channels)
        self.amplitude = np.zeros(self.n_channels)
        self.amplitude_rms = np.zeros(self.n_channels)

        self.average_vec = np.zeros((self.n_channels, self.window_size))
        self.amplitude_vec = np.zeros((self.n_channels, self.window_size))
        self.amplitude_rms_vec = np.zeros((self.n_channels, self.window_size))

        for i in range(self.n_channels):
            self.average_vec[i,:] = self.get_average(i)
            self.amplitude_vec[i,:] = self.get_amplitude(i)
            self.amplitude_rms_vec[i,:] = self.get_amplitude_rms(i)

        for i in range(self.n_channels+1):
            self.mean_labels.append(QtGui.QLabel(''))
            self.ampl_labels.append(QtGui.QLabel(''))
            self.ampl_rms_labels.append(QtGui.QLabel(''))
            self.mean_labels[i].setAlignment(QtCore.Qt.AlignCenter)
            self.ampl_labels[i].setAlignment(QtCore.Qt.AlignCenter)
            self.ampl_rms_labels[i].setAlignment(QtCore.Qt.AlignCenter)

        self.mean_labels[0].setText('Average')
        self.ampl_labels[0].setText('Peak-Peak')
        self.ampl_rms_labels[0].setText('RMS')

        self.boxes = []
        self.box_names = ['Measures', 'ADC 1', 'ADC 2']
        for i in range(self.n_channels+1):
            self.boxes.append(QtGui.QGroupBox(self.box_names[i]))
            self.boxes[i].setAlignment(5)

        self.name_layout = QtGui.QVBoxLayout()
        self.name_layout.addWidget(self.mean_labels[0])
        self.name_layout.addWidget(self.ampl_labels[0])
        self.name_layout.addWidget(self.ampl_rms_labels[0])
        self.boxes[0].setLayout(self.name_layout)

        self.adc_1_layout = QtGui.QVBoxLayout()
        self.adc_1_layout.addWidget(self.mean_labels[1])
        self.adc_1_layout.addWidget(self.ampl_labels[1])
        self.adc_1_layout.addWidget(self.ampl_rms_labels[1])
        self.boxes[1].setLayout(self.adc_1_layout)

        self.adc_2_layout = QtGui.QVBoxLayout()
        self.adc_2_layout.addWidget(self.mean_labels[2])
        self.adc_2_layout.addWidget(self.ampl_labels[2])
        self.adc_2_layout.addWidget(self.ampl_rms_labels[2])
        self.boxes[2].setLayout(self.adc_2_layout)

        for i in range(self.n_channels+1):
            self.layout.addWidget(self.boxes[i])

    def get_average(self, channel):
        return np.mean(self.driver.adc[channel,:])

    def get_amplitude(self, channel):
        return np.max(self.driver.adc[channel,:])-np.min(self.driver.adc[channel,:])

    def get_amplitude_rms(self, channel):
        return np.std(self.driver.adc[channel,:])

    def update(self):
        self.average_vec = np.roll(self.average_vec, 1, axis=1)
        self.amplitude_vec = np.roll(self.amplitude_vec, 1, axis=1)
        self.amplitude_rms_vec = np.roll(self.amplitude_rms_vec, 1, axis=1)

        for i in range(self.n_channels):
            self.average_vec[i,0] = self.get_average(i)
            self.amplitude_vec[i,0] = self.get_amplitude(i)
            self.amplitude_rms_vec[i,0] = self.get_amplitude_rms(i)

            self.average[i] = np.mean(self.average_vec[i,:])
            if 1e-2 < abs(self.average[i]) < 1e4:
                mean_text = '{:.2f}'.format(self.average[i])
            else:
                mean_text = '%.4e'%(self.average[i])
            self.mean_labels[i+1].setText(mean_text)

            self.amplitude[i] = np.mean(self.amplitude_vec[i,:])
            if 1e-2 < self.amplitude[i] < 1e4:
                ampl_text = '{:.2f}'.format(self.amplitude[i])
            else:
                ampl_text = '%.4e'%(self.amplitude[i])
            self.ampl_labels[i+1].setText(ampl_text)

            self.amplitude_rms[i] = np.mean(self.amplitude_rms_vec[i,:])
            if 1e-2 < self.amplitude_rms[i] < 1e4:
                ampl_rms_text = '{:.2f}'.format(self.amplitude_rms[i])
            else:
                ampl_rms_text = '%.4e'%(self.amplitude_rms[i])
            self.ampl_rms_labels[i+1].setText(ampl_rms_text)

<|endoftext|>