<commit_before>"""
I/O functions: reading and writing molecules.
"""

__author__ = "Steven Kearnes"
__copyright__ = "Copyright 2014, Stanford University"
__license__ = "3-clause BSD"

import gzip

from rdkit import Chem
from rdkit.Chem.SaltRemover import SaltRemover

def guess_mol_format(filename):
    """
    Guess molecule file format from filename. Currently supports SDF and
    SMILES.

    Parameters
    ----------
    filename : str
        Filename.
    """
    if filename.endswith(('.sdf', '.sdf.gz')):
        mol_format = 'sdf'
    elif filename.endswith(('.smi', '.smi.gz', '.can', '.can.gz',
                            '.ism', '.ism.gz')):
        mol_format = 'smi'
    else:
        raise NotImplementedError('Unrecognized file format.')
    return mol_format

class MolReader(object):
    """
    Read molecules from files and file-like objects. Supports SDF or SMILES
    format.

    Parameters
    ----------
    remove_salts : bool, optional (default True)
        Whether to remove salts from molecules.
    """
    def __init__(self, remove_salts=True):
        self.remove_salts = remove_salts
        self.salt_remover = SaltRemover()

    def clean_mol(self, mol):
        """
        Clean a molecule.

        Parameters
        ----------
        mol : RDKit Mol
            Molecule.
        """
        if self.remove_salts:
            mol = self.salt_remover.StripMol(mol)
        return mol

    def read_mols_from_file(self, filename, mol_format=None):
        """
        Read molecules from a file.

        Parameters
        ----------
        filename : str
            Filename.
        mol_format : str, optional
            Molecule file format. Currently supports 'sdf' and 'smi'. If
            not provided, this method will attempt to infer it from the
            filename.

        Returns
        -------
        A generator yielding multi-conformer RDKit Mol objects.
        """
        if mol_format is None:
            mol_format = guess_mol_format(filename)
        if filename.endswith('.gz'):
            f = gzip.open(filename)
        else:
            f = open(filename)
        for mol in self.read_mols(f, mol_format=mol_format):
            yield mol
        f.close()

    def read_mols(self, f, mol_format):
        """
        Read molecules from a file-like object.

        Molecule conformers are grouped into a single molecule. Two
        molecules are considered conformers of the same molecule if they:
        * Are contiguous in the file
        * Have identical (canonical isomeric) SMILES strings
        * Have identical compound names (if set)

        Parameters
        ----------
        f : file
            File-like object.
        mol_format : str
            Molecule file format. Currently supports 'sdf' and 'smi'.

        Returns
        -------
        A generator yielding multi-conformer RDKit Mol objects.
        """
        source = self._read_mols(f, mol_format)
        parent = None
        for mol in source:
            assert mol.GetNumConformers() == 1
            if parent is None:
                parent = mol
                continue
            if self.is_same_molecule(parent, mol):
                for conf in mol.GetConformers():
                    parent.AddConformer(conf, assignId=True)
            else:
                parent = self.clean_mol(parent)
                yield parent
                parent = mol
        parent = self.clean_mol(parent)
        yield parent

    def _read_mols(self, f, mol_format):
        """
        Read molecules from a file-like object.

        This method returns individual conformers from a file and does not
        attempt to combine them into multiconformer Mol objects.

        Parameters
        ----------
        f : file
            File-like object.
        mol_format : str
            Molecule file format. Currently supports 'sdf' and 'smi'.

        Returns
        -------
        A generator yielding single-conformer Mol objects.
        """
        if mol_format == 'sdf':
            for mol in Chem.ForwardSDMolSupplier(f):
                yield mol
        elif mol_format == 'smi':
            for line in f.readlines():
                line = line.strip().split()
                if len(line) > 1:
                    smiles, name = line
                else:
                    smiles = line
                    name = None
                mol = Chem.MolFromSmiles(smiles)
                if name is not None:
                    mol.SetProp('_Name', name)
                yield mol
        else:
            raise NotImplementedError('Unrecognized mol_format "{}"'.format(
                mol_format))

    def is_same_molecule(self, a, b):
        """
        Test whether two molecules are conformers of the same molecule.

        Test for:
        * Identical (canonical isomeric) SMILES strings
        * Identical compound names (if set)

        Parameters
        ----------
        a, b : RDKit Mol
            Molecules to compare.
        """
        a_name = None
        if a.HasProp('_Name'):
            a_name = a.GetProp('_Name')
        b_name = None
        if b.HasProp('_Name'):
            b_name = b.GetProp('_Name')
        a_smiles = Chem.MolToSmiles(a, isomericSmiles=True, canonical=True)
        b_smiles = Chem.MolToSmiles(b, isomericSmiles=True, canonical=True)
        assert a_smiles and b_smiles
        return a_smiles == b_smiles and a_name == b_name

class MolWriter(object):
    """
    Write molecules to files or file-like objects. Supports SDF or SMILES
    format.

    Parameters
    ----------
    f : file, optional
        File-like object.
    mol_format : str, optional
        Molecule file format. Currently supports 'sdf' and 'smi'.
    """
    def __init__(self, f=None, mol_format=None):
        self.f = f
        self.mol_format = mol_format

    def __del__(self):
        self.close()

    def open(self, filename, mol_format=None):
        """
        Open output file.

        Parameters
        ----------
        filename : str
            Filename.
        mol_format : str, optional
            Molecule file format. Currently supports 'sdf' and 'smi'.
        """
        if filename.endswith('.gz'):
            self.f = gzip.open(filename, 'wb')
        else:
            self.f = open(filename, 'wb')
        if mol_format is None:
            self.mol_format = guess_mol_format(filename)
        else:
            self.mol_format = mol_format

    def close(self):
        """
        Close output file.
        """
        if self.f is not None:
            self.f.close()

    def write(self, mols):
        """
        Write molecules to a file.

        Parameters
        ----------
        mols : iterable
            Molecules to write.
        """
        if self.mol_format == 'sdf':
            w = Chem.SDWriter(self.f)
            for mol in mols:
                if mol.GetNumConformers():
                    for conf in mol.GetConformers():
                        w.write(mol, confId=conf.GetId())
                else:
                    w.write(mol)
            w.close()
        elif self.mol_format == 'smi':
            w = Chem.SmilesWriter(self.f)
            for mol in mols:
                w.write(mol)
            w.close()
<commit_msg>Add sanitize and remove_hydrogens options to MolReader<commit_after>"""
I/O functions: reading and writing molecules.
"""

__author__ = "Steven Kearnes"
__copyright__ = "Copyright 2014, Stanford University"
__license__ = "3-clause BSD"

import gzip

from rdkit import Chem
from rdkit.Chem.SaltRemover import SaltRemover

def guess_mol_format(filename):
    """
    Guess molecule file format from filename. Currently supports SDF and
    SMILES.

    Parameters
    ----------
    filename : str
        Filename.
    """
    if filename.endswith(('.sdf', '.sdf.gz')):
        mol_format = 'sdf'
    elif filename.endswith(('.smi', '.smi.gz', '.can', '.can.gz',
                            '.ism', '.ism.gz')):
        mol_format = 'smi'
    else:
        raise NotImplementedError('Unrecognized file format.')
    return mol_format

class MolReader(object):
    """
    Read molecules from files and file-like objects. Supports SDF or SMILES
    format.

    Parameters
    ----------
    sanitize : bool, optional (default True)
        Whether to sanitize molecules. Note that sanitization is triggered
        automatically if hydrogens are removed.
    remove_hydrogens : bool, optional (default False)
        Whether to remove hydrogens from molecules.
    remove_salts : bool, optional (default True)
        Whether to remove salts from molecules.
    """
    def __init__(self, sanitize=True, remove_hydrogens=False,
                 remove_salts=True):
        self.sanitize = sanitize
        self.remove_hydrogens = remove_hydrogens
        self.remove_salts = remove_salts
        self.salt_remover = SaltRemover()

    def clean_mol(self, mol):
        """
        Clean a molecule.

        Parameters
        ----------
        mol : RDKit Mol
            Molecule.
        """
        if self.remove_salts:
            mol = self.salt_remover.StripMol(mol)
        return mol

    def read_mols_from_file(self, filename, mol_format=None):
        """
        Read molecules from a file.

        Parameters
        ----------
        filename : str
            Filename.
        mol_format : str, optional
            Molecule file format. Currently supports 'sdf' and 'smi'. If
            not provided, this method will attempt to infer it from the
            filename.

        Returns
        -------
        A generator yielding multi-conformer RDKit Mol objects.
        """
        if mol_format is None:
            mol_format = guess_mol_format(filename)
        if filename.endswith('.gz'):
            f = gzip.open(filename)
        else:
            f = open(filename)
        for mol in self.read_mols(f, mol_format=mol_format):
            yield mol
        f.close()

    def read_mols(self, f, mol_format):
        """
        Read molecules from a file-like object.

        Molecule conformers are grouped into a single molecule. Two
        molecules are considered conformers of the same molecule if they:
        * Are contiguous in the file
        * Have identical (canonical isomeric) SMILES strings
        * Have identical compound names (if set)

        Parameters
        ----------
        f : file
            File-like object.
        mol_format : str
            Molecule file format. Currently supports 'sdf' and 'smi'.

        Returns
        -------
        A generator yielding multi-conformer RDKit Mol objects.
        """
        source = self._read_mols(f, mol_format)
        parent = None
        for mol in source:
            assert mol.GetNumConformers() == 1
            if parent is None:
                parent = mol
                continue
            if self.is_same_molecule(parent, mol):
                for conf in mol.GetConformers():
                    parent.AddConformer(conf, assignId=True)
            else:
                parent = self.clean_mol(parent)
                yield parent
                parent = mol
        parent = self.clean_mol(parent)
        yield parent

    def _read_mols(self, f, mol_format):
        """
        Read molecules from a file-like object.

        This method returns individual conformers from a file and does not
        attempt to combine them into multiconformer Mol objects.

        Parameters
        ----------
        f : file
            File-like object.
        mol_format : str
            Molecule file format. Currently supports 'sdf' and 'smi'.

        Returns
        -------
        A generator yielding single-conformer Mol objects.
        """
        if mol_format == 'sdf':
            return self._read_sdf(f)
        elif mol_format == 'smi':
            return self._read_smiles(f)
        else:
            raise NotImplementedError('Unrecognized mol_format "{}"'.format(
                mol_format))

    def _read_sdf(self, f):
        """
        Read SDF molecules from a file-like object.

        Parameters
        ----------
        f : file
            File-like object.
        """
        supplier = Chem.ForwardSDMolSupplier(
            f, sanitize=self.sanitize, removeHs=self.remove_hydrogens)
        for mol in supplier:
            yield mol

    def _read_smiles(self, f):
        """
        Read SMILES molecules from a file-like object.

        Parameters
        ----------
        f : file
            File-like object.
        """
        for line in f.readlines():
            line = line.strip().split()
            if len(line) > 1:
                smiles, name = line
            else:
                smiles = line
                name = None
            if self.remove_hydrogens:
                mol = Chem.MolFromSmiles(smiles)
            else:

                # sanitization is normally triggered by removing
                # hydrogens
                mol = Chem.MolFromSmiles(smiles, sanitize=False)
                if self.sanitize:
                    Chem.SanitizeMol(mol)

            if name is not None:
                mol.SetProp('_Name', name)
            yield mol

    def is_same_molecule(self, a, b):
        """
        Test whether two molecules are conformers of the same molecule.

        Test for:
        * Identical (canonical isomeric) SMILES strings
        * Identical compound names (if set)

        Parameters
        ----------
        a, b : RDKit Mol
            Molecules to compare.
        """
        a_name = None
        if a.HasProp('_Name'):
            a_name = a.GetProp('_Name')
        b_name = None
        if b.HasProp('_Name'):
            b_name = b.GetProp('_Name')
        a_smiles = Chem.MolToSmiles(a, isomericSmiles=True, canonical=True)
        b_smiles = Chem.MolToSmiles(b, isomericSmiles=True, canonical=True)
        assert a_smiles and b_smiles
        return a_smiles == b_smiles and a_name == b_name

class MolWriter(object):
    """
    Write molecules to files or file-like objects. Supports SDF or SMILES
    format.

    Parameters
    ----------
    f : file, optional
        File-like object.
    mol_format : str, optional
        Molecule file format. Currently supports 'sdf' and 'smi'.
    """
    def __init__(self, f=None, mol_format=None):
        self.f = f
        self.mol_format = mol_format

    def __del__(self):
        self.close()

    def open(self, filename, mol_format=None):
        """
        Open output file.

        Parameters
        ----------
        filename : str
            Filename.
        mol_format : str, optional
            Molecule file format. Currently supports 'sdf' and 'smi'.
        """
        if filename.endswith('.gz'):
            self.f = gzip.open(filename, 'wb')
        else:
            self.f = open(filename, 'wb')
        if mol_format is None:
            self.mol_format = guess_mol_format(filename)
        else:
            self.mol_format = mol_format

    def close(self):
        """
        Close output file.
        """
        if self.f is not None:
            self.f.close()

    def write(self, mols):
        """
        Write molecules to a file.

        Parameters
        ----------
        mols : iterable
            Molecules to write.
        """
        if self.mol_format == 'sdf':
            w = Chem.SDWriter(self.f)
            for mol in mols:
                if mol.GetNumConformers():
                    for conf in mol.GetConformers():
                        w.write(mol, confId=conf.GetId())
                else:
                    w.write(mol)
            w.close()
        elif self.mol_format == 'smi':
            w = Chem.SmilesWriter(self.f)
            for mol in mols:
                w.write(mol)
            w.close()
<|endoftext|>


<commit_before># Copyright 2014 The Bazel 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.

load("@io_bazel_rules_go//go/private:go_repository.bzl", "go_repository", "env_execute")

_GO_REPOSITORY_TOOLS_BUILD_FILE = """
package(default_visibility = ["//visibility:public"])

filegroup(
    name = "fetch_repo",
    srcs = ["bin/fetch_repo"],
)

filegroup(
    name = "gazelle",
    srcs = ["bin/gazelle"],
)
"""

def _go_repository_tools_impl(ctx):
  # We work this out here because you can't use a toolchain from a repository rule
  if ctx.os.name == 'linux':
    go_tool = ctx.path(Label("@go1_8_3_linux_amd64//:bin/go"))
  elif ctx.os.name == 'mac os x':
    go_tool = ctx.path(Label("@go1_8_3_darwin_amd64//:bin/go"))
  else:
    fail("Unsupported operating system: " + ctx.os.name)

  x_tools_commit = "3d92dd60033c312e3ae7cac319c792271cf67e37"
  x_tools_path = ctx.path('tools-' + x_tools_commit)
  buildtools_path = ctx.path(ctx.attr._buildtools).dirname
  go_tools_path = ctx.path(ctx.attr._tools).dirname

  # We have to download this directly because the normal version is based on go_repository
  # and thus requires the gazelle we build in here to generate it's BUILD files
  # The commit used here should match the one in repositories.bzl
  ctx.download_and_extract(
      url = "https://codeload.github.com/golang/tools/zip/" + x_tools_commit,
      type = "zip",
  )

  # Build something that looks like a normal GOPATH so go install will work
  ctx.symlink(x_tools_path, "src/golang.org/x/tools")
  ctx.symlink(buildtools_path, "src/github.com/bazelbuild/buildtools")
  ctx.symlink(go_tools_path, "src/github.com/bazelbuild/rules_go/go/tools")
  env = {
    'GOROOT': str(go_tool.dirname.dirname),
    'GOPATH': str(ctx.path('')),
  }

  # build gazelle and fetch_repo
  result = env_execute(ctx, [go_tool, "install", 'github.com/bazelbuild/rules_go/go/tools/gazelle/gazelle'], environment = env)
  if result.return_code:
      fail("failed to build gazelle: %s" % result.stderr)
  result = env_execute(ctx, [go_tool, "install", 'github.com/bazelbuild/rules_go/go/tools/fetch_repo'], environment = env)
  if result.return_code:
      fail("failed to build fetch_repo: %s" % result.stderr)

  # add a build file to export the tools
  ctx.file('BUILD.bazel', _GO_REPOSITORY_TOOLS_BUILD_FILE, False)

go_repository_tools = repository_rule(
    _go_repository_tools_impl,
    attrs = {
        "_tools": attr.label(
            default = Label("//go/tools:BUILD.bazel"),
            allow_files = True,
            single_file = True,
        ),
        "_buildtools": attr.label(
            default = Label("@com_github_bazelbuild_buildtools//:WORKSPACE"),
            allow_files = True,
            single_file = True,
        ),
    },
)
<commit_msg>Allow the sdk used by repository tools to be overriden, and have the default match the normal sdk default (#786)<commit_after># Copyright 2014 The Bazel 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.

load("@io_bazel_rules_go//go/private:go_repository.bzl", "go_repository", "env_execute")
load("@io_bazel_rules_go//go/toolchain:toolchains.bzl", "DEFAULT_VERSION")

_GO_REPOSITORY_TOOLS_BUILD_FILE = """
package(default_visibility = ["//visibility:public"])

filegroup(
    name = "fetch_repo",
    srcs = ["bin/fetch_repo"],
)

filegroup(
    name = "gazelle",
    srcs = ["bin/gazelle"],
)
"""

def _go_repository_tools_impl(ctx):
  # We work this out here because you can't use a toolchain from a repository rule
  # TODO: This is an ugly non sustainable hack, we need to kill repository tools.

  version = DEFAULT_VERSION.replace(".", "_")
  go_sdk = None
  if ctx.os.name == 'linux':
    go_sdk = ctx.attr.linux_sdk if ctx.attr.linux_sdk else "go{}_linux_amd64".format(version)
  elif ctx.os.name == 'mac os x':
    go_sdk = ctx.attr.linux_sdk if ctx.attr.linux_sdk else "go{}_darwin_amd64".format(version)
  else:
      fail("Unsupported operating system: " + ctx.os.name)
  go_tool = ctx.path(Label("@{}//:bin/go".format(go_sdk)))

  x_tools_commit = "3d92dd60033c312e3ae7cac319c792271cf67e37"
  x_tools_path = ctx.path('tools-' + x_tools_commit)
  buildtools_path = ctx.path(ctx.attr._buildtools).dirname
  go_tools_path = ctx.path(ctx.attr._tools).dirname

  # We have to download this directly because the normal version is based on go_repository
  # and thus requires the gazelle we build in here to generate it's BUILD files
  # The commit used here should match the one in repositories.bzl
  ctx.download_and_extract(
      url = "https://codeload.github.com/golang/tools/zip/" + x_tools_commit,
      type = "zip",
  )

  # Build something that looks like a normal GOPATH so go install will work
  ctx.symlink(x_tools_path, "src/golang.org/x/tools")
  ctx.symlink(buildtools_path, "src/github.com/bazelbuild/buildtools")
  ctx.symlink(go_tools_path, "src/github.com/bazelbuild/rules_go/go/tools")
  env = {
    'GOROOT': str(go_tool.dirname.dirname),
    'GOPATH': str(ctx.path('')),
  }

  # build gazelle and fetch_repo
  result = env_execute(ctx, [go_tool, "install", 'github.com/bazelbuild/rules_go/go/tools/gazelle/gazelle'], environment = env)
  if result.return_code:
      fail("failed to build gazelle: %s" % result.stderr)
  result = env_execute(ctx, [go_tool, "install", 'github.com/bazelbuild/rules_go/go/tools/fetch_repo'], environment = env)
  if result.return_code:
      fail("failed to build fetch_repo: %s" % result.stderr)

  # add a build file to export the tools
  ctx.file('BUILD.bazel', _GO_REPOSITORY_TOOLS_BUILD_FILE, False)

go_repository_tools = repository_rule(
    _go_repository_tools_impl,
    attrs = {
        "linux_sdk": attr.string(),
        "darwin_sdk": attr.string(),
        "_tools": attr.label(
            default = Label("//go/tools:BUILD.bazel"),
            allow_files = True,
            single_file = True,
        ),
        "_buildtools": attr.label(
            default = Label("@com_github_bazelbuild_buildtools//:WORKSPACE"),
            allow_files = True,
            single_file = True,
        ),
    },
)
<|endoftext|>


<commit_before>"""
byceps.services.user.models.user
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:Copyright: 2006-2017 Jochen Kupperschmidt
:License: Modified BSD, see LICENSE for details.
"""

from collections import namedtuple
from datetime import datetime
from enum import Enum
from typing import Optional, Set
from uuid import UUID

from flask import g
from sqlalchemy.ext.associationproxy import association_proxy

from ....database import db, generate_uuid
from ....typing import PartyID
from ....util.instances import ReprBuilder

from ...user_avatar.models import AvatarSelection

GUEST_USER_ID = UUID('00000000-0000-0000-0000-000000000000')

class AnonymousUser:

    id = GUEST_USER_ID
    enabled = False

    @property
    def is_anonymous(self) -> bool:
        return True

    @property
    def is_active(self) -> bool:
        return False

    def has_permission(self, permission: Enum) -> bool:
        return False

    def has_any_permission(self, *permissions: Set[Enum]) -> bool:
        return False

    @property
    def avatar(self) -> None:
        return None

    @property
    def avatar_url(self) -> None:
        return None

    @property
    def is_orga(self) -> bool:
        return False

    def is_orga_for_party(self, party_id: PartyID) -> bool:
        return False

    def __eq__(self, other) -> bool:
        return self.id == other.id

    def __repr__(self) -> str:
        return ReprBuilder(self) \
            .add_with_lookup('id') \
            .build()

class User(db.Model):
    """A user."""
    __tablename__ = 'users'

    id = db.Column(db.Uuid, default=generate_uuid, primary_key=True)
    created_at = db.Column(db.DateTime, default=datetime.now, nullable=False)
    screen_name = db.Column(db.Unicode(40), unique=True, nullable=False)
    email_address = db.Column(db.Unicode(80), unique=True, nullable=False)
    enabled = db.Column(db.Boolean, default=False, nullable=False)
    deleted = db.Column(db.Boolean, default=False, nullable=False)
    legacy_id = db.Column(db.Integer)

    avatar = association_proxy('avatar_selection', 'avatar',
                               creator=lambda avatar:
                                    AvatarSelection(None, avatar.id))

    def __init__(self, screen_name: str, email_address: str) -> None:
        self.screen_name = screen_name
        self.email_address = email_address

    @property
    def is_anonymous(self) -> bool:
        return False

    @property
    def is_active(self) -> bool:
        return self.enabled

    @property
    def avatar_url(self) -> Optional[str]:
        avatar = self.avatar
        return avatar.url if (avatar is not None) else None

    def has_permission(self, permission: Enum) -> bool:
        return permission in self.permissions

    def has_any_permission(self, *permissions: Set[Enum]) -> bool:
        return any(map(self.has_permission, permissions))

    @property
    def is_orga(self) -> bool:
        party = getattr(g, 'party', None)
        return (party is not None) and self.is_orga_for_party(party.id)

    def is_orga_for_party(self, party_id: PartyID) -> bool:
        party_ids = {ms.orga_team.party_id for ms in self.orga_team_memberships}
        return party_id in party_ids

    def __eq__(self, other) -> bool:
        return (other is not None) and (self.id == other.id)

    def __hash__(self) -> int:
        if self.id is None:
            raise ValueError('User instance is unhashable because its id is None.')

        return hash(self.id)

    def __repr__(self) -> str:
        return ReprBuilder(self) \
            .add_with_lookup('id') \
            .add_with_lookup('screen_name') \
            .build()

UserTuple = namedtuple('UserTuple', 'id, screen_name, deleted, avatar_url, is_orga')
<commit_msg>Reuse simplified query to determine a user's orga team membership for a specific party<commit_after>"""
byceps.services.user.models.user
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:Copyright: 2006-2017 Jochen Kupperschmidt
:License: Modified BSD, see LICENSE for details.
"""

from collections import namedtuple
from datetime import datetime
from enum import Enum
from typing import Optional, Set
from uuid import UUID

from flask import g
from sqlalchemy.ext.associationproxy import association_proxy

from ....database import db, generate_uuid
from ....typing import PartyID
from ....util.instances import ReprBuilder

from ...user_avatar.models import AvatarSelection

GUEST_USER_ID = UUID('00000000-0000-0000-0000-000000000000')

class AnonymousUser:

    id = GUEST_USER_ID
    enabled = False

    @property
    def is_anonymous(self) -> bool:
        return True

    @property
    def is_active(self) -> bool:
        return False

    def has_permission(self, permission: Enum) -> bool:
        return False

    def has_any_permission(self, *permissions: Set[Enum]) -> bool:
        return False

    @property
    def avatar(self) -> None:
        return None

    @property
    def avatar_url(self) -> None:
        return None

    @property
    def is_orga(self) -> bool:
        return False

    def is_orga_for_party(self, party_id: PartyID) -> bool:
        return False

    def __eq__(self, other) -> bool:
        return self.id == other.id

    def __repr__(self) -> str:
        return ReprBuilder(self) \
            .add_with_lookup('id') \
            .build()

class User(db.Model):
    """A user."""
    __tablename__ = 'users'

    id = db.Column(db.Uuid, default=generate_uuid, primary_key=True)
    created_at = db.Column(db.DateTime, default=datetime.now, nullable=False)
    screen_name = db.Column(db.Unicode(40), unique=True, nullable=False)
    email_address = db.Column(db.Unicode(80), unique=True, nullable=False)
    enabled = db.Column(db.Boolean, default=False, nullable=False)
    deleted = db.Column(db.Boolean, default=False, nullable=False)
    legacy_id = db.Column(db.Integer)

    avatar = association_proxy('avatar_selection', 'avatar',
                               creator=lambda avatar:
                                    AvatarSelection(None, avatar.id))

    def __init__(self, screen_name: str, email_address: str) -> None:
        self.screen_name = screen_name
        self.email_address = email_address

    @property
    def is_anonymous(self) -> bool:
        return False

    @property
    def is_active(self) -> bool:
        return self.enabled

    @property
    def avatar_url(self) -> Optional[str]:
        avatar = self.avatar
        return avatar.url if (avatar is not None) else None

    def has_permission(self, permission: Enum) -> bool:
        return permission in self.permissions

    def has_any_permission(self, *permissions: Set[Enum]) -> bool:
        return any(map(self.has_permission, permissions))

    @property
    def is_orga(self) -> bool:
        party = getattr(g, 'party', None)
        return (party is not None) and self.is_orga_for_party(party.id)

    def is_orga_for_party(self, party_id: PartyID) -> bool:
        from ...orga_team import service as orga_team_service
        return orga_team_service.is_orga_for_party(self.id, party_id)

    def __eq__(self, other) -> bool:
        return (other is not None) and (self.id == other.id)

    def __hash__(self) -> int:
        if self.id is None:
            raise ValueError('User instance is unhashable because its id is None.')

        return hash(self.id)

    def __repr__(self) -> str:
        return ReprBuilder(self) \
            .add_with_lookup('id') \
            .add_with_lookup('screen_name') \
            .build()

UserTuple = namedtuple('UserTuple', 'id, screen_name, deleted, avatar_url, is_orga')
<|endoftext|>


<commit_before>from django.contrib import admin
from django.utils.safestring import mark_safe
from models import Tweet, SearchTerm, Message, MarketAccount
from filters import TwitterImageFilter, TweetStatusFilter, TongueGraphicFilter

# Register your models here.

def mark_deleted(modeladmin, request, queryset):
    queryset.update(deleted=True)
mark_deleted.short_description = 'Hide selected tweets'

def mark_approved(modeladmin, request, queryset):
    queryset.update(approved=True)
mark_approved.short_description = 'Mark selected tweets as approved'

class BaseAdmin(admin.ModelAdmin):

    class Media:
        js = ('js/tweet_admin.js', )
        css = {
            'all': ('css/adi051.css', )
        }

class MessageAdmin(BaseAdmin):
    list_display = ('account', 'type', 'copy')
    list_filter = ('account', 'type')

class TweetAdmin(BaseAdmin):
    search_fields = ('handle', 'content',)
    list_display = ('created_at', 'high_priority', 'get_handle', 'account', 'get_image', 'get_autophotoshop', 'get_photoshop', 'content', 'messages', 'tweeted_by', 'artworker', 'notes')
    list_filter = ('account', 'high_priority', TweetStatusFilter, TwitterImageFilter, TongueGraphicFilter)
    list_editable = ('notes', )

    actions = [mark_deleted, ]

    fieldsets = (
        ('Attach your photoshop', {
            'fields': ('photoshop', ),
        }),
        ('Make high priority', {
            'fields': ('high_priority', 'notes'),
        }),
        ('View/change autophotoshop', {
            'classes': ('collapse', ),
            'fields': ('auto_photoshop', 'auto_base', 'auto_compose'),
        }),
        ('Tweet data', {
            'classes': ('collapse', ),
            'fields': ('created_at', 'handle', 'account', 'content', 'image_url', 'uid')
        }),
        ('Sent data', {
            'classes': ('collapse', ),
            'fields': ('artworker', 'tweeted_by', 'tweeted_at', 'tweet_id', 'sent_tweet', )
        }),
    )

    def get_image(self, obj):
        if obj.image_url:
            if 'twitpic' in obj.image_url:
                url = 'http://twitpic.com/show/thumb/{}'.format(obj.image_url.split('/')[-1])
            else:
                url = obj.image_url

            return mark_safe(''.format(obj.image_url, url))
        else:
            return "N/A"
    get_image.short_description = 'Original Image'

    def get_handle(self, obj):
        return mark_safe("""

{0}

({1} Followers)
        """.format(obj.handle.encode('utf-8'), obj.followers))
    get_handle.short_description = 'User\'s Handle'

    def messages(self, obj):
        return mark_safe("""

Image doesn't work

Tweet tongue graphic

        """)
    messages.short_description = 'Tweet back to user'

    def get_photoshop(self, obj):
        if obj.photoshop:
            if obj.tweet_id:
                # Open up the actual tweet if it's been sent
                return mark_safe(''.\
                    format(obj.account.handle, obj.photoshop.url))
            else:
                # Otherwise direct to the local image
                return mark_safe(''.format(obj.photoshop.url))
        else:
            return mark_safe('Upload'.format(obj.id))
    get_photoshop.short_description = 'Tongue Graphic'

    def get_autophotoshop(self, obj):
        auto, base, composed = "N/A", "N/A", "N/A"

        if obj.auto_photoshop:
            auto = '
'.format(obj.auto_photoshop.url)

        if obj.auto_base:
            base = '
'.format(obj.auto_base.url)

        if obj.auto_compose:
            composed = '
'.format(obj.auto_compose.url)

        return mark_safe("%s
%s
%s
" % (auto, base, composed))

    get_autophotoshop.short_description = 'Automatic Graphic'

    def save_model(self, request, obj, form, change):
        obj.artworker = request.user
        obj.save()

    def get_actions(self, request):
        actions = super(TweetAdmin, self).get_actions(request)
        if 'delete_selected' in actions:
            del actions['delete_selected']
        return actions

admin.site.register(Tweet, TweetAdmin)
admin.site.register(SearchTerm, BaseAdmin)
admin.site.register(Message, MessageAdmin)
admin.site.register(MarketAccount, BaseAdmin)
<commit_msg>and add the twitter id!<commit_after>from django.contrib import admin
from django.utils.safestring import mark_safe
from models import Tweet, SearchTerm, Message, MarketAccount
from filters import TwitterImageFilter, TweetStatusFilter, TongueGraphicFilter

# Register your models here.

def mark_deleted(modeladmin, request, queryset):
    queryset.update(deleted=True)
mark_deleted.short_description = 'Hide selected tweets'

def mark_approved(modeladmin, request, queryset):
    queryset.update(approved=True)
mark_approved.short_description = 'Mark selected tweets as approved'

class BaseAdmin(admin.ModelAdmin):

    class Media:
        js = ('js/tweet_admin.js', )
        css = {
            'all': ('css/adi051.css', )
        }

class MessageAdmin(BaseAdmin):
    list_display = ('account', 'type', 'copy')
    list_filter = ('account', 'type')

class TweetAdmin(BaseAdmin):
    search_fields = ('handle', 'content',)
    list_display = ('created_at', 'high_priority', 'get_handle', 'account', 'get_image', 'get_autophotoshop', 'get_photoshop', 'content', 'messages', 'tweeted_by', 'artworker', 'notes')
    list_filter = ('account', 'high_priority', TweetStatusFilter, TwitterImageFilter, TongueGraphicFilter)
    list_editable = ('notes', )

    actions = [mark_deleted, ]

    fieldsets = (
        ('Attach your photoshop', {
            'fields': ('photoshop', ),
        }),
        ('Make high priority', {
            'fields': ('high_priority', 'notes'),
        }),
        ('View/change autophotoshop', {
            'classes': ('collapse', ),
            'fields': ('auto_photoshop', 'auto_base', 'auto_compose'),
        }),
        ('Tweet data', {
            'classes': ('collapse', ),
            'fields': ('created_at', 'handle', 'account', 'content', 'image_url', 'uid')
        }),
        ('Sent data', {
            'classes': ('collapse', ),
            'fields': ('artworker', 'tweeted_by', 'tweeted_at', 'tweet_id', 'sent_tweet', )
        }),
    )

    def get_image(self, obj):
        if obj.image_url:
            if 'twitpic' in obj.image_url:
                url = 'http://twitpic.com/show/thumb/{}'.format(obj.image_url.split('/')[-1])
            else:
                url = obj.image_url

            return mark_safe(''.format(obj.image_url, url))
        else:
            return "N/A"
    get_image.short_description = 'Original Image'

    def get_handle(self, obj):
        return mark_safe("""

{0}

({1} Followers)
        """.format(obj.handle.encode('utf-8'), obj.followers))
    get_handle.short_description = 'User\'s Handle'

    def messages(self, obj):
        return mark_safe("""

Image doesn't work

Tweet tongue graphic

        """)
    messages.short_description = 'Tweet back to user'

    def get_photoshop(self, obj):
        if obj.photoshop:
            if obj.tweet_id:
                # Open up the actual tweet if it's been sent
                return mark_safe(''.\
                    format(obj.account.handle, obj.photoshop.url, obj.tweet_id))
            else:
                # Otherwise direct to the local image
                return mark_safe(''.format(obj.photoshop.url))
        else:
            return mark_safe('Upload'.format(obj.id))
    get_photoshop.short_description = 'Tongue Graphic'

    def get_autophotoshop(self, obj):
        auto, base, composed = "N/A", "N/A", "N/A"

        if obj.auto_photoshop:
            auto = '
'.format(obj.auto_photoshop.url)

        if obj.auto_base:
            base = '
'.format(obj.auto_base.url)

        if obj.auto_compose:
            composed = '
'.format(obj.auto_compose.url)

        return mark_safe("%s
%s
%s
" % (auto, base, composed))

    get_autophotoshop.short_description = 'Automatic Graphic'

    def save_model(self, request, obj, form, change):
        obj.artworker = request.user
        obj.save()

    def get_actions(self, request):
        actions = super(TweetAdmin, self).get_actions(request)
        if 'delete_selected' in actions:
            del actions['delete_selected']
        return actions

admin.site.register(Tweet, TweetAdmin)
admin.site.register(SearchTerm, BaseAdmin)
admin.site.register(Message, MessageAdmin)
admin.site.register(MarketAccount, BaseAdmin)
<|endoftext|>


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

"""List video URLs of stories on tested.com.

Copyright: (C) 2014 Michael Bemmerl
License: MIT License (see LICENSE.txt)

Requirements:
- Python (well, obviously ;-)

Tested with Python 2.7.6
"""

import os
import feedparser
from lxml import html
from lxml.cssselect import CSSSelector
import urllib
import re
from datetime import datetime
import argparse

parser = argparse.ArgumentParser(description="List video URLs of stories on tested.com.")
parser.add_argument('--html', action='store_true', help="HTML output instead of plain text")
parser.add_argument('--file', help="Load feed from a file instead from the Internet")
parser.add_argument('--hide-empty', action='store_true', help="Hide stories without videos")

args = parser.parse_args()

class TestedVideos(object):

    def __init__(self):
        self.result = dict()
        self.providers = dict()

        self.providers['youtube'] = dict()
        self.providers['youtube']['pattern'] = re.compile('[a-zA-Z0-9_-]{11}')
        self.providers['youtube']['group'] = 0
        self.providers['youtube']['template'] = 'https://youtu.be/{0}'

        self.providers['vimeo'] = dict()
        self.providers['vimeo']['pattern'] = re.compile('vimeo.+?/(\d+)')
        self.providers['vimeo']['group'] = 1
        self.providers['vimeo']['template'] = 'https://vimeo.com/{0}'

    def load_feed_from(self, location):
        self.feed = feedparser.parse(location)

    def process_entries(self):
        for entry in self.feed.entries:
            self.process_entry(entry)

    def process_entry(self, entry):
        root = html.parse(entry.link).getroot()
        elements = root.cssselect('div.embed-type-video iframe')

        result = list()
        for element in elements:
            url = element.get('src')
            data = self.analyze_url(url)
            if data:
                result.append(data)

        self.result[entry.title] = result

    def analyze_url(self, url):
        url = urllib.unquote_plus(url)

        for name in self.providers.keys():
            provider = self.providers[name]
            match =  provider['pattern'].search(url)
            if match:
                result = dict()
                result['provider'] = name
                result['token'] = match.group(provider['group'])
                return result

        return None

    def print_plain(self, hide_empty=False):
        print "List generated on {0}:\n".format(datetime.now())

        for key in self.result:
            if not hide_empty or self.result[key]:
                print key
                for item in self.result[key]:
                    url = self.build_video_url(item['provider'], item['token'])
                    print "  " + url
                print "-" * 80

    def print_html(self, hide_empty=False):
        html = '<!DOCTYPE html><title>tested.com videos</title>'
        html = html + '
List generated on {0}'.format(datetime.now())

        for key in self.result:
            if not hide_empty or self.result[key]:
                html = html + '
' + key + '

'
                for item in self.result[key]:
                    url = self.build_video_url(item['provider'], item['token'])
                    html = html + '
{0}
'.format(url)
                html = html + '
'

        html = html + ''
        print html

    def build_video_url(self, provider, token):
        if provider in self.providers:
            return self.providers[provider]['template'].format(token)
        else:
            return None

tv = TestedVideos()

if not args.html:
    print "Loading feed..."

if args.file and os.path.isfile(args.file):
    tv.load_feed_from(args.file)
else:
    tv.load_feed_from('http://www.tested.com/feeds/')

tv.process_entries()

if args.html:
    tv.print_html(args.hide_empty)
else:
    tv.print_plain(args.hide_empty)
<commit_msg>Let the user choose if HTTPS should be used or not.<commit_after>#!/usr/bin/env python

"""List video URLs of stories on tested.com.

Copyright: (C) 2014 Michael Bemmerl
License: MIT License (see LICENSE.txt)

Requirements:
- Python (well, obviously ;-)

Tested with Python 2.7.6
"""

import os
import feedparser
from lxml import html
from lxml.cssselect import CSSSelector
import urllib
import re
from datetime import datetime
import argparse

parser = argparse.ArgumentParser(description="List video URLs of stories on tested.com.")
parser.add_argument('--html', action='store_true', help="HTML output instead of plain text")
parser.add_argument('--file', help="Load feed from a file instead from the Internet")
parser.add_argument('--hide-empty', action='store_true', help="Hide stories without videos")
parser.add_argument('--ssl', action='store_true', help="Use HTTPS for URLs")

args = parser.parse_args()

class TestedVideos(object):

    def __init__(self, ssl=False):
        self.ssl = ssl
        self.result = dict()
        self.providers = dict()

        self.providers['youtube'] = dict()
        self.providers['youtube']['pattern'] = re.compile('[a-zA-Z0-9_-]{11}')
        self.providers['youtube']['group'] = 0
        self.providers['youtube']['template'] = '{0}://youtu.be/{1}'

        self.providers['vimeo'] = dict()
        self.providers['vimeo']['pattern'] = re.compile('vimeo.+?/(\d+)')
        self.providers['vimeo']['group'] = 1
        self.providers['vimeo']['template'] = '{0}://vimeo.com/{1}'

    def load_feed_from(self, location):
        self.feed = feedparser.parse(location)

    def process_entries(self):
        for entry in self.feed.entries:
            self.process_entry(entry)

    def process_entry(self, entry):
        root = html.parse(entry.link).getroot()
        elements = root.cssselect('div.embed-type-video iframe')

        result = list()
        for element in elements:
            url = element.get('src')
            data = self.analyze_url(url)
            if data:
                result.append(data)

        self.result[entry.title] = result

    def analyze_url(self, url):
        url = urllib.unquote_plus(url)

        for name in self.providers.keys():
            provider = self.providers[name]
            match =  provider['pattern'].search(url)
            if match:
                result = dict()
                result['provider'] = name
                result['token'] = match.group(provider['group'])
                return result

        return None

    def print_plain(self, hide_empty=False):
        print "List generated on {0}:\n".format(datetime.now())

        for key in self.result:
            if not hide_empty or self.result[key]:
                print key
                for item in self.result[key]:
                    url = self.build_video_url(item['provider'], item['token'])
                    print "  " + url
                print "-" * 80

    def print_html(self, hide_empty=False):
        html = '<!DOCTYPE html><title>tested.com videos</title>'
        html = html + '
List generated on {0}'.format(datetime.now())

        for key in self.result:
            if not hide_empty or self.result[key]:
                html = html + '
' + key + '

'
                for item in self.result[key]:
                    url = self.build_video_url(item['provider'], item['token'])
                    html = html + '
{0}
'.format(url)
                html = html + '
'

        html = html + ''
        print html

    def build_video_url(self, provider, token):
        if provider in self.providers:
            scheme = 'http'
            if self.ssl:
                scheme += 's'

            return self.providers[provider]['template'].format(scheme, token)
        else:
            return None

tv = TestedVideos(args.ssl)

if not args.html:
    print "Loading feed..."

if args.file and os.path.isfile(args.file):
    tv.load_feed_from(args.file)
else:
    tv.load_feed_from('http://www.tested.com/feeds/')

tv.process_entries()

if args.html:
    tv.print_html(args.hide_empty)
else:
    tv.print_plain(args.hide_empty)
<|endoftext|>


<commit_before>"""
The ``power_curves`` module contains functions apply calculations to the power
curve of a wind turbine, wind farm or wind turbine cluster.

"""

__copyright__ = "Copyright oemof developer group"
__license__ = "GPLv3"

import numpy as np
import pandas as pd
from windpowerlib import tools

def smooth_power_curve(power_curve_wind_speeds, power_curve_values,
                       block_width=0.5, wind_speeds_block_range=15.0, # TODO wind_speeds_block_range delete later
                       standard_deviation_method='turbulence_intensity',
                       mean_gauss=0, **kwargs):
    r"""
    Smoothes the input power curve values by using a gaussian distribution.

    Parameters
    ----------
    power_curve_wind_speeds : pandas.Series
        Wind speeds in m/s for which the power curve values are provided in
        `power_curve_values`.
    power_curve_values : pandas.Series or numpy.array
        Power curve values corresponding to wind speeds in
        `power_curve_wind_speeds`.
    block_width : Float
        Width of the moving block. Default: 0.5.
    standard_deviation_method : String
        Method for calculating the standard deviation for the gaussian
        distribution. Options: 'turbulence_intensity', 'Norgaard', 'Staffell'.
        Default: 'turbulence_intensity'.

    Other Parameters
    ----------------
    turbulence intensity : Float, optional
        Turbulence intensity at hub height of the wind turbine the power curve
        is smoothed for.

    Returns
    -------
    smoothed_power_curve_df : pd.DataFrame
        Smoothed power curve. DataFrame has 'wind_speed' and
        'power' columns with wind speeds in m/s and the corresponding power
        curve value in W.

    Notes
    -----
    The following equation is used [1]_:
        # TODO: add equation

    References
    ----------
    .. [1]  Knorr, K.: "Modellierung von raum-zeitlichen Eigenschaften der
             Windenergieeinspeisung für wetterdatenbasierte
             Windleistungssimulationen". Universität Kassel, Diss., 2016,
             p. 106

    # TODO: add references
    """
    # Specify normalized standard deviation
    if standard_deviation_method == 'turbulence_intensity':
        if 'turbulence_intensity' in kwargs:
            normalized_standard_deviation = kwargs['turbulence_intensity']
        else:
            raise ValueError("Turbulence intensity must be defined for " +
                             "using 'turbulence_intensity' as " +
                             "`standard_deviation_method`")
    elif standard_deviation_method == 'Norgaard':
        pass # TODO add
    elif standard_deviation_method == 'Staffell':
        normalized_standard_deviation = 0.2
    # Initialize list for power curve values
    smoothed_power_curve_values = []
    # Step of power curve wind speeds
    step = power_curve_wind_speeds.iloc[-5] - power_curve_wind_speeds.iloc[-6]
    # Append wind speeds to `power_curve_wind_speeds` until 40 m/s
    while (power_curve_wind_speeds.values[-1] < 40.0):
        power_curve_wind_speeds = power_curve_wind_speeds.append(
            pd.Series(power_curve_wind_speeds.iloc[-1] + step,
                      index=[power_curve_wind_speeds.index[-1] + 1]))
        power_curve_values = power_curve_values.append(
            pd.Series(0.0, index=[power_curve_values.index[-1] + 1]))
    for power_curve_wind_speed in power_curve_wind_speeds:
        # Create array of wind speeds for the moving block
        wind_speeds_block = (
            np.arange(-wind_speeds_block_range, wind_speeds_block_range + block_width, block_width) +
            power_curve_wind_speed)
        # Get standard deviation for gaussian filter
        standard_deviation = (
            (power_curve_wind_speed * normalized_standard_deviation + 0.6)
            if standard_deviation_method is 'Staffell'
            else power_curve_wind_speed * normalized_standard_deviation)
        # Get the smoothed value of the power output
        smoothed_value = sum(
            block_width * np.interp(wind_speed, power_curve_wind_speeds,
                                    power_curve_values, left=0, right=0) *
            tools.gaussian_distribution(
                power_curve_wind_speed - wind_speed,
                standard_deviation, mean_gauss)
            for wind_speed in wind_speeds_block)
        # Add value to list - add 0 if `smoothed_value` is nan. This occurs
        # because the gaussian distribution is not defined for 0.
        smoothed_power_curve_values.append(0 if np.isnan(smoothed_value)
                                           else smoothed_value)
    # Create smoothed power curve DataFrame
    smoothed_power_curve_df = pd.DataFrame(
        data=[list(power_curve_wind_speeds.values),
              smoothed_power_curve_values]).transpose()
    # Rename columns of DataFrame
    smoothed_power_curve_df.columns = ['wind_speed', 'power']
#    # Plot power curves
#    fig = plt.figure()
#    plt.plot(power_curve_wind_speeds.values, power_curve_values.values)
#    plt.plot(power_curve_wind_speeds.values, smoothed_power_curve_values)
#    fig.savefig(os.path.abspath(os.path.join(
#        os.path.dirname(__file__), '../Plots/power_curves',
#        '{0}_{1}_{2}.png'.format(kwargs['object_name'],
#                                 standard_deviation_method, block_width))))
#    plt.close() # TODO: delete plot later
    return smoothed_power_curve_df

def wake_losses_to_power_curve(power_curve_wind_speeds, power_curve_values,
                               wake_losses_method='wind_efficiency_curve',
                               wind_farm_efficiency=None):
    r"""
    Applies wake losses depending on the method to a power curve.

    Parameters
    ----------
    power_curve_wind_speeds : pandas.Series
        Wind speeds in m/s for which the power curve values are provided in
        `power_curve_values`.
    power_curve_values : pandas.Series or numpy.array
        Power curve values corresponding to wind speeds in
        `power_curve_wind_speeds`.
    wake_losses_method : String
        Defines the method for talking wake losses within the farm into
        consideration. Options: 'wind_efficiency_curve', 'constant_efficiency'.
        Default: 'wind_efficiency_curve'.
    wind_farm_efficiency : Float or pd.DataFrame or Dictionary
        Efficiency of the wind farm. Either constant (float) or wind efficiency
        curve (pd.DataFrame or Dictionary) contianing 'wind_speed' and
        'efficiency' columns/keys with wind speeds in m/s and the
        corresponding dimensionless wind farm efficiency. Default: None.

    Returns
    -------
    power_curve_df : pd.DataFrame
        With wind farm efficiency reduced power curve. DataFrame has
        'wind_speed' and 'power' columns with wind speeds in m/s and the
        corresponding power curve value in W.

    Notes
    -----
    TODO add

    """
    # Create power curve DataFrame
    power_curve_df = pd.DataFrame(
        data=[list(power_curve_wind_speeds),
              list(power_curve_values)]).transpose()
    # Rename columns of DataFrame
    power_curve_df.columns = ['wind_speed', 'power']
    if wake_losses_method == 'constant_efficiency':
        if not isinstance(wind_farm_efficiency, float):
            raise TypeError("'wind_farm_efficiency' must be float if " +
                            "`wake_losses_method´ is '{0}'")
        power_curve_df['power'] = power_curve_values * wind_farm_efficiency
    elif wake_losses_method == 'wind_efficiency_curve':
        if (not isinstance(wind_farm_efficiency, dict) and
                not isinstance(wind_farm_efficiency, pd.DataFrame)):
            raise TypeError(
                "'wind_farm_efficiency' must be a dictionary or " +
                "pd.DataFrame if `wake_losses_method´ is '{0}'")
        df = pd.concat([power_curve_df.set_index('wind_speed'),
                        wind_farm_efficiency.set_index('wind_speed')], axis=1)
        # Add by efficiency reduced power column (nan values of efficiency
        # are interpolated)
        df['reduced_power'] = df['power'] * df['efficiency'].interpolate(
            method='index')
        reduced_power = df['reduced_power'].dropna()
        power_curve_df = pd.DataFrame([reduced_power.index,
                                       reduced_power.values]).transpose()
        power_curve_df.columns = ['wind_speed', 'power']
    else:
        raise ValueError(
            "`wake_losses_method` is {0} but should be ".format(
                wake_losses_method) +
            "'constant_efficiency' or 'wind_efficiency_curve'")
    return power_curve_df

def density_correct_power_curve(density, power_curve_wind_speeds,
                                power_curve_values):
    r"""
    Applies a density correction to a power curve.

    As site specific density a mean density has to be given as parameter.

    Parameters
    ----------
    density : float
        Mean density of air at hub height in kg/m³.
    power_curve_wind_speeds : pandas.Series or numpy.array
        Wind speeds in m/s for which the power curve values are provided in
        `power_curve_values`.
    power_curve_values : pandas.Series or numpy.array
        Power curve values corresponding to wind speeds in
        `power_curve_wind_speeds`.

    Returns
    -------
    power_curve_df : pd.DataFrame
        Density corrected power curve. DataFrame has 'wind_speed' and 'power'
        columns with wind speeds in m/s and the corresponding power curve
        value in W.

    Notes
    -----
    The following equation is used for the site specific power curve wind
    speeds [1]_, [2]_, [3]_:

    .. math:: v_{site}=v_{std}\cdot\left(\frac{\rho_0}
                       {\rho_{site}}\right)^{p(v)}

    with:
        .. math:: p=\begin{cases}
                      \frac{1}{3} & v_{std} \leq 7.5\text{ m/s}\\
                      \frac{1}{15}\cdot v_{std}-\frac{1}{6} & 7.5
                      \text{ m/s}<v_{std}<12.5\text{ m/s}\\
                      \frac{2}{3} & \geq 12.5 \text{ m/s}
                    \end{cases},
        v: wind speed [m/s], :math:`\rho`: density [kg/m³]

    :math:`v_{std}` is the standard wind speed in the power curve
    (:math:`v_{std}`, :math:`P_{std}`),
    :math:`v_{site}` is the density corrected wind speed for the power curve
    (:math:`v_{site}`, :math:`P_{std}`),
    :math:`\rho_0` is the ambient density (1.225 kg/m³)
    and :math:`\rho_{site}` the density at site conditions (and hub height).

    It is assumed that the power output for wind speeds above the maximum
    and below the minimum wind speed given in the power curve is zero.

    References
    ----------
    .. [1] Svenningsen, L.: "Power Curve Air Density Correction And Other
            Power Curve Options in WindPRO". 1st edition, Aalborg,
            EMD International A/S , 2010, p. 4
    .. [2] Svenningsen, L.: "Proposal of an Improved Power Curve Correction".
            EMD International A/S , 2010
    .. [3] Biank, M.: "Methodology, Implementation and Validation of a
            Variable Scale Simulation Model for Windpower based on the
            Georeferenced Installation Register of Germany". Master's Thesis
            at Reiner Lemoine Institute, 2014, p. 13

    """
    if density is None:
        raise TypeError("`density` is None. For the calculation with a " +
                        "density corrected power curve mean density at hub " +
                        "height is needed.")
    corrected_power_curve_wind_speeds = (
        power_curve_wind_speeds * (1.225 / density) ** (
            np.interp(power_curve_wind_speeds, [7.5, 12.5], [1/3, 2/3])))
    power_curve_df = pd.DataFrame([corrected_power_curve_wind_speeds,
                                   power_curve_values]).transpose()
    power_curve_df.columns = ['wind_speed', 'power']
    return power_curve_df
<commit_msg>Add values to power curve in step size of 0.5 m/s<commit_after>"""
The ``power_curves`` module contains functions apply calculations to the power
curve of a wind turbine, wind farm or wind turbine cluster.

"""

__copyright__ = "Copyright oemof developer group"
__license__ = "GPLv3"

import numpy as np
import pandas as pd
from windpowerlib import tools

def smooth_power_curve(power_curve_wind_speeds, power_curve_values,
                       block_width=0.5, wind_speeds_block_range=15.0, # TODO wind_speeds_block_range delete later
                       standard_deviation_method='turbulence_intensity',
                       mean_gauss=0, **kwargs):
    r"""
    Smoothes the input power curve values by using a gaussian distribution.

    Parameters
    ----------
    power_curve_wind_speeds : pandas.Series
        Wind speeds in m/s for which the power curve values are provided in
        `power_curve_values`.
    power_curve_values : pandas.Series or numpy.array
        Power curve values corresponding to wind speeds in
        `power_curve_wind_speeds`.
    block_width : Float
        Width of the moving block. Default: 0.5.
    standard_deviation_method : String
        Method for calculating the standard deviation for the gaussian
        distribution. Options: 'turbulence_intensity', 'Norgaard', 'Staffell'.
        Default: 'turbulence_intensity'.

    Other Parameters
    ----------------
    turbulence intensity : Float, optional
        Turbulence intensity at hub height of the wind turbine the power curve
        is smoothed for.

    Returns
    -------
    smoothed_power_curve_df : pd.DataFrame
        Smoothed power curve. DataFrame has 'wind_speed' and
        'power' columns with wind speeds in m/s and the corresponding power
        curve value in W.

    Notes
    -----
    The following equation is used [1]_:
        # TODO: add equation

    References
    ----------
    .. [1]  Knorr, K.: "Modellierung von raum-zeitlichen Eigenschaften der
             Windenergieeinspeisung für wetterdatenbasierte
             Windleistungssimulationen". Universität Kassel, Diss., 2016,
             p. 106

    # TODO: add references
    """
    # Specify normalized standard deviation
    if standard_deviation_method == 'turbulence_intensity':
        if 'turbulence_intensity' in kwargs:
            normalized_standard_deviation = kwargs['turbulence_intensity']
        else:
            raise ValueError("Turbulence intensity must be defined for " +
                             "using 'turbulence_intensity' as " +
                             "`standard_deviation_method`")
    elif standard_deviation_method == 'Norgaard':
        pass # TODO add
    elif standard_deviation_method == 'Staffell':
        normalized_standard_deviation = 0.2
    # Initialize list for power curve values
    smoothed_power_curve_values = []
    # Append wind speeds to `power_curve_wind_speeds` until 40 m/s
    while (power_curve_wind_speeds.values[-1] < 40.0):
        power_curve_wind_speeds = power_curve_wind_speeds.append(
            pd.Series(power_curve_wind_speeds.iloc[-1] + 0.5,
                      index=[power_curve_wind_speeds.index[-1] + 1]))
        power_curve_values = power_curve_values.append(
            pd.Series(0.0, index=[power_curve_values.index[-1] + 1]))
    for power_curve_wind_speed in power_curve_wind_speeds:
        # Create array of wind speeds for the moving block
        wind_speeds_block = (
            np.arange(-wind_speeds_block_range, wind_speeds_block_range + block_width, block_width) +
            power_curve_wind_speed)
        # Get standard deviation for gaussian filter
        standard_deviation = (
            (power_curve_wind_speed * normalized_standard_deviation + 0.6)
            if standard_deviation_method is 'Staffell'
            else power_curve_wind_speed * normalized_standard_deviation)
        # Get the smoothed value of the power output
        smoothed_value = sum(
            block_width * np.interp(wind_speed, power_curve_wind_speeds,
                                    power_curve_values, left=0, right=0) *
            tools.gaussian_distribution(
                power_curve_wind_speed - wind_speed,
                standard_deviation, mean_gauss)
            for wind_speed in wind_speeds_block)
        # Add value to list - add 0 if `smoothed_value` is nan. This occurs
        # because the gaussian distribution is not defined for 0.
        smoothed_power_curve_values.append(0 if np.isnan(smoothed_value)
                                           else smoothed_value)
    # Create smoothed power curve DataFrame
    smoothed_power_curve_df = pd.DataFrame(
        data=[list(power_curve_wind_speeds.values),
              smoothed_power_curve_values]).transpose()
    # Rename columns of DataFrame
    smoothed_power_curve_df.columns = ['wind_speed', 'power']
#    # Plot power curves
#    fig = plt.figure()
#    plt.plot(power_curve_wind_speeds.values, power_curve_values.values)
#    plt.plot(power_curve_wind_speeds.values, smoothed_power_curve_values)
#    fig.savefig(os.path.abspath(os.path.join(
#        os.path.dirname(__file__), '../Plots/power_curves',
#        '{0}_{1}_{2}.png'.format(kwargs['object_name'],
#                                 standard_deviation_method, block_width))))
#    plt.close() # TODO: delete plot later
    return smoothed_power_curve_df

def wake_losses_to_power_curve(power_curve_wind_speeds, power_curve_values,
                               wake_losses_method='wind_efficiency_curve',
                               wind_farm_efficiency=None):
    r"""
    Applies wake losses depending on the method to a power curve.

    Parameters
    ----------
    power_curve_wind_speeds : pandas.Series
        Wind speeds in m/s for which the power curve values are provided in
        `power_curve_values`.
    power_curve_values : pandas.Series or numpy.array
        Power curve values corresponding to wind speeds in
        `power_curve_wind_speeds`.
    wake_losses_method : String
        Defines the method for talking wake losses within the farm into
        consideration. Options: 'wind_efficiency_curve', 'constant_efficiency'.
        Default: 'wind_efficiency_curve'.
    wind_farm_efficiency : Float or pd.DataFrame or Dictionary
        Efficiency of the wind farm. Either constant (float) or wind efficiency
        curve (pd.DataFrame or Dictionary) contianing 'wind_speed' and
        'efficiency' columns/keys with wind speeds in m/s and the
        corresponding dimensionless wind farm efficiency. Default: None.

    Returns
    -------
    power_curve_df : pd.DataFrame
        With wind farm efficiency reduced power curve. DataFrame has
        'wind_speed' and 'power' columns with wind speeds in m/s and the
        corresponding power curve value in W.

    Notes
    -----
    TODO add

    """
    # Create power curve DataFrame
    power_curve_df = pd.DataFrame(
        data=[list(power_curve_wind_speeds),
              list(power_curve_values)]).transpose()
    # Rename columns of DataFrame
    power_curve_df.columns = ['wind_speed', 'power']
    if wake_losses_method == 'constant_efficiency':
        if not isinstance(wind_farm_efficiency, float):
            raise TypeError("'wind_farm_efficiency' must be float if " +
                            "`wake_losses_method´ is '{0}'")
        power_curve_df['power'] = power_curve_values * wind_farm_efficiency
    elif wake_losses_method == 'wind_efficiency_curve':
        if (not isinstance(wind_farm_efficiency, dict) and
                not isinstance(wind_farm_efficiency, pd.DataFrame)):
            raise TypeError(
                "'wind_farm_efficiency' must be a dictionary or " +
                "pd.DataFrame if `wake_losses_method´ is '{0}'")
        df = pd.concat([power_curve_df.set_index('wind_speed'),
                        wind_farm_efficiency.set_index('wind_speed')], axis=1)
        # Add by efficiency reduced power column (nan values of efficiency
        # are interpolated)
        df['reduced_power'] = df['power'] * df['efficiency'].interpolate(
            method='index')
        reduced_power = df['reduced_power'].dropna()
        power_curve_df = pd.DataFrame([reduced_power.index,
                                       reduced_power.values]).transpose()
        power_curve_df.columns = ['wind_speed', 'power']
    else:
        raise ValueError(
            "`wake_losses_method` is {0} but should be ".format(
                wake_losses_method) +
            "'constant_efficiency' or 'wind_efficiency_curve'")
    return power_curve_df

def density_correct_power_curve(density, power_curve_wind_speeds,
                                power_curve_values):
    r"""
    Applies a density correction to a power curve.

    As site specific density a mean density has to be given as parameter.

    Parameters
    ----------
    density : float
        Mean density of air at hub height in kg/m³.
    power_curve_wind_speeds : pandas.Series or numpy.array
        Wind speeds in m/s for which the power curve values are provided in
        `power_curve_values`.
    power_curve_values : pandas.Series or numpy.array
        Power curve values corresponding to wind speeds in
        `power_curve_wind_speeds`.

    Returns
    -------
    power_curve_df : pd.DataFrame
        Density corrected power curve. DataFrame has 'wind_speed' and 'power'
        columns with wind speeds in m/s and the corresponding power curve
        value in W.

    Notes
    -----
    The following equation is used for the site specific power curve wind
    speeds [1]_, [2]_, [3]_:

    .. math:: v_{site}=v_{std}\cdot\left(\frac{\rho_0}
                       {\rho_{site}}\right)^{p(v)}

    with:
        .. math:: p=\begin{cases}
                      \frac{1}{3} & v_{std} \leq 7.5\text{ m/s}\\
                      \frac{1}{15}\cdot v_{std}-\frac{1}{6} & 7.5
                      \text{ m/s}<v_{std}<12.5\text{ m/s}\\
                      \frac{2}{3} & \geq 12.5 \text{ m/s}
                    \end{cases},
        v: wind speed [m/s], :math:`\rho`: density [kg/m³]

    :math:`v_{std}` is the standard wind speed in the power curve
    (:math:`v_{std}`, :math:`P_{std}`),
    :math:`v_{site}` is the density corrected wind speed for the power curve
    (:math:`v_{site}`, :math:`P_{std}`),
    :math:`\rho_0` is the ambient density (1.225 kg/m³)
    and :math:`\rho_{site}` the density at site conditions (and hub height).

    It is assumed that the power output for wind speeds above the maximum
    and below the minimum wind speed given in the power curve is zero.

    References
    ----------
    .. [1] Svenningsen, L.: "Power Curve Air Density Correction And Other
            Power Curve Options in WindPRO". 1st edition, Aalborg,
            EMD International A/S , 2010, p. 4
    .. [2] Svenningsen, L.: "Proposal of an Improved Power Curve Correction".
            EMD International A/S , 2010
    .. [3] Biank, M.: "Methodology, Implementation and Validation of a
            Variable Scale Simulation Model for Windpower based on the
            Georeferenced Installation Register of Germany". Master's Thesis
            at Reiner Lemoine Institute, 2014, p. 13

    """
    if density is None:
        raise TypeError("`density` is None. For the calculation with a " +
                        "density corrected power curve mean density at hub " +
                        "height is needed.")
    corrected_power_curve_wind_speeds = (
        power_curve_wind_speeds * (1.225 / density) ** (
            np.interp(power_curve_wind_speeds, [7.5, 12.5], [1/3, 2/3])))
    power_curve_df = pd.DataFrame([corrected_power_curve_wind_speeds,
                                   power_curve_values]).transpose()
    power_curve_df.columns = ['wind_speed', 'power']
    return power_curve_df
<|endoftext|>


<commit_before>from django.conf.urls.defaults import *
from django.views.generic import ListView, TemplateView

from open_municipio.people.models import Institution
from open_municipio.people.views import CouncilView, CityGovernmentView, CommitteeDetailView

urlpatterns = patterns('',
    url(r'^$', ListView.as_view(
           model=Institution,
           template_name='institution_list.html'
        ), name='om_institution_list'),

    url(r'^committees/(?P<slug>[-\w]+)/$', CommitteeDetailView.as_view(), name='om_institution_commission'),
    url(r'^city-government/$', CityGovernmentView.as_view(), name='om_institution_citigov'),
    url(r'^council/$', CouncilView.as_view(), name='om_institution_council'),

    # url(r'^(?P<slug>[-\w]+)/$', InstitutionDetailView.as_view(
    #        template_name='institution_detail.html'
    #     ), name='om_institution_detail'),

)
<commit_msg>Minor typo<commit_after>from django.conf.urls.defaults import *
from django.views.generic import ListView, TemplateView

from open_municipio.people.models import Institution
from open_municipio.people.views import CouncilView, CityGovernmentView, CommitteeDetailView

urlpatterns = patterns('',
    url(r'^$', ListView.as_view(
           model=Institution,
           template_name='institution_list.html'
        ), name='om_institution_list'),

    url(r'^committees/(?P<slug>[-\w]+)/$', CommitteeDetailView.as_view(), name='om_institution_committee'),
    url(r'^city-government/$', CityGovernmentView.as_view(), name='om_institution_citigov'),
    url(r'^council/$', CouncilView.as_view(), name='om_institution_council'),

    # url(r'^(?P<slug>[-\w]+)/$', InstitutionDetailView.as_view(
    #        template_name='institution_detail.html'
    #     ), name='om_institution_detail'),

)
<|endoftext|>