<commit_before>"""Support for media metadata handling."""
from __future__ import annotations

import datetime
import logging
from typing import Any

from soco.core import (
    MUSIC_SRC_AIRPLAY,
    MUSIC_SRC_LINE_IN,
    MUSIC_SRC_RADIO,
    MUSIC_SRC_SPOTIFY_CONNECT,
    MUSIC_SRC_TV,
    SoCo,
)
from soco.data_structures import DidlAudioBroadcast, DidlPlaylistContainer
from soco.music_library import MusicLibrary

from homeassistant.core import HomeAssistant
from homeassistant.helpers.config_validation import time_period_str
from homeassistant.helpers.dispatcher import dispatcher_send
from homeassistant.util import dt as dt_util

from .const import (
    SONOS_MEDIA_UPDATED,
    SONOS_STATE_PLAYING,
    SONOS_STATE_TRANSITIONING,
    SOURCE_AIRPLAY,
    SOURCE_LINEIN,
    SOURCE_SPOTIFY_CONNECT,
    SOURCE_TV,
)
from .helpers import soco_error

LINEIN_SOURCES = (MUSIC_SRC_TV, MUSIC_SRC_LINE_IN)
SOURCE_MAPPING = {
    MUSIC_SRC_AIRPLAY: SOURCE_AIRPLAY,
    MUSIC_SRC_TV: SOURCE_TV,
    MUSIC_SRC_LINE_IN: SOURCE_LINEIN,
    MUSIC_SRC_SPOTIFY_CONNECT: SOURCE_SPOTIFY_CONNECT,
}
UNAVAILABLE_VALUES = {"", "NOT_IMPLEMENTED", None}
DURATION_SECONDS = "duration_in_s"
POSITION_SECONDS = "position_in_s"

_LOGGER = logging.getLogger(__name__)

def _timespan_secs(timespan: str | None) -> None | float:
    """Parse a time-span into number of seconds."""
    if timespan in UNAVAILABLE_VALUES:
        return None
    return time_period_str(timespan).total_seconds()  # type: ignore[arg-type]

class SonosMedia:
    """Representation of the current Sonos media."""

    def __init__(self, hass: HomeAssistant, soco: SoCo) -> None:
        """Initialize a SonosMedia."""
        self.hass = hass
        self.soco = soco
        self.play_mode: str | None = None
        self.playback_status: str | None = None

        # This block is reset with clear()
        self.album_name: str | None = None
        self.artist: str | None = None
        self.channel: str | None = None
        self.duration: float | None = None
        self.image_url: str | None = None
        self.queue_position: int | None = None
        self.queue_size: int | None = None
        self.playlist_name: str | None = None
        self.source_name: str | None = None
        self.title: str | None = None
        self.uri: str | None = None

        self.position: float | None = None
        self.position_updated_at: datetime.datetime | None = None

    def clear(self) -> None:
        """Clear basic media info."""
        self.album_name = None
        self.artist = None
        self.channel = None
        self.duration = None
        self.image_url = None
        self.playlist_name = None
        self.queue_position = None
        self.queue_size = None
        self.source_name = None
        self.title = None
        self.uri = None

    def clear_position(self) -> None:
        """Clear the position attributes."""
        self.position = None
        self.position_updated_at = None

    @property
    def library(self) -> MusicLibrary:
        """Return the soco MusicLibrary instance."""
        return self.soco.music_library

    @soco_error()
    def poll_track_info(self) -> dict[str, Any]:
        """Poll the speaker for current track info, add converted position values, and return."""
        track_info = self.soco.get_current_track_info()
        track_info[DURATION_SECONDS] = _timespan_secs(track_info.get("duration"))
        track_info[POSITION_SECONDS] = _timespan_secs(track_info.get("position"))
        return track_info

    def write_media_player_states(self) -> None:
        """Send a signal to media player(s) to write new states."""
        dispatcher_send(self.hass, SONOS_MEDIA_UPDATED, self.soco.uid)

    def set_basic_track_info(self, update_position: bool = False) -> None:
        """Query the speaker to update media metadata and position info."""
        self.clear()

        track_info = self.poll_track_info()
        self.uri = track_info["uri"]

        audio_source = self.soco.music_source_from_uri(self.uri)
        if source := SOURCE_MAPPING.get(audio_source):
            self.source_name = source
            if audio_source in LINEIN_SOURCES:
                self.clear_position()
                self.title = source
                return

        self.artist = track_info.get("artist")
        self.album_name = track_info.get("album")
        self.title = track_info.get("title")
        self.image_url = track_info.get("album_art")

        playlist_position = int(track_info.get("playlist_position"))
        if playlist_position > 0:
            self.queue_position = playlist_position

        self.update_media_position(track_info, force_update=update_position)

    def update_media_from_event(self, evars: dict[str, Any]) -> None:
        """Update information about currently playing media using an event payload."""
        new_status = evars["transport_state"]
        state_changed = new_status != self.playback_status

        self.play_mode = evars["current_play_mode"]
        self.playback_status = new_status

        track_uri = evars["enqueued_transport_uri"] or evars["current_track_uri"]
        audio_source = self.soco.music_source_from_uri(track_uri)

        self.set_basic_track_info(update_position=state_changed)

        if ct_md := evars["current_track_meta_data"]:
            if not self.image_url:
                if album_art_uri := getattr(ct_md, "album_art_uri", None):
                    self.image_url = self.library.build_album_art_full_uri(
                        album_art_uri
                    )

        et_uri_md = evars["enqueued_transport_uri_meta_data"]
        if isinstance(et_uri_md, DidlPlaylistContainer):
            self.playlist_name = et_uri_md.title

        if queue_size := evars.get("number_of_tracks", 0):
            self.queue_size = int(queue_size)

        if audio_source == MUSIC_SRC_RADIO:
            self.channel = et_uri_md.title

            if ct_md and ct_md.radio_show:
                radio_show = ct_md.radio_show.split(",")[0]
                self.channel = " • ".join(filter(None, [self.channel, radio_show]))

            if isinstance(et_uri_md, DidlAudioBroadcast):
                self.title = self.title or self.channel

        self.write_media_player_states()

    @soco_error()
    def poll_media(self) -> None:
        """Poll information about currently playing media."""
        transport_info = self.soco.get_current_transport_info()
        new_status = transport_info["current_transport_state"]

        if new_status == SONOS_STATE_TRANSITIONING:
            return

        update_position = new_status != self.playback_status
        self.playback_status = new_status
        self.play_mode = self.soco.play_mode

        self.set_basic_track_info(update_position=update_position)

        self.write_media_player_states()

    def update_media_position(
        self, position_info: dict[str, int], force_update: bool = False
    ) -> None:
        """Update state when playing music tracks."""
        if (duration := position_info.get(DURATION_SECONDS)) == 0:
            self.clear_position()
            return

        should_update = force_update
        self.duration = duration
        current_position = position_info.get(POSITION_SECONDS)

        # player started reporting position?
        if current_position is not None and self.position is None:
            should_update = True

        # position jumped?
        if current_position is not None and self.position is not None:
            if self.playback_status == SONOS_STATE_PLAYING:
                assert self.position_updated_at is not None
                time_delta = dt_util.utcnow() - self.position_updated_at
                time_diff = time_delta.total_seconds()
            else:
                time_diff = 0

            calculated_position = self.position + time_diff

            if abs(calculated_position - current_position) > 1.5:
                should_update = True

        if current_position is None:
            self.clear_position()
        elif should_update:
            self.position = current_position
            self.position_updated_at = dt_util.utcnow()
<commit_msg>Fix Sonos radio metadata processing with missing data (#67141)<commit_after>"""Support for media metadata handling."""
from __future__ import annotations

import datetime
import logging
from typing import Any

from soco.core import (
    MUSIC_SRC_AIRPLAY,
    MUSIC_SRC_LINE_IN,
    MUSIC_SRC_RADIO,
    MUSIC_SRC_SPOTIFY_CONNECT,
    MUSIC_SRC_TV,
    SoCo,
)
from soco.data_structures import DidlAudioBroadcast, DidlPlaylistContainer
from soco.music_library import MusicLibrary

from homeassistant.core import HomeAssistant
from homeassistant.helpers.config_validation import time_period_str
from homeassistant.helpers.dispatcher import dispatcher_send
from homeassistant.util import dt as dt_util

from .const import (
    SONOS_MEDIA_UPDATED,
    SONOS_STATE_PLAYING,
    SONOS_STATE_TRANSITIONING,
    SOURCE_AIRPLAY,
    SOURCE_LINEIN,
    SOURCE_SPOTIFY_CONNECT,
    SOURCE_TV,
)
from .helpers import soco_error

LINEIN_SOURCES = (MUSIC_SRC_TV, MUSIC_SRC_LINE_IN)
SOURCE_MAPPING = {
    MUSIC_SRC_AIRPLAY: SOURCE_AIRPLAY,
    MUSIC_SRC_TV: SOURCE_TV,
    MUSIC_SRC_LINE_IN: SOURCE_LINEIN,
    MUSIC_SRC_SPOTIFY_CONNECT: SOURCE_SPOTIFY_CONNECT,
}
UNAVAILABLE_VALUES = {"", "NOT_IMPLEMENTED", None}
DURATION_SECONDS = "duration_in_s"
POSITION_SECONDS = "position_in_s"

_LOGGER = logging.getLogger(__name__)

def _timespan_secs(timespan: str | None) -> None | float:
    """Parse a time-span into number of seconds."""
    if timespan in UNAVAILABLE_VALUES:
        return None
    return time_period_str(timespan).total_seconds()  # type: ignore[arg-type]

class SonosMedia:
    """Representation of the current Sonos media."""

    def __init__(self, hass: HomeAssistant, soco: SoCo) -> None:
        """Initialize a SonosMedia."""
        self.hass = hass
        self.soco = soco
        self.play_mode: str | None = None
        self.playback_status: str | None = None

        # This block is reset with clear()
        self.album_name: str | None = None
        self.artist: str | None = None
        self.channel: str | None = None
        self.duration: float | None = None
        self.image_url: str | None = None
        self.queue_position: int | None = None
        self.queue_size: int | None = None
        self.playlist_name: str | None = None
        self.source_name: str | None = None
        self.title: str | None = None
        self.uri: str | None = None

        self.position: float | None = None
        self.position_updated_at: datetime.datetime | None = None

    def clear(self) -> None:
        """Clear basic media info."""
        self.album_name = None
        self.artist = None
        self.channel = None
        self.duration = None
        self.image_url = None
        self.playlist_name = None
        self.queue_position = None
        self.queue_size = None
        self.source_name = None
        self.title = None
        self.uri = None

    def clear_position(self) -> None:
        """Clear the position attributes."""
        self.position = None
        self.position_updated_at = None

    @property
    def library(self) -> MusicLibrary:
        """Return the soco MusicLibrary instance."""
        return self.soco.music_library

    @soco_error()
    def poll_track_info(self) -> dict[str, Any]:
        """Poll the speaker for current track info, add converted position values, and return."""
        track_info = self.soco.get_current_track_info()
        track_info[DURATION_SECONDS] = _timespan_secs(track_info.get("duration"))
        track_info[POSITION_SECONDS] = _timespan_secs(track_info.get("position"))
        return track_info

    def write_media_player_states(self) -> None:
        """Send a signal to media player(s) to write new states."""
        dispatcher_send(self.hass, SONOS_MEDIA_UPDATED, self.soco.uid)

    def set_basic_track_info(self, update_position: bool = False) -> None:
        """Query the speaker to update media metadata and position info."""
        self.clear()

        track_info = self.poll_track_info()
        self.uri = track_info["uri"]

        audio_source = self.soco.music_source_from_uri(self.uri)
        if source := SOURCE_MAPPING.get(audio_source):
            self.source_name = source
            if audio_source in LINEIN_SOURCES:
                self.clear_position()
                self.title = source
                return

        self.artist = track_info.get("artist")
        self.album_name = track_info.get("album")
        self.title = track_info.get("title")
        self.image_url = track_info.get("album_art")

        playlist_position = int(track_info.get("playlist_position"))
        if playlist_position > 0:
            self.queue_position = playlist_position

        self.update_media_position(track_info, force_update=update_position)

    def update_media_from_event(self, evars: dict[str, Any]) -> None:
        """Update information about currently playing media using an event payload."""
        new_status = evars["transport_state"]
        state_changed = new_status != self.playback_status

        self.play_mode = evars["current_play_mode"]
        self.playback_status = new_status

        track_uri = evars["enqueued_transport_uri"] or evars["current_track_uri"]
        audio_source = self.soco.music_source_from_uri(track_uri)

        self.set_basic_track_info(update_position=state_changed)

        if ct_md := evars["current_track_meta_data"]:
            if not self.image_url:
                if album_art_uri := getattr(ct_md, "album_art_uri", None):
                    self.image_url = self.library.build_album_art_full_uri(
                        album_art_uri
                    )

        et_uri_md = evars["enqueued_transport_uri_meta_data"]
        if isinstance(et_uri_md, DidlPlaylistContainer):
            self.playlist_name = et_uri_md.title

        if queue_size := evars.get("number_of_tracks", 0):
            self.queue_size = int(queue_size)

        if audio_source == MUSIC_SRC_RADIO:
            if et_uri_md:
                self.channel = et_uri_md.title

            if ct_md and ct_md.radio_show:
                radio_show = ct_md.radio_show.split(",")[0]
                self.channel = " • ".join(filter(None, [self.channel, radio_show]))

            if isinstance(et_uri_md, DidlAudioBroadcast):
                self.title = self.title or self.channel

        self.write_media_player_states()

    @soco_error()
    def poll_media(self) -> None:
        """Poll information about currently playing media."""
        transport_info = self.soco.get_current_transport_info()
        new_status = transport_info["current_transport_state"]

        if new_status == SONOS_STATE_TRANSITIONING:
            return

        update_position = new_status != self.playback_status
        self.playback_status = new_status
        self.play_mode = self.soco.play_mode

        self.set_basic_track_info(update_position=update_position)

        self.write_media_player_states()

    def update_media_position(
        self, position_info: dict[str, int], force_update: bool = False
    ) -> None:
        """Update state when playing music tracks."""
        if (duration := position_info.get(DURATION_SECONDS)) == 0:
            self.clear_position()
            return

        should_update = force_update
        self.duration = duration
        current_position = position_info.get(POSITION_SECONDS)

        # player started reporting position?
        if current_position is not None and self.position is None:
            should_update = True

        # position jumped?
        if current_position is not None and self.position is not None:
            if self.playback_status == SONOS_STATE_PLAYING:
                assert self.position_updated_at is not None
                time_delta = dt_util.utcnow() - self.position_updated_at
                time_diff = time_delta.total_seconds()
            else:
                time_diff = 0

            calculated_position = self.position + time_diff

            if abs(calculated_position - current_position) > 1.5:
                should_update = True

        if current_position is None:
            self.clear_position()
        elif should_update:
            self.position = current_position
            self.position_updated_at = dt_util.utcnow()
<|endoftext|>


<commit_before>"""
homeassistant.components.switch.wemo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Support for WeMo switches.
"""
import logging

from homeassistant.components.switch import SwitchDevice
from homeassistant.const import STATE_ON, STATE_OFF, STATE_STANDBY

REQUIREMENTS = ['pywemo==0.3']

# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
    """ Find and return WeMo switches. """
    import pywemo
    import pywemo.discovery as discovery

    if discovery_info is not None:
        device = discovery.device_from_description(discovery_info[2])

        if device:
            add_devices_callback([WemoSwitch(device)])

        return

    logging.getLogger(__name__).info("Scanning for WeMo devices")
    switches = pywemo.discover_devices()

    # Filter out the switches and wrap in WemoSwitch object
    add_devices_callback(
        [WemoSwitch(switch) for switch in switches
         if isinstance(switch, pywemo.Switch)])

class WemoSwitch(SwitchDevice):
    """ Represents a WeMo switch within Home Assistant. """
    def __init__(self, wemo):
        self.wemo = wemo
        self.insight_params = None
        self.maker_params = None

    @property
    def unique_id(self):
        """ Returns the id of this WeMo switch """
        return "{}.{}".format(self.__class__, self.wemo.serialnumber)

    @property
    def name(self):
        """ Returns the name of the switch if any. """
        return self.wemo.name

    @property
    def state(self):
        """ Returns the state. """
        is_on = self.is_on
        if not is_on:
            return STATE_OFF
        elif self.is_standby:
            print(STATE_STANDBY)
            print(self.wemo)
            # import pdb; pdb.set_trace()
            return STATE_STANDBY
        return STATE_ON

    @property
    def current_power_mwh(self):
        """ Current power usage in mwh. """
        if self.insight_params:
            return self.insight_params['currentpower']

    @property
    def today_power_mw(self):
        """ Today total power usage in mw. """
        if self.insight_params:
            return self.insight_params['todaymw']

    @property
    def is_standby(self):
        """ Is the device on - or in standby. """
        if self.insight_params:
            standby_state = self.insight_params['state']
            # Standby  is actually '8' but seems more defensive
            # to check for the On and Off states
            if standby_state == '1' or standby_state == '0':
                return False
            else:
                return True

    @property
    def sensor_state(self):
        """ Is the sensor on or off. """
        if self.maker_params and self.has_sensor:
            # Note a state of 1 matches the WeMo app 'not triggered'!
            if self.maker_params['sensorstate']:
                return STATE_OFF
            else:
                return STATE_ON

    @property
    def switch_mode(self):
        """ Is the switch configured as toggle(0) or momentary (1). """
        if self.maker_params:
            return self.maker_params['switchmode']

    @property
    def has_sensor(self):
        """ Is the sensor present? """
        if self.maker_params:
            return self.maker_params['hassensor']

    @property
    def is_on(self):
        """ True if switch is on. """
        return self.wemo.get_state()

    def turn_on(self, **kwargs):
        """ Turns the switch on. """
        self.wemo.on()

    def turn_off(self):
        """ Turns the switch off. """
        self.wemo.off()

    def update(self):
        """ Update WeMo state. """
        self.wemo.get_state(True)
        if self.wemo.model_name == 'Insight':
            self.insight_params = self.wemo.insight_params
            self.insight_params['standby_state'] = self.wemo.get_standby_state
        elif self.wemo.model_name == 'Maker':
            self.maker_params = self.wemo.maker_params
<commit_msg>Remove debug statements!<commit_after>"""
homeassistant.components.switch.wemo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Support for WeMo switches.
"""
import logging

from homeassistant.components.switch import SwitchDevice
from homeassistant.const import STATE_ON, STATE_OFF, STATE_STANDBY

REQUIREMENTS = ['pywemo==0.3']

# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
    """ Find and return WeMo switches. """
    import pywemo
    import pywemo.discovery as discovery

    if discovery_info is not None:
        device = discovery.device_from_description(discovery_info[2])

        if device:
            add_devices_callback([WemoSwitch(device)])

        return

    logging.getLogger(__name__).info("Scanning for WeMo devices")
    switches = pywemo.discover_devices()

    # Filter out the switches and wrap in WemoSwitch object
    add_devices_callback(
        [WemoSwitch(switch) for switch in switches
         if isinstance(switch, pywemo.Switch)])

class WemoSwitch(SwitchDevice):
    """ Represents a WeMo switch within Home Assistant. """
    def __init__(self, wemo):
        self.wemo = wemo
        self.insight_params = None
        self.maker_params = None

    @property
    def unique_id(self):
        """ Returns the id of this WeMo switch """
        return "{}.{}".format(self.__class__, self.wemo.serialnumber)

    @property
    def name(self):
        """ Returns the name of the switch if any. """
        return self.wemo.name

    @property
    def state(self):
        """ Returns the state. """
        is_on = self.is_on
        if not is_on:
            return STATE_OFF
        elif self.is_standby:
            return STATE_STANDBY
        return STATE_ON

    @property
    def current_power_mwh(self):
        """ Current power usage in mwh. """
        if self.insight_params:
            return self.insight_params['currentpower']

    @property
    def today_power_mw(self):
        """ Today total power usage in mw. """
        if self.insight_params:
            return self.insight_params['todaymw']

    @property
    def is_standby(self):
        """ Is the device on - or in standby. """
        if self.insight_params:
            standby_state = self.insight_params['state']
            # Standby  is actually '8' but seems more defensive
            # to check for the On and Off states
            if standby_state == '1' or standby_state == '0':
                return False
            else:
                return True

    @property
    def sensor_state(self):
        """ Is the sensor on or off. """
        if self.maker_params and self.has_sensor:
            # Note a state of 1 matches the WeMo app 'not triggered'!
            if self.maker_params['sensorstate']:
                return STATE_OFF
            else:
                return STATE_ON

    @property
    def switch_mode(self):
        """ Is the switch configured as toggle(0) or momentary (1). """
        if self.maker_params:
            return self.maker_params['switchmode']

    @property
    def has_sensor(self):
        """ Is the sensor present? """
        if self.maker_params:
            return self.maker_params['hassensor']

    @property
    def is_on(self):
        """ True if switch is on. """
        return self.wemo.get_state()

    def turn_on(self, **kwargs):
        """ Turns the switch on. """
        self.wemo.on()

    def turn_off(self):
        """ Turns the switch off. """
        self.wemo.off()

    def update(self):
        """ Update WeMo state. """
        self.wemo.get_state(True)
        if self.wemo.model_name == 'Insight':
            self.insight_params = self.wemo.insight_params
            self.insight_params['standby_state'] = self.wemo.get_standby_state
        elif self.wemo.model_name == 'Maker':
            self.maker_params = self.wemo.maker_params
<|endoftext|>


<commit_before>"""compares yearly summaries"""

from pandas.io.sql import read_sql
from pyiem.plot import figure_axes
from pyiem.util import get_autoplot_context, get_dbconn
from pyiem.exceptions import NoDataFound

PDICT = dict(
    [
        ("avg_high", "Average High Temperature"),
        ("avg_low", "Average Low Temperature"),
        ("avg_temp", "Average Temperature"),
        ("max_high", "Maximum Daily High"),
        ("max_low", "Maximum Daily Low"),
        ("total_precip", "Total Precipitation"),
    ]
)

def get_description():
    """Return a dict describing how to call this plotter"""
    desc = dict()
    desc["data"] = True
    desc[
        "description"
    ] = """This chart compares yearly summaries between two
    long term climate sites."""
    desc["arguments"] = [
        dict(
            type="select",
            options=PDICT,
            name="var",
            label="Select Variable to Plot",
            default="avg_temp",
        ),
        dict(
            type="station",
            name="station1",
            default="IATDSM",
            label="Select First Station:",
            network="IACLIMATE",
        ),
        dict(
            type="station",
            name="station2",
            default="IA0200",
            label="Select Secont Station:",
            network="IACLIMATE",
        ),
    ]
    return desc

def plotter(fdict):
    """Go"""
    pgconn = get_dbconn("coop")
    ctx = get_autoplot_context(fdict, get_description())
    station1 = ctx["station1"].upper()
    station2 = ctx["station2"].upper()
    table1 = "alldata_%s" % (station1[:2],)
    table2 = "alldata_%s" % (station2[:2],)
    varname = ctx["var"]

    df = read_sql(
        f"""WITH one as (
      SELECT year, sum(precip) as one_total_precip,
      avg(high) as one_avg_high, avg(low) as one_avg_low,
      avg((high+low)/2.) as one_avg_temp, max(high) as one_max_high,
      min(low) as one_min_low from {table1} WHERE
      station = %s GROUP by year),
    two as (
      SELECT year, sum(precip) as two_total_precip,
      avg(high) as two_avg_high, avg(low) as two_avg_low,
      avg((high+low)/2.) as two_avg_temp, max(high) as two_max_high,
      min(low) as two_min_low from {table2} WHERE
      station = %s GROUP by year
    )

    SELECT o.year, one_total_precip, one_avg_high, one_avg_low,
    one_avg_temp, one_max_high, one_min_low, two_total_precip, two_avg_high,
    two_avg_low, two_avg_temp, two_max_high, two_min_low from one o JOIN two t
    on (o.year = t.year) ORDER by o.year ASC
    """,
        pgconn,
        params=(station1, station2),
        index_col="year",
    )
    if df.empty:
        raise NoDataFound("No Data Found.")
    df["one_station"] = station1
    df["two_station"] = station2
    for col in [
        "total_precip",
        "avg_high",
        "avg_low",
        "max_high",
        "min_low",
        "avg_temp",
    ]:
        df["diff_" + col] = df["one_" + col] - df["two_" + col]

    title = "Yearly %s [%s] %s\nminus [%s] %s" % (
        PDICT[varname],
        station1,
        ctx["_nt1"].sts[station1]["name"],
        station2,
        ctx["_nt2"].sts[station2]["name"],
    )
    (fig, ax) = figure_axes(title=title)
    color_above = "b" if varname in ["total_precip"] else "r"
    color_below = "r" if color_above == "b" else "b"

    bars = ax.bar(
        df.index, df["diff_" + varname], fc=color_above, ec=color_above
    )
    for mybar, val in zip(bars, df["diff_" + varname].values):
        if val < 0:
            mybar.set_facecolor(color_below)
            mybar.set_edgecolor(color_below)
    units = "inch" if varname in ["total_precip"] else "F"
    lbl = "wetter" if units == "inch" else "warmer"
    wins = len(df[df["diff_" + varname] > 0].index)
    ax.text(
        0.5,
        0.95,
        "%s %s (%s/%s)"
        % (ctx["_nt1"].sts[station1]["name"], lbl, wins, len(df.index)),
        transform=ax.transAxes,
        ha="center",
    )
    wins = len(df[df["diff_" + varname] < 0].index)
    ax.text(
        0.5,
        0.05,
        "%s %s (%s/%s)"
        % (ctx["_nt1"].sts[station2]["name"], lbl, wins, len(df.index)),
        transform=ax.transAxes,
        ha="center",
    )
    ax.axhline(df["diff_" + varname].mean(), lw=2, color="k")
    ax.set_ylabel(
        "%s [%s] Avg: %.2f"
        % (PDICT[varname], units, df["diff_" + varname].mean())
    )
    ax.grid(True)
    ax.set_xlim(df.index.min() - 1, df.index.max() + 1)
    ymax = df["diff_" + varname].abs().max() * 1.1
    ax.set_ylim(0 - ymax, ymax)
    return fig, df

if __name__ == "__main__":
    plotter(dict())
<commit_msg>correct station lookup typo<commit_after>"""compares yearly summaries"""

from pandas.io.sql import read_sql
from pyiem.plot import figure_axes
from pyiem.util import get_autoplot_context, get_dbconn
from pyiem.exceptions import NoDataFound

PDICT = dict(
    [
        ("avg_high", "Average High Temperature"),
        ("avg_low", "Average Low Temperature"),
        ("avg_temp", "Average Temperature"),
        ("max_high", "Maximum Daily High"),
        ("max_low", "Maximum Daily Low"),
        ("total_precip", "Total Precipitation"),
    ]
)

def get_description():
    """Return a dict describing how to call this plotter"""
    desc = dict()
    desc["data"] = True
    desc[
        "description"
    ] = """This chart compares yearly summaries between two
    long term climate sites."""
    desc["arguments"] = [
        dict(
            type="select",
            options=PDICT,
            name="var",
            label="Select Variable to Plot",
            default="avg_temp",
        ),
        dict(
            type="station",
            name="station1",
            default="IATDSM",
            label="Select First Station:",
            network="IACLIMATE",
        ),
        dict(
            type="station",
            name="station2",
            default="IA0200",
            label="Select Secont Station:",
            network="IACLIMATE",
        ),
    ]
    return desc

def plotter(fdict):
    """Go"""
    pgconn = get_dbconn("coop")
    ctx = get_autoplot_context(fdict, get_description())
    station1 = ctx["station1"].upper()
    station2 = ctx["station2"].upper()
    table1 = "alldata_%s" % (station1[:2],)
    table2 = "alldata_%s" % (station2[:2],)
    varname = ctx["var"]

    df = read_sql(
        f"""WITH one as (
      SELECT year, sum(precip) as one_total_precip,
      avg(high) as one_avg_high, avg(low) as one_avg_low,
      avg((high+low)/2.) as one_avg_temp, max(high) as one_max_high,
      min(low) as one_min_low from {table1} WHERE
      station = %s GROUP by year),
    two as (
      SELECT year, sum(precip) as two_total_precip,
      avg(high) as two_avg_high, avg(low) as two_avg_low,
      avg((high+low)/2.) as two_avg_temp, max(high) as two_max_high,
      min(low) as two_min_low from {table2} WHERE
      station = %s GROUP by year
    )

    SELECT o.year, one_total_precip, one_avg_high, one_avg_low,
    one_avg_temp, one_max_high, one_min_low, two_total_precip, two_avg_high,
    two_avg_low, two_avg_temp, two_max_high, two_min_low from one o JOIN two t
    on (o.year = t.year) ORDER by o.year ASC
    """,
        pgconn,
        params=(station1, station2),
        index_col="year",
    )
    if df.empty:
        raise NoDataFound("No Data Found.")
    df["one_station"] = station1
    df["two_station"] = station2
    for col in [
        "total_precip",
        "avg_high",
        "avg_low",
        "max_high",
        "min_low",
        "avg_temp",
    ]:
        df["diff_" + col] = df["one_" + col] - df["two_" + col]

    title = "Yearly %s [%s] %s\nminus [%s] %s" % (
        PDICT[varname],
        station1,
        ctx["_nt1"].sts[station1]["name"],
        station2,
        ctx["_nt2"].sts[station2]["name"],
    )
    (fig, ax) = figure_axes(title=title)
    color_above = "b" if varname in ["total_precip"] else "r"
    color_below = "r" if color_above == "b" else "b"

    bars = ax.bar(
        df.index, df["diff_" + varname], fc=color_above, ec=color_above
    )
    for mybar, val in zip(bars, df["diff_" + varname].values):
        if val < 0:
            mybar.set_facecolor(color_below)
            mybar.set_edgecolor(color_below)
    units = "inch" if varname in ["total_precip"] else "F"
    lbl = "wetter" if units == "inch" else "warmer"
    wins = len(df[df["diff_" + varname] > 0].index)
    ax.text(
        0.5,
        0.95,
        "%s %s (%s/%s)"
        % (ctx["_nt1"].sts[station1]["name"], lbl, wins, len(df.index)),
        transform=ax.transAxes,
        ha="center",
    )
    wins = len(df[df["diff_" + varname] < 0].index)
    ax.text(
        0.5,
        0.05,
        "%s %s (%s/%s)"
        % (ctx["_nt2"].sts[station2]["name"], lbl, wins, len(df.index)),
        transform=ax.transAxes,
        ha="center",
    )
    ax.axhline(df["diff_" + varname].mean(), lw=2, color="k")
    ax.set_ylabel(
        "%s [%s] Avg: %.2f"
        % (PDICT[varname], units, df["diff_" + varname].mean())
    )
    ax.grid(True)
    ax.set_xlim(df.index.min() - 1, df.index.max() + 1)
    ymax = df["diff_" + varname].abs().max() * 1.1
    ax.set_ylim(0 - ymax, ymax)
    return fig, df

if __name__ == "__main__":
    plotter(
        dict(
            var="max_high",
            network1="NYCLIMATE",
            station1="NYTNYC",
            network2="MACLIMATE",
            station2="MATBOS",
        )
    )
<|endoftext|>


<commit_before>"""Tools for setting up printing in interactive sessions. """

from sympy import latex

def _init_python_printing(stringify_func):
    """Setup printing in Python interactive session. """
    import __builtin__, sys

    def _displayhook(arg):
        """Python's pretty-printer display hook.

           This function was adapted from:

            http://www.python.org/dev/peps/pep-0217/

        """
        if arg is not None:
            __builtin__._ = None
            print stringify_func(arg)
            __builtin__._ = arg

    sys.displayhook = _displayhook

def _init_ipython_printing(ip, stringify_func):
    """Setup printing in IPython interactive session. """
    # For IPython >= 0.11, will use latex_to_png to render LaTeX
    try:
        from IPython.lib.latextools import latex_to_png
    except ImportError:
        pass

    def _print_pretty(arg, p, cycle):
        """caller for pretty, for use in IPython 0.11"""
        p.text(stringify_func(arg))

    def _print_png(o):
        """
        A function to display sympy expressions using inline style LaTeX in PNG.
        """
        s = latex(o, mode='inline')
        # mathtext does not understand centain latex flags, so we try to
        # replace them with suitable subs
        s = s.replace(r'\operatorname', '')
        s = s.replace(r'\overline', r'\bar')
        png = latex_to_png(s)
        return png

    def _print_png(o):
        """
        A function to display sympy expression using display style LaTeX in PNG.
        """
        s = latex(o, mode='plain')
        s = s.strip('$')
        # As matplotlib does not support display style, dvipng backend is used
        # here
        png = latex_to_png(s, backend='dvipng', wrap=True)
        return png

    def _can_print_latex(o):
        """Return True if type o can be printed with LaTeX.

        If o is a container type, this is True if and only if every element of
        o can be printed with LaTeX.
        """
        if isinstance(o, (list, tuple, set, frozenset)):
            return all(can_print_latex(i) for i in o)
        elif isinstance(o, dict):
            return all((isinstance(i, basestring) or can_print_latex(i)) and can_print_latex(o[i]) for i in o)
        elif isinstance(o,(sympy.Basic, sympy.matrices.MatrixBase, int, long, float)):
            return True
        return False

    def _print_latex(o):
        """
        A function to generate the latex representation of sympy expressions.
        """
        if _can_print_latex(o):
            s = latex(o, mode='plain')
            s = s.replace(r'\dag', r'\dagger')
            s = s.strip('$')
            return '$$%s$$' % s
        # Fallback to the string printer
        return None

    def _result_display(self, arg):
        """IPython's pretty-printer display hook, for use in IPython 0.10

           This function was adapted from:

            ipython/IPython/hooks.py:155

        """
        if self.rc.pprint:
            out = stringify_func(arg)

            if '\n' in out:
                print

            print out
        else:
            print repr(arg)

    import IPython
    if IPython.__version__ >= '0.11':
        printable_containers = [tuple, list, set, frozenset]

        plaintext_formatter = ip.display_formatter.formatters['text/plain']

        for cls in [object, str, dict] + printable_containers:
            plaintext_formatter.for_type(cls, _print_pretty)

        plaintext_formatter.for_type_by_name(
            'sympy.core.basic', 'Basic', _print_pretty
        )
        plaintext_formatter.for_type_by_name(
            'sympy.matrices.matrices', 'MatrixBase', _print_pretty
        )

        png_formatter = ip.display_formatter.formatters['image/png']

        png_formatter.for_type_by_name(
            'sympy.core.basic', 'Basic', _print_png
        )
        png_formatter.for_type_by_name(
            'sympy.matrices.matrices', 'MatrixBase', _print_png
        )

        for cls in [dict, int, long, float] + printable_containers:
            png_formatter.for_type(cls, _print_png)

        latex_formatter = ip.display_formatter.formatters['text/latex']
        latex_formatter.for_type_by_name(
            'sympy.core.basic', 'Basic', _print_latex
        )
        latex_formatter.for_type_by_name(
            'sympy.matrices.matrices', 'MatrixBase', _print_latex
        )
        for cls in printable_containers:
            latex_formatter.for_type(cls, _print_latex)
    else:
        ip.set_hook('result_display', _result_display)

def init_printing(pretty_print=True, order=None, use_unicode=None, wrap_line=None, num_columns=None, no_global=False, ip=None):
    """
    Initializes pretty-printer depending on the environment.

    Parameters
    ==========

    pretty_print: boolean
        If True, use pretty_print to stringify;
        if False, use sstrrepr to stringify.
    order: string or None
        There are a few different settings for this parameter:
        lex (default), which is lexographic order;
        grlex, which is graded lexographic order;
        grevlex, which is reversed graded lexographic order;
        old, which is used for compatibility reasons and for long expressions;
        None, which sets it to lex.
    use_unicode: boolean or None
        If True, use unicode characters;
        if False, do not use unicode characters.
    wrap_line: boolean
        If True, lines will wrap at the end;
        if False, they will not wrap but continue as one line.
    num_columns: int or None
        If int, number of columns before wrapping is set to num_columns;
        if None, number of columns before wrapping is set to terminal width.
    no_global: boolean
        If True, the settings become system wide;
        if False, use just for this console/session.
    ip: An interactive console
        This can either be an instance of IPython,
        or a class that derives from code.InteractiveConsole.

    Examples
    ========
    >>> from sympy.interactive import init_printing
    >>> from sympy import Symbol, sqrt
    >>> from sympy.abc import x, y
    >>> sqrt(5)
    sqrt(5)
    >>> init_printing(pretty_print=True) # doctest: +SKIP
    >>> sqrt(5) # doctest: +SKIP
      ___
    \/ 5
    >>> theta = Symbol('theta') # doctest: +SKIP
    >>> init_printing(use_unicode=True) # doctest: +SKIP
    >>> theta # doctest: +SKIP
    \u03b8
    >>> init_printing(use_unicode=False) # doctest: +SKIP
    >>> theta # doctest: +SKIP
    theta
    >>> init_printing(order='lex') # doctest: +SKIP
    >>> str(y + x + y**2 + x**2) # doctest: +SKIP
    x**2 + x + y**2 + y
    >>> init_printing(order='grlex') # doctest: +SKIP
    >>> str(y + x + y**2 + x**2) # doctest: +SKIP
    x**2 + x + y**2 + y
    >>> init_printing(order='grevlex') # doctest: +SKIP
    >>> str(y * x**2 + x * y**2) # doctest: +SKIP
    x**2*y + x*y**2
    >>> init_printing(order='old') # doctest: +SKIP
    >>> str(x**2 + y**2 + x + y) # doctest: +SKIP
    x**2 + x + y**2 + y
    >>> init_printing(num_columns=10) # doctest: +SKIP
    >>> x**2 + x + y**2 + y # doctest: +SKIP
    x + y +
    x**2 + y**2
    """
    from sympy.printing.printer import Printer

    if pretty_print:
        from sympy.printing import pretty as stringify_func
    else:
        from sympy.printing import sstrrepr as stringify_func

    if not no_global:
        Printer.set_global_settings(order=order, use_unicode=use_unicode, wrap_line=wrap_line, num_columns=num_columns)
    else:
        _stringify_func = stringify_func

        if pretty_print:
            stringify_func = lambda expr: _stringify_func(expr, order=order, use_unicode=use_unicode, wrap_line=wrap_line, num_columns=num_columns)
        else:
            stringify_func = lambda expr: _stringify_func(expr, order=order)

    if ip is not None and ip.__module__.startswith('IPython'):
        _init_ipython_printing(ip, stringify_func)
    else:
        _init_python_printing(stringify_func)
<commit_msg>Fix Matrix latex rendering using ipythonprinting<commit_after>"""Tools for setting up printing in interactive sessions. """

from sympy import latex

def _init_python_printing(stringify_func):
    """Setup printing in Python interactive session. """
    import __builtin__, sys

    def _displayhook(arg):
        """Python's pretty-printer display hook.

           This function was adapted from:

            http://www.python.org/dev/peps/pep-0217/

        """
        if arg is not None:
            __builtin__._ = None
            print stringify_func(arg)
            __builtin__._ = arg

    sys.displayhook = _displayhook

def _init_ipython_printing(ip, stringify_func):
    """Setup printing in IPython interactive session. """
    # For IPython >= 0.11, will use latex_to_png to render LaTeX
    try:
        from IPython.lib.latextools import latex_to_png
    except ImportError:
        pass

    def _print_pretty(arg, p, cycle):
        """caller for pretty, for use in IPython 0.11"""
        p.text(stringify_func(arg))

    def _print_png(o):
        """
        A function to display sympy expressions using inline style LaTeX in PNG.
        """
        s = latex(o, mode='inline')
        # mathtext does not understand centain latex flags, so we try to
        # replace them with suitable subs
        s = s.replace(r'\operatorname', '')
        s = s.replace(r'\overline', r'\bar')
        png = latex_to_png(s)
        return png

    def _print_display_png(o):
        """
        A function to display sympy expression using display style LaTeX in PNG.
        """
        s = latex(o, mode='plain')
        s = s.strip('$')
        # As matplotlib does not support display style, dvipng backend is used
        # here
        png = latex_to_png(s, backend='dvipng', wrap=True)
        return png

    def _can_print_latex(o):
        """Return True if type o can be printed with LaTeX.

        If o is a container type, this is True if and only if every element of
        o can be printed with LaTeX.
        """
        if isinstance(o, (list, tuple, set, frozenset)):
            return all(can_print_latex(i) for i in o)
        elif isinstance(o, dict):
            return all((isinstance(i, basestring) or can_print_latex(i)) and can_print_latex(o[i]) for i in o)
        elif isinstance(o,(sympy.Basic, sympy.matrices.MatrixBase, int, long, float)):
            return True
        return False

    def _print_latex(o):
        """
        A function to generate the latex representation of sympy expressions.
        """
        if _can_print_latex(o):
            s = latex(o, mode='plain')
            s = s.replace(r'\dag', r'\dagger')
            s = s.strip('$')
            return '$$%s$$' % s
        # Fallback to the string printer
        return None

    def _result_display(self, arg):
        """IPython's pretty-printer display hook, for use in IPython 0.10

           This function was adapted from:

            ipython/IPython/hooks.py:155

        """
        if self.rc.pprint:
            out = stringify_func(arg)

            if '\n' in out:
                print

            print out
        else:
            print repr(arg)

    import IPython
    if IPython.__version__ >= '0.11':
        printable_containers = [tuple, list, set, frozenset]

        plaintext_formatter = ip.display_formatter.formatters['text/plain']

        for cls in [object, str, dict] + printable_containers:
            plaintext_formatter.for_type(cls, _print_pretty)

        plaintext_formatter.for_type_by_name(
            'sympy.core.basic', 'Basic', _print_pretty
        )
        plaintext_formatter.for_type_by_name(
            'sympy.matrices.matrices', 'MatrixBase', _print_pretty
        )

        png_formatter = ip.display_formatter.formatters['image/png']

        png_formatter.for_type_by_name(
            'sympy.core.basic', 'Basic', _print_png
        )
        png_formatter.for_type_by_name(
            'sympy.matrices.matrices', 'MatrixBase', _print_display_png
        )

        for cls in [dict, int, long, float] + printable_containers:
            png_formatter.for_type(cls, _print_png)

        latex_formatter = ip.display_formatter.formatters['text/latex']
        latex_formatter.for_type_by_name(
            'sympy.core.basic', 'Basic', _print_latex
        )
        latex_formatter.for_type_by_name(
            'sympy.matrices.matrices', 'MatrixBase', _print_latex
        )
        for cls in printable_containers:
            latex_formatter.for_type(cls, _print_latex)
    else:
        ip.set_hook('result_display', _result_display)

def init_printing(pretty_print=True, order=None, use_unicode=None, wrap_line=None, num_columns=None, no_global=False, ip=None):
    """
    Initializes pretty-printer depending on the environment.

    Parameters
    ==========

    pretty_print: boolean
        If True, use pretty_print to stringify;
        if False, use sstrrepr to stringify.
    order: string or None
        There are a few different settings for this parameter:
        lex (default), which is lexographic order;
        grlex, which is graded lexographic order;
        grevlex, which is reversed graded lexographic order;
        old, which is used for compatibility reasons and for long expressions;
        None, which sets it to lex.
    use_unicode: boolean or None
        If True, use unicode characters;
        if False, do not use unicode characters.
    wrap_line: boolean
        If True, lines will wrap at the end;
        if False, they will not wrap but continue as one line.
    num_columns: int or None
        If int, number of columns before wrapping is set to num_columns;
        if None, number of columns before wrapping is set to terminal width.
    no_global: boolean
        If True, the settings become system wide;
        if False, use just for this console/session.
    ip: An interactive console
        This can either be an instance of IPython,
        or a class that derives from code.InteractiveConsole.

    Examples
    ========
    >>> from sympy.interactive import init_printing
    >>> from sympy import Symbol, sqrt
    >>> from sympy.abc import x, y
    >>> sqrt(5)
    sqrt(5)
    >>> init_printing(pretty_print=True) # doctest: +SKIP
    >>> sqrt(5) # doctest: +SKIP
      ___
    \/ 5
    >>> theta = Symbol('theta') # doctest: +SKIP
    >>> init_printing(use_unicode=True) # doctest: +SKIP
    >>> theta # doctest: +SKIP
    \u03b8
    >>> init_printing(use_unicode=False) # doctest: +SKIP
    >>> theta # doctest: +SKIP
    theta
    >>> init_printing(order='lex') # doctest: +SKIP
    >>> str(y + x + y**2 + x**2) # doctest: +SKIP
    x**2 + x + y**2 + y
    >>> init_printing(order='grlex') # doctest: +SKIP
    >>> str(y + x + y**2 + x**2) # doctest: +SKIP
    x**2 + x + y**2 + y
    >>> init_printing(order='grevlex') # doctest: +SKIP
    >>> str(y * x**2 + x * y**2) # doctest: +SKIP
    x**2*y + x*y**2
    >>> init_printing(order='old') # doctest: +SKIP
    >>> str(x**2 + y**2 + x + y) # doctest: +SKIP
    x**2 + x + y**2 + y
    >>> init_printing(num_columns=10) # doctest: +SKIP
    >>> x**2 + x + y**2 + y # doctest: +SKIP
    x + y +
    x**2 + y**2
    """
    from sympy.printing.printer import Printer

    if pretty_print:
        from sympy.printing import pretty as stringify_func
    else:
        from sympy.printing import sstrrepr as stringify_func

    if not no_global:
        Printer.set_global_settings(order=order, use_unicode=use_unicode, wrap_line=wrap_line, num_columns=num_columns)
    else:
        _stringify_func = stringify_func

        if pretty_print:
            stringify_func = lambda expr: _stringify_func(expr, order=order, use_unicode=use_unicode, wrap_line=wrap_line, num_columns=num_columns)
        else:
            stringify_func = lambda expr: _stringify_func(expr, order=order)

    if ip is not None and ip.__module__.startswith('IPython'):
        _init_ipython_printing(ip, stringify_func)
    else:
        _init_python_printing(stringify_func)
<|endoftext|>


<commit_before># Copyright 2018 The Hypebot 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.
"""Interface that captures messages sent as output."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from typing import List, Text

from hypebot import types
from hypebot.interfaces import interface_lib

class CaptureInterface(interface_lib.BaseChatInterface):
  """Interface that captures output."""

  def __init__(self, unused_params):
    """This interface ignores everything."""
    self._msgs = []  # type: List[Text]

  def MessageLog(self) -> Text:
    return u'\n'.join(self._msgs)

  # =======================
  # BaseInterface overrides
  # =======================

  def Join(self, channel: types.Channel):
    """This interface does not interact with a chat application."""
    pass

  def Leave(self, channel: types.Channel):
    """This interface does not interact with a chat application."""
    pass

  def Loop(self):
    """This interface does not interact with a chat application."""
    pass

  def Who(self, unused_user: types.User):
    """This interface doesn't care about plebs."""
    pass

  def WhoAll(self):
    """This interface doesn't care about plebs."""
    pass

  def SendMessage(self, unused_channel: types.Channel, message: types.Message):
    for msg in message.messages:
      if msg.WhichOneof('message') == 'card':
        self._msgs.extend(msg.card.alternate_text)
      else:
        self._msgs.append(msg.text)

  def Notice(self, unused_channel: types.Channel,
             unused_message: types.Message):
    pass

  def Topic(self, unused_channel: types.Channel, unused_new_topic: Text):
    pass
<commit_msg>Update capture interface for new message proto format.<commit_after># Copyright 2018 The Hypebot 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.
"""Interface that captures messages sent as output."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from typing import List, Text

from hypebot import types
from hypebot.interfaces import interface_lib

class CaptureInterface(interface_lib.BaseChatInterface):
  """Interface that captures output."""

  def __init__(self, unused_params):
    """This interface ignores everything."""
    self._msgs = []  # type: List[Text]

  def MessageLog(self) -> Text:
    return '\n'.join(self._msgs)

  # =======================
  # BaseInterface overrides
  # =======================

  def Join(self, channel: types.Channel):
    """This interface does not interact with a chat application."""
    pass

  def Leave(self, channel: types.Channel):
    """This interface does not interact with a chat application."""
    pass

  def Loop(self):
    """This interface does not interact with a chat application."""
    pass

  def Who(self, unused_user: types.User):
    """This interface doesn't care about plebs."""
    pass

  def WhoAll(self):
    """This interface doesn't care about plebs."""
    pass

  def SendMessage(self, unused_channel: types.Channel, message: types.Message):
    for msg in message.messages:
      # Messages with only cards and no text will have had default text already
      # added by the HypeCore.
      self._msgs.extend(msg.text)

  def Notice(self, unused_channel: types.Channel,
             unused_message: types.Message):
    pass

  def Topic(self, unused_channel: types.Channel, unused_new_topic: Text):
    pass
<|endoftext|>


<commit_before>VERSION = "1.1.0"
STABLE = True

if __name__ == '__main__':
    print(str(STABLE))
<commit_msg>stable back to false<commit_after>VERSION = "1.1.0"
STABLE = False

if __name__ == '__main__':
    print(str(STABLE))
<|endoftext|>


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

from __future__ import print_function

import argparse

import chainer
from chainer import training
from chainer.training import extensions

from facade_dataset import FacadeDataset
from facade_visualizer import out_image

from net import Decoder
from net import Discriminator
from net import Encoder

from updater import FacadeUpdater

def main():
    parser = argparse.ArgumentParser(
        description='chainer implementation of pix2pix')
    parser.add_argument('--batchsize', '-b', type=int, default=1,
                        help='Number of images in each mini-batch')
    parser.add_argument('--epoch', '-e', type=int, default=200,
                        help='Number of sweeps over the dataset to train')
    parser.add_argument('--gpu', '-g', type=int, default=-1,
                        help='GPU ID (negative value indicates CPU)')
    parser.add_argument('--dataset', '-i', default='./facade/base',
                        help='Directory of image files.')
    parser.add_argument('--out', '-o', default='result',
                        help='Directory to output the result')
    parser.add_argument('--resume', '-r', default='',
                        help='Resume the training from snapshot')
    parser.add_argument('--seed', type=int, default=0,
                        help='Random seed')
    parser.add_argument('--snapshot_interval', type=int, default=1000,
                        help='Interval of snapshot')
    parser.add_argument('--display_interval', type=int, default=100,
                        help='Interval of displaying log to console')
    args = parser.parse_args()

    print('GPU: {}'.format(args.gpu))
    print('# Minibatch-size: {}'.format(args.batchsize))
    print('# epoch: {}'.format(args.epoch))
    print('')

    # Set up a neural network to train
    enc = Encoder(in_ch=12)
    dec = Decoder(out_ch=3)
    dis = Discriminator(in_ch=12, out_ch=3)

    if args.gpu >= 0:
        chainer.cuda.get_device(args.gpu).use()  # Make a specified GPU current
        enc.to_gpu()  # Copy the model to the GPU
        dec.to_gpu()
        dis.to_gpu()

    # Setup an optimizer
    def make_optimizer(model, alpha=0.0002, beta1=0.5):
        optimizer = chainer.optimizers.Adam(alpha=alpha, beta1=beta1)
        optimizer.setup(model)
        optimizer.add_hook(chainer.optimizer.WeightDecay(0.00001), 'hook_dec')
        return optimizer
    opt_enc = make_optimizer(enc)
    opt_dec = make_optimizer(dec)
    opt_dis = make_optimizer(dis)

    train_d = FacadeDataset(args.dataset, data_range=(1, 300))
    test_d = FacadeDataset(args.dataset, data_range=(300, 379))
    train_iter = chainer.iterators.SerialIterator(train_d, args.batchsize)
    test_iter = chainer.iterators.SerialIterator(test_d, args.batchsize)

    # Set up a trainer
    updater = FacadeUpdater(
        models=(enc, dec, dis),
        iterator={
            'main': train_iter,
            'test': test_iter},
        optimizer={
            'enc': opt_enc, 'dec': opt_dec,
            'dis': opt_dis},
        device=args.gpu)
    trainer = training.Trainer(updater, (args.epoch, 'epoch'), out=args.out)

    snapshot_interval = (args.snapshot_interval, 'iteration')
    display_interval = (args.display_interval, 'iteration')
    trainer.extend(extensions.snapshot(
        filename='snapshot_iter_{.updater.iteration}.npz'),
        trigger=snapshot_interval)
    trainer.extend(extensions.snapshot_object(
        enc, 'enc_iter_{.updater.iteration}.npz'), trigger=snapshot_interval)
    trainer.extend(extensions.snapshot_object(
        dec, 'dec_iter_{.updater.iteration}.npz'), trigger=snapshot_interval)
    trainer.extend(extensions.snapshot_object(
        dis, 'dis_iter_{.updater.iteration}.npz'), trigger=snapshot_interval)
    trainer.extend(extensions.LogReport(trigger=display_interval))
    trainer.extend(extensions.PrintReport([
        'epoch', 'iteration', 'enc/loss', 'dec/loss', 'dis/loss',
    ]), trigger=display_interval)
    trainer.extend(extensions.ProgressBar(update_interval=10))
    trainer.extend(
        out_image(
            updater, enc, dec,
            5, 5, args.seed, args.out),
        trigger=snapshot_interval)

    if args.resume:
        # Resume from a snapshot
        chainer.serializers.load_npz(args.resume, trainer)

    # Run the training
    trainer.run()

if __name__ == '__main__':
    main()
<commit_msg>set resume None in pix2pix<commit_after>#!/usr/bin/env python

from __future__ import print_function

import argparse

import chainer
from chainer import training
from chainer.training import extensions

from facade_dataset import FacadeDataset
from facade_visualizer import out_image

from net import Decoder
from net import Discriminator
from net import Encoder

from updater import FacadeUpdater

def main():
    parser = argparse.ArgumentParser(
        description='chainer implementation of pix2pix')
    parser.add_argument('--batchsize', '-b', type=int, default=1,
                        help='Number of images in each mini-batch')
    parser.add_argument('--epoch', '-e', type=int, default=200,
                        help='Number of sweeps over the dataset to train')
    parser.add_argument('--gpu', '-g', type=int, default=-1,
                        help='GPU ID (negative value indicates CPU)')
    parser.add_argument('--dataset', '-i', default='./facade/base',
                        help='Directory of image files.')
    parser.add_argument('--out', '-o', default='result',
                        help='Directory to output the result')
    parser.add_argument('--resume', '-r', type=str,
                        help='Resume the training from snapshot')
    parser.add_argument('--seed', type=int, default=0,
                        help='Random seed')
    parser.add_argument('--snapshot_interval', type=int, default=1000,
                        help='Interval of snapshot')
    parser.add_argument('--display_interval', type=int, default=100,
                        help='Interval of displaying log to console')
    args = parser.parse_args()

    print('GPU: {}'.format(args.gpu))
    print('# Minibatch-size: {}'.format(args.batchsize))
    print('# epoch: {}'.format(args.epoch))
    print('')

    # Set up a neural network to train
    enc = Encoder(in_ch=12)
    dec = Decoder(out_ch=3)
    dis = Discriminator(in_ch=12, out_ch=3)

    if args.gpu >= 0:
        chainer.cuda.get_device(args.gpu).use()  # Make a specified GPU current
        enc.to_gpu()  # Copy the model to the GPU
        dec.to_gpu()
        dis.to_gpu()

    # Setup an optimizer
    def make_optimizer(model, alpha=0.0002, beta1=0.5):
        optimizer = chainer.optimizers.Adam(alpha=alpha, beta1=beta1)
        optimizer.setup(model)
        optimizer.add_hook(chainer.optimizer.WeightDecay(0.00001), 'hook_dec')
        return optimizer
    opt_enc = make_optimizer(enc)
    opt_dec = make_optimizer(dec)
    opt_dis = make_optimizer(dis)

    train_d = FacadeDataset(args.dataset, data_range=(1, 300))
    test_d = FacadeDataset(args.dataset, data_range=(300, 379))
    train_iter = chainer.iterators.SerialIterator(train_d, args.batchsize)
    test_iter = chainer.iterators.SerialIterator(test_d, args.batchsize)

    # Set up a trainer
    updater = FacadeUpdater(
        models=(enc, dec, dis),
        iterator={
            'main': train_iter,
            'test': test_iter},
        optimizer={
            'enc': opt_enc, 'dec': opt_dec,
            'dis': opt_dis},
        device=args.gpu)
    trainer = training.Trainer(updater, (args.epoch, 'epoch'), out=args.out)

    snapshot_interval = (args.snapshot_interval, 'iteration')
    display_interval = (args.display_interval, 'iteration')
    trainer.extend(extensions.snapshot(
        filename='snapshot_iter_{.updater.iteration}.npz'),
        trigger=snapshot_interval)
    trainer.extend(extensions.snapshot_object(
        enc, 'enc_iter_{.updater.iteration}.npz'), trigger=snapshot_interval)
    trainer.extend(extensions.snapshot_object(
        dec, 'dec_iter_{.updater.iteration}.npz'), trigger=snapshot_interval)
    trainer.extend(extensions.snapshot_object(
        dis, 'dis_iter_{.updater.iteration}.npz'), trigger=snapshot_interval)
    trainer.extend(extensions.LogReport(trigger=display_interval))
    trainer.extend(extensions.PrintReport([
        'epoch', 'iteration', 'enc/loss', 'dec/loss', 'dis/loss',
    ]), trigger=display_interval)
    trainer.extend(extensions.ProgressBar(update_interval=10))
    trainer.extend(
        out_image(
            updater, enc, dec,
            5, 5, args.seed, args.out),
        trigger=snapshot_interval)

    if args.resume is not None:
        # Resume from a snapshot
        chainer.serializers.load_npz(args.resume, trainer)

    # Run the training
    trainer.run()

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


<commit_before>import scipy as sp

class Splicegraph:

    def __init__(self, genes = None):

        vertices = sp.zeros((2, 0))
        edges = sp.zeros((0, 0))
        terminals = sp.zeros((2, 0))

        if genes:
            from_genes(genes)

    def new_edge(self):

        edges = sp.c_[edges, sp.zeros((edges.shape[0],))]
        edges = sp.r_[edges, sp.zeros((edges.shape[1],))]

    def from_genes(self, genes):

        if gene_idx % 100 == 0:
            print '.',
            if gene_idx % 1000 == 0:
                 print '%i' % gene_idx

        for transcript_idx = len(genes[gene_idx].transcripts):
            exon_start_end = genes[gene_idx].exons[transcript_idx]

            ### only one exon in the transcript
            if exon_start_end.shape[0] == 1,
                exon1_start = exon_start_end[0, 0]
                exon1_end = exon_start_end[0, 1]

                if vertices.shape[1] == 0:
                  vertices[0, 0] = exon1_start
                  vertices[1, 0] = exon1_end
                  edges = 0
                  num_exons = 0
                else:
                  vertices[0, num_exons + 1) = exon1_start
                  vertices[1, num_exons + 1) = exon1_end
                  edges[0, num_exons + 1] = 0
                  edges[num_exons + 1, 0] = 0
                  num_exons += 1
            ### more than one exon in the transcript
            else:
                for exon_idx in  xrange(exon_start_end.shape[0] - 1):
                    exon1_start = exon_start_end[exon_idx , 0]
                    exon1_end = exon_start_end[exon_idx, 1]
                    exon2_start = exon_start_end[exon_idx + 1, 0]
                    exon2_end = exon_start_end[exon_idx + 1, 1]

                    if vertices.shape[1] == 0:
                        vertices[0, 0] = exon1_start
                        vertices[1, 0] = exon1_end
                        vertices[0, 1] = exon2_start
                        vertices[1, 1] = exon2_end
                        edges = sp.zeros((2, 2))
                        edges[0, 1] = 1
                        edges[1, 0] = 1
                        num_exons = 2
                    else:
                        exon1_idx = 0
                        exon2_idx = 0
                        ### check if current exon already occurred
                        for idx in range(num_exons):
                            if ((vertices[0, idx] == exon1_start) && (vertices[1, idx] == exon1_end)):
                                 exon1_idx = idx
                            if ((vertices[0, idx] == exon2_start) && (vertices[1, idx] == exon2_end)):
                                 exon2_idx = idx

                        ### both exons already occured -> only add an edge
                        if (exon1_idx !=0) && (exon2_idx != 0):
                            edges[exon1_idx, exon2_idx] = 1
                            edges[exon2_idx, exon1_idx] = 1
                        else:
                            ### 2nd exon occured
                            if ((exon1_idx == 0) && (exon2_idx !=0 )):
                                vertices[0, num_exons + 1] = exon1_start
                                vertices[1, num_exons + 1] = exon1_end
                                edges[exon2_idx, num_exons + 1] = 1
                                edges[num_exons + 1, exon2_idx] = 1
                                num_exons += 1
                            ### 1st exon occured
                            elif ((exon2_idx == 0) && (exon1_idx !=0)):
                                vertices[0, num_exons + 1] = exon2_start
                                vertices[1, num_exons + 1] = exon2_end
                                edges[exon1_idx, num_exons + 1] = 1
                                edges[num_exons + 1, exon1_idx] = 1
                                num_exons += 1
                            ### no exon occured
                            else:
                                assert((exon1_idx == 0) && (exon2_idx == 0))
                                vertices[0, num_exons + 1] = exon1_start
                                vertices[1, num_exons + 1] = exon1_end
                                num_exons += 1
                                vertices[0, num_exons + 1] = exon2_start
                                vertices[1, num_exons + 1] = exon2_end
                                num_exons += 1

                                edges[num_exons - 1, num_exons] = 1
                                edges[num_exons, num_exons - 1] = 1

                terminals[0, sp.where(vertices[0, :] == exon_start_end.max())[0]] = 1
                terminals[1, sp.where(vertices[1, :] == exon_start_end.max())[0]] = 1

          ### take care of the sorting by exon start
          s_idx = sp.argsort(vertices[0, :])
          vertices = vertices[:, s_idx]
          edges = edges[s_idx, :][:, s_idx]
          if vertices.shape != terminals.shape:
            terminals = sp.c_[terminals, sp.zeros((2,))]
          terminals = terminals[:, s_idx]

    def add_intron(self, idx1, flag1, idx2, flag2):
        """adds new introns into splicegraph between idx1 and idx2"""

        ### if flag1, all end terminal exons in idx1 are preserved
        ### if flag2, all start terminal exons in idx2 are preserved

        if idx2:
            adj_mat = sp.triu(edges)

            if flag1:
                for i1 in idx1:

                    ### if exon is end-terminal
                    if sp.all(adj_mat[i1, :] == 0):

                        vertices = sp.c_[vertices, vertices[:, i1]]

                        _new_edge()
                        edges[:, -1] = edges[:, i1]
                        edges[-1, :] = edges[i1, :]

                        terminals = sp.c_[terminals, terminals[:, i1]]
            if flag2:,
                for i2 in idx2:
                    ### if exon is start-terminal
                    if sp.all(adj_mat[:, i2] == 0):
                        vertices = sp.c_[vertices, vertices[:, i2]]

                        _new_edge()
                        edges[:, -1] = edges[:, i2]
                        edges[-1, :] = edges[i2, :]

                        terminals = sp.c_[terminals, terminals[:, i2]]

        for i1 in idx1:
            for i2 in idx2:
                edges[i1, i2] = 1
                edges[i2, i1] = 1

    def add_cassette_exon(self, new_exon, exons_pre, exons_aft)
        ### exon_pre contains the indices of preceding exons
        ### exon_aft contains the indices of successing exons

        vertices = sp.r_[vertices, new_exon.T]

        _new_edge()

        edges[exons_pre, -1] = 1
        edges[exons_aft, -1] = 1
        edges[-1, :] = edges[:, -1].T

        terminals = sp.c_[terminals, sp.zeros((2,))]

    def add_intron_retention(self, idx1, idx2):

        adj_mat = sp.triu(edges)

        vertices = sp.c_[vertices, sp.array([vertices[0, idx1], vertices[1, idx2]])]

        _new_edge()

        adj_mat = sp.r_[adj_mat, sp.zeros((adj_mat.shape[1],))]
        adj_mat = sp.c_[adj_mat, sp.zeros((adj_mat.shape[2],))]

        ### check if adjacency matrix is symmetric
        ### otherwise or is not justyfied
        assert(sp.all(sp.all(adj_mat - (splicegraph['graph'] - adj_mat).T == 0)))

        ### AK: under the assumption that our splice graph representation is symmetric
        ### I preserve symmetry by using OR over the adj_mat column and row

        splicegraph['graph'] = adj_mat[:, idx1] | adj_mat[idx2, :].T
        splicegraph['graph'] = adj_mat[:, idx1].T | adj_mat[idx2, :]

        if 'term' in splicegraph:
            splicegraph['term'] = sp.c_[splicegraph['term'], sp.array([splicegraph['term'][1, idx1], splicegraph['term'][2, idx2]])]

<commit_msg>added uniquify functionality<commit_after>import scipy as sp

class Splicegraph:

    def __init__(self, genes = None):

        vertices = sp.zeros((2, 0))
        edges = sp.zeros((0, 0))
        terminals = sp.zeros((2, 0))

        if genes:
            from_genes(genes)

    def new_edge(self):

        edges = sp.c_[edges, sp.zeros((edges.shape[0],))]
        edges = sp.r_[edges, sp.zeros((edges.shape[1],))]

    def from_genes(self, genes):

        if gene_idx % 100 == 0:
            print '.',
            if gene_idx % 1000 == 0:
                 print '%i' % gene_idx

        for transcript_idx = len(genes[gene_idx].transcripts):
            exon_start_end = genes[gene_idx].exons[transcript_idx]

            ### only one exon in the transcript
            if exon_start_end.shape[0] == 1,
                exon1_start = exon_start_end[0, 0]
                exon1_end = exon_start_end[0, 1]

                if vertices.shape[1] == 0:
                  vertices[0, 0] = exon1_start
                  vertices[1, 0] = exon1_end
                  edges = 0
                  num_exons = 0
                else:
                  vertices[0, num_exons + 1) = exon1_start
                  vertices[1, num_exons + 1) = exon1_end
                  edges[0, num_exons + 1] = 0
                  edges[num_exons + 1, 0] = 0
                  num_exons += 1
            ### more than one exon in the transcript
            else:
                for exon_idx in  xrange(exon_start_end.shape[0] - 1):
                    exon1_start = exon_start_end[exon_idx , 0]
                    exon1_end = exon_start_end[exon_idx, 1]
                    exon2_start = exon_start_end[exon_idx + 1, 0]
                    exon2_end = exon_start_end[exon_idx + 1, 1]

                    if vertices.shape[1] == 0:
                        vertices[0, 0] = exon1_start
                        vertices[1, 0] = exon1_end
                        vertices[0, 1] = exon2_start
                        vertices[1, 1] = exon2_end
                        edges = sp.zeros((2, 2))
                        edges[0, 1] = 1
                        edges[1, 0] = 1
                        num_exons = 2
                    else:
                        exon1_idx = 0
                        exon2_idx = 0
                        ### check if current exon already occurred
                        for idx in range(num_exons):
                            if ((vertices[0, idx] == exon1_start) && (vertices[1, idx] == exon1_end)):
                                 exon1_idx = idx
                            if ((vertices[0, idx] == exon2_start) && (vertices[1, idx] == exon2_end)):
                                 exon2_idx = idx

                        ### both exons already occured -> only add an edge
                        if (exon1_idx !=0) && (exon2_idx != 0):
                            edges[exon1_idx, exon2_idx] = 1
                            edges[exon2_idx, exon1_idx] = 1
                        else:
                            ### 2nd exon occured
                            if ((exon1_idx == 0) && (exon2_idx !=0 )):
                                vertices[0, num_exons + 1] = exon1_start
                                vertices[1, num_exons + 1] = exon1_end
                                edges[exon2_idx, num_exons + 1] = 1
                                edges[num_exons + 1, exon2_idx] = 1
                                num_exons += 1
                            ### 1st exon occured
                            elif ((exon2_idx == 0) && (exon1_idx !=0)):
                                vertices[0, num_exons + 1] = exon2_start
                                vertices[1, num_exons + 1] = exon2_end
                                edges[exon1_idx, num_exons + 1] = 1
                                edges[num_exons + 1, exon1_idx] = 1
                                num_exons += 1
                            ### no exon occured
                            else:
                                assert((exon1_idx == 0) && (exon2_idx == 0))
                                vertices[0, num_exons + 1] = exon1_start
                                vertices[1, num_exons + 1] = exon1_end
                                num_exons += 1
                                vertices[0, num_exons + 1] = exon2_start
                                vertices[1, num_exons + 1] = exon2_end
                                num_exons += 1

                                edges[num_exons - 1, num_exons] = 1
                                edges[num_exons, num_exons - 1] = 1

                terminals[0, sp.where(vertices[0, :] == exon_start_end.max())[0]] = 1
                terminals[1, sp.where(vertices[1, :] == exon_start_end.max())[0]] = 1

          ### take care of the sorting by exon start
          s_idx = sp.argsort(vertices[0, :])
          vertices = vertices[:, s_idx]
          edges = edges[s_idx, :][:, s_idx]
          if vertices.shape != terminals.shape:
            terminals = sp.c_[terminals, sp.zeros((2,))]
          terminals = terminals[:, s_idx]

    def add_intron(self, idx1, flag1, idx2, flag2):
        """adds new introns into splicegraph between idx1 and idx2"""

        ### if flag1, all end terminal exons in idx1 are preserved
        ### if flag2, all start terminal exons in idx2 are preserved

        if idx2:
            adj_mat = sp.triu(edges)

            if flag1:
                for i1 in idx1:

                    ### if exon is end-terminal
                    if sp.all(adj_mat[i1, :] == 0):

                        vertices = sp.c_[vertices, vertices[:, i1]]

                        _new_edge()
                        edges[:, -1] = edges[:, i1]
                        edges[-1, :] = edges[i1, :]

                        terminals = sp.c_[terminals, terminals[:, i1]]
            if flag2:,
                for i2 in idx2:
                    ### if exon is start-terminal
                    if sp.all(adj_mat[:, i2] == 0):
                        vertices = sp.c_[vertices, vertices[:, i2]]

                        _new_edge()
                        edges[:, -1] = edges[:, i2]
                        edges[-1, :] = edges[i2, :]

                        terminals = sp.c_[terminals, terminals[:, i2]]

        for i1 in idx1:
            for i2 in idx2:
                edges[i1, i2] = 1
                edges[i2, i1] = 1

    def add_cassette_exon(self, new_exon, exons_pre, exons_aft)
        ### exon_pre contains the indices of preceding exons
        ### exon_aft contains the indices of successing exons

        vertices = sp.r_[vertices, new_exon.T]

        _new_edge()

        edges[exons_pre, -1] = 1
        edges[exons_aft, -1] = 1
        edges[-1, :] = edges[:, -1].T

        terminals = sp.c_[terminals, sp.zeros((2,))]

    def add_intron_retention(self, idx1, idx2):

        adj_mat = sp.triu(edges)

        vertices = sp.c_[vertices, sp.array([vertices[0, idx1], vertices[1, idx2]])]

        _new_edge()

        adj_mat = sp.r_[adj_mat, sp.zeros((adj_mat.shape[1],))]
        adj_mat = sp.c_[adj_mat, sp.zeros((adj_mat.shape[2],))]

        ### check if adjacency matrix is symmetric
        ### otherwise or is not justyfied
        assert(sp.all(sp.all(adj_mat - (splicegraph['graph'] - adj_mat).T == 0)))

        ### AK: under the assumption that our splice graph representation is symmetric
        ### I preserve symmetry by using OR over the adj_mat column and row

        splicegraph['graph'] = adj_mat[:, idx1] | adj_mat[idx2, :].T
        splicegraph['graph'] = adj_mat[:, idx1].T | adj_mat[idx2, :]

        if 'term' in splicegraph:
            splicegraph['term'] = sp.c_[splicegraph['term'], sp.array([splicegraph['term'][1, idx1], splicegraph['term'][2, idx2]])]

    def uniquify(self):
        # OUTPUT: splice graph that has been made unique on exons for each gene

        (s_tmp, s_idx) = sort_rows(vertices.T, index=True)
        vertices = s_tmp.T
        edges = vertices[s_idx, :][:, s_idx]
        terminals = erminals[:, s_idx]

        rm_idx = []
        for j in range(1, vertices.shape[1]):
            if sp.all(vertices[:, j-1] == vertices[:, j]):
                edges[:, j] = edges[:, j-1] | edges[:, j]
                edges[j, :] = edges[j-1, :] | edges[j, :]
                rm_idx.append(j - 1)

        keep_idx = sp.where(~sp.in1d(sp.array(range(vertices.shape[1])), rm_idx))[0]
        vertices = vertices[:, keep_idx]
        edges = edges[keep_idx, :][:, keep_idx]
        terminals = terminals[:, keep_idx]

<|endoftext|>


<commit_before>'''
synbiochem (c) University of Manchester 2015

synbiochem is licensed under the MIT License.

To view a copy of this license, visit <http://opensource.org/licenses/MIT/>.

@author:  neilswainston
'''
# pylint: disable=no-member
# pylint: disable=too-many-arguments
from itertools import product
import copy
import math
import re
import uuid

from Bio.Restriction import RestrictionBatch
from Bio.Seq import Seq

SO_PROM = 'http://purl.obolibrary.org/obo/SO_0000167'
SO_RBS = 'http://purl.obolibrary.org/obo/SO_0000139'
SO_CDS = 'http://purl.obolibrary.org/obo/SO_0000316'
SO_PART = 'http://purl.obolibrary.org/obo/SO_0000804'
SO_ASS_COMP = 'http://purl.obolibrary.org/obo/SO_0000143'
SO_PLASMID = 'http://purl.obolibrary.org/obo/SO_0000637'

_RDF_NS = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
_NS = {'ns': 'http://sbols.org/v1#',
       'rdf': _RDF_NS}

class DNA(dict):
    '''Class to represent a DNA object.'''

    def __init__(self, disp_id=None, name=None, desc=None, typ=None, seq=None,
                 start=1, end=float('NaN'), forward=True,
                 features=None, children=None, options=None,
                 links=None, parameters=None, temp_params=None):

        if seq is None:
            seq = ''

        dict.__init__(self)

        self.update({'disp_id': disp_id
                     if disp_id is not None else str(uuid.uuid4()),
                     'seq': seq.upper(),
                     'name': name,
                     'desc': desc,
                     'typ': typ,
                     'start': start,
                     'end': end if not math.isnan(end)
                     else start + len(seq) - 1,
                     'forward': forward,
                     'features': [] if features is None else features,
                     'children': [] if children is None else children,
                     'options': [] if options is None else options,
                     'links': [] if links is None else links,
                     'parameters': {} if parameters is None else parameters,
                     'temp_params': {} if temp_params is None else temp_params,
                     })

    def set_seq(self, seq):
        '''Sets sequence.'''
        self['seq'] = seq.upper()
        self['end'] = self['start'] + len(seq) - 1

    def copy(self):
        '''Copies the DNA object (making a deep copy).'''
        copy_dict = copy.deepcopy(self)
        copy_dna = DNA(**copy_dict)
        return copy_dna

    def __eq__(self, other):
        return self.__dict__ == other.__dict__

    def __repr__(self):
        return self['name']

def get_dna(dct):
    '''Factory method for constructing DNA object from dict.'''
    dna = DNA(**dct)
    dna['features'] = [get_dna(feat) for feat in dna['features']]
    dna['children'] = [get_dna(child) for child in dna['children']]
    dna['options'] = [get_dna(opt) for opt in dna['options']]
    return dna

def concat(dnas):
    '''Concatenates a list of DNA objects into a single DNA object.'''
    concat_dna = dnas[0].copy()
    concat_dna['disp_id'] = str(uuid.uuid4())

    for dna in dnas[1:]:
        concat_dna = add(concat_dna, dna)

    return concat_dna

def apply_restricts(dna, restricts, circular=False):
    '''Applies restriction site cleavage to forward and reverse strands.'''
    out_dnas = [dna]

    for restrict in restricts:
        batch = RestrictionBatch()
        batch.add(str(restrict))
        restrict = batch.get(str(restrict))
        out_dnas = _apply_restrict_to_dnas(out_dnas, restrict, circular)

    return out_dnas

def add(dna1, dna2):
    '''Adds two DNA objects together.'''
    # Add names, etc.
    dna1.disp_id = str(uuid.uuid4())
    dna1['name'] = _concat([dna1['name'], dna2['name']])
    dna1['desc'] = _concat([dna1['desc'], dna2['desc']])

    # Add sequences:
    orig_seq_len = len(dna1['seq'])
    dna1['seq'] += dna2['seq']
    dna1['end'] = len(dna1['seq'])

    # Update parameters:
    for key, value in dna2['parameters'].iteritems():
        param = dna1['parameters'].get(key, None)

        if param is None:
            dna1['parameters'][key] = value
        elif isinstance(param, list):
            param.append(value)
            dna1['parameters'][key] = param
        else:
            dna1['parameters'][key] = [param, value]

    # Update features:
    for feature in dna2.get('features', []):
        feature = feature.copy()
        feature['start'] += orig_seq_len
        feature['end'] += orig_seq_len
        dna1['features'].append(feature)

    return dna1

def expand(dna):
    '''Expand a DNA object containing options into distinct DNA objects.'''
    features = dna.pop('features')
    dna['features'] = []

    dnas = [dna]

    for feature in features:
        if len(feature['options']):
            additions = feature['options']
        elif len(feature['seq']):
            additions = [feature]
        else:
            continue

        for addition in additions:
            addition['features'].append(addition.copy())

        dnas = [add(dna.copy(), addition)
                for dna, addition in product(dnas, additions)
                if len(addition['seq'])]

    return dnas

def _concat(strs):
    '''Concatenates non-None strings.'''
    return ' - '.join([string for string in strs
                       if string is not None and len(string)])

def _apply_restrict_to_dnas(dnas, restrict, circular):
    '''Applies restriction site cleavage to forward and reverse strands.'''
    out_dnas = []

    for dna in dnas:
        restrict.catalyse(Seq(dna['seq']), linear=not circular)
        start = 0
        seqs = []

        for result in restrict.results:
            end = result - 1
            seqs.append((dna['seq'][start:end], start, end))
            start = end

        seqs.append((dna['seq'][start:], start, len(dna['seq'])))

        if circular:
            seqs = [(seqs[-1][0] + seqs[0][0], seqs[-1][1], seqs[0][2])] + \
                seqs[1:-1]

        for seq in seqs:
            out_dnas.append(_get_concat_dna(dna, seq[0], seq[1], seq[2]))

    return out_dnas

def _apply_restrict_to_seq(seq, restrict):
    '''Applies restriction site cleavage to a sequence.'''
    sub_seqs = [(match.group(0), match.start())
                for match in re.finditer(restrict, seq)]
    end = sub_seqs[0][1] if len(sub_seqs) > 0 else len(seq)
    return [(seq[:end], 0)] + sub_seqs

def _get_concat_dna(parent_dna, seq, start, end):
    '''Returns a DNA object from the supplied subsequence from a parent DNA
    object.'''
    if parent_dna['seq'] == seq:
        disp_id = parent_dna['disp_id']
        frag_str = ''
    else:
        disp_id = str(uuid.uuid4())
        frag_str = ' [' + str(start) + ':' + str(end) + ']'

    dna = DNA(disp_id=disp_id,
              name=parent_dna['name'] + frag_str,
              desc=parent_dna['desc'] + frag_str,
              seq=seq)

    for feature in parent_dna['features']:
        if feature['start'] >= start and feature['end'] <= end:
            copy_feature = feature.copy()
            copy_feature['start'] -= start
            copy_feature['end'] -= start
            dna['features'].append(copy_feature)

    return dna
<commit_msg>Added additional SO terms.<commit_after>'''
synbiochem (c) University of Manchester 2015

synbiochem is licensed under the MIT License.

To view a copy of this license, visit <http://opensource.org/licenses/MIT/>.

@author:  neilswainston
'''
# pylint: disable=no-member
# pylint: disable=too-many-arguments
from itertools import product
import copy
import math
import re
import uuid

from Bio.Restriction import RestrictionBatch
from Bio.Seq import Seq

SO_PROM = 'http://purl.obolibrary.org/obo/SO_0000167'
SO_RBS = 'http://purl.obolibrary.org/obo/SO_0000139'
SO_CDS = 'http://purl.obolibrary.org/obo/SO_0000316'
SO_PART = 'http://purl.obolibrary.org/obo/SO_0000804'
SO_ASS_COMP = 'http://purl.obolibrary.org/obo/SO_0000143'
SO_PLASMID = 'http://purl.obolibrary.org/obo/SO_0000637'
SO_DESIGNED = 'http://purl.obolibrary.org/obo/SO_0000546'
SO_RANDOM = 'http://purl.obolibrary.org/obo/SO_0000449'

_RDF_NS = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
_NS = {'ns': 'http://sbols.org/v1#',
       'rdf': _RDF_NS}

class DNA(dict):
    '''Class to represent a DNA object.'''

    def __init__(self, disp_id=None, name=None, desc=None, typ=None, seq=None,
                 start=1, end=float('NaN'), forward=True,
                 features=None, children=None, options=None,
                 links=None, parameters=None, temp_params=None):

        if seq is None:
            seq = ''

        dict.__init__(self)

        self.update({'disp_id': disp_id
                     if disp_id is not None else str(uuid.uuid4()),
                     'seq': seq.upper(),
                     'name': name,
                     'desc': desc,
                     'typ': typ,
                     'start': start,
                     'end': end if not math.isnan(end)
                     else start + len(seq) - 1,
                     'forward': forward,
                     'features': [] if features is None else features,
                     'children': [] if children is None else children,
                     'options': [] if options is None else options,
                     'links': [] if links is None else links,
                     'parameters': {} if parameters is None else parameters,
                     'temp_params': {} if temp_params is None else temp_params,
                     })

    def set_seq(self, seq):
        '''Sets sequence.'''
        self['seq'] = seq.upper()
        self['end'] = self['start'] + len(seq) - 1

    def copy(self):
        '''Copies the DNA object (making a deep copy).'''
        copy_dict = copy.deepcopy(self)
        copy_dna = DNA(**copy_dict)
        return copy_dna

    def __eq__(self, other):
        return self.__dict__ == other.__dict__

    def __repr__(self):
        return self['name']

def get_dna(dct):
    '''Factory method for constructing DNA object from dict.'''
    dna = DNA(**dct)
    dna['features'] = [get_dna(feat) for feat in dna['features']]
    dna['children'] = [get_dna(child) for child in dna['children']]
    dna['options'] = [get_dna(opt) for opt in dna['options']]
    return dna

def concat(dnas):
    '''Concatenates a list of DNA objects into a single DNA object.'''
    concat_dna = dnas[0].copy()
    concat_dna['disp_id'] = str(uuid.uuid4())

    for dna in dnas[1:]:
        concat_dna = add(concat_dna, dna)

    return concat_dna

def apply_restricts(dna, restricts, circular=False):
    '''Applies restriction site cleavage to forward and reverse strands.'''
    out_dnas = [dna]

    for restrict in restricts:
        batch = RestrictionBatch()
        batch.add(str(restrict))
        restrict = batch.get(str(restrict))
        out_dnas = _apply_restrict_to_dnas(out_dnas, restrict, circular)

    return out_dnas

def add(dna1, dna2):
    '''Adds two DNA objects together.'''
    # Add names, etc.
    dna1.disp_id = str(uuid.uuid4())
    dna1['name'] = _concat([dna1['name'], dna2['name']])
    dna1['desc'] = _concat([dna1['desc'], dna2['desc']])

    # Add sequences:
    orig_seq_len = len(dna1['seq'])
    dna1['seq'] += dna2['seq']
    dna1['end'] = len(dna1['seq'])

    # Update parameters:
    for key, value in dna2['parameters'].iteritems():
        param = dna1['parameters'].get(key, None)

        if param is None:
            dna1['parameters'][key] = value
        elif isinstance(param, list):
            param.append(value)
            dna1['parameters'][key] = param
        else:
            dna1['parameters'][key] = [param, value]

    # Update features:
    for feature in dna2.get('features', []):
        feature = feature.copy()
        feature['start'] += orig_seq_len
        feature['end'] += orig_seq_len
        dna1['features'].append(feature)

    return dna1

def expand(dna):
    '''Expand a DNA object containing options into distinct DNA objects.'''
    features = dna.pop('features')
    dna['features'] = []

    dnas = [dna]

    for feature in features:
        if len(feature['options']):
            additions = feature['options']
        elif len(feature['seq']):
            additions = [feature]
        else:
            continue

        for addition in additions:
            addition['features'].append(addition.copy())

        dnas = [add(dna.copy(), addition)
                for dna, addition in product(dnas, additions)
                if len(addition['seq'])]

    return dnas

def _concat(strs):
    '''Concatenates non-None strings.'''
    return ' - '.join([string for string in strs
                       if string is not None and len(string)])

def _apply_restrict_to_dnas(dnas, restrict, circular):
    '''Applies restriction site cleavage to forward and reverse strands.'''
    out_dnas = []

    for dna in dnas:
        restrict.catalyse(Seq(dna['seq']), linear=not circular)
        start = 0
        seqs = []

        for result in restrict.results:
            end = result - 1
            seqs.append((dna['seq'][start:end], start, end))
            start = end

        seqs.append((dna['seq'][start:], start, len(dna['seq'])))

        if circular:
            seqs = [(seqs[-1][0] + seqs[0][0], seqs[-1][1], seqs[0][2])] + \
                seqs[1:-1]

        for seq in seqs:
            out_dnas.append(_get_concat_dna(dna, seq[0], seq[1], seq[2]))

    return out_dnas

def _apply_restrict_to_seq(seq, restrict):
    '''Applies restriction site cleavage to a sequence.'''
    sub_seqs = [(match.group(0), match.start())
                for match in re.finditer(restrict, seq)]
    end = sub_seqs[0][1] if len(sub_seqs) > 0 else len(seq)
    return [(seq[:end], 0)] + sub_seqs

def _get_concat_dna(parent_dna, seq, start, end):
    '''Returns a DNA object from the supplied subsequence from a parent DNA
    object.'''
    if parent_dna['seq'] == seq:
        disp_id = parent_dna['disp_id']
        frag_str = ''
    else:
        disp_id = str(uuid.uuid4())
        frag_str = ' [' + str(start) + ':' + str(end) + ']'

    dna = DNA(disp_id=disp_id,
              name=parent_dna['name'] + frag_str,
              desc=parent_dna['desc'] + frag_str,
              seq=seq)

    for feature in parent_dna['features']:
        if feature['start'] >= start and feature['end'] <= end:
            copy_feature = feature.copy()
            copy_feature['start'] -= start
            copy_feature['end'] -= start
            dna['features'].append(copy_feature)

    return dna
<|endoftext|>