<commit_before>""" Going to try algorithm 1 from Neal (2000)
"""

import bisect
import itertools

import numpy as np

def pick_discrete(p):
    """Pick a discrete integer between 0 and len(p) - 1 with probability given by p array."""
    c = np.cumsum(p)
    u = np.random.uniform()
    return bisect.bisect_left(c, u)

class DPMM(object):
    """Dirichlet Process Mixture Model.  Using algorithm 1 from Neal (2000).

    @param prior    The prior object for whatever model is being inferred.
    @param alpha    Concentration parameter.
    @param D        Data.
    @param theta    Optional initial state for sampler.  Will be drawn from prior if not specified.
    """
    def __init__(self, prior, alpha, D, theta=None):
        self.prior = prior
        self.alpha = alpha
        self.D = D  # data
        self.n = len(self.D)

        if theta is None:
            # Draw from the prior
            theta = [prior.sample() for i in range(self.n)]
        self.theta = theta

        # Initialize r_i array
        self.r_i = self.alpha * np.array([prior.pred(x) for x in D])

    def q(self, i):
        # compute and return row of q_ij matrix (we only ever need one row at a time).
        qs = np.array([self.prior.like1(*th_j, x=self.D[i]) for th_j in self.theta])
        qs[i] = self.r_i[i]  # cheat by placing r_i at q_ii.
        return qs

    def update_1_theta(self, i):
        x = self.D[i]
        qs = self.q(i)
        p = qs/np.sum(qs)
        picked = pick_discrete(p)
        if picked == i:  # This corresponds to picking r_i in Neal (2000); i.e. get a new theta
            # Neal (2000) H_i is the posterior given a single observation x.
            self.theta[i] = self.prior.post(x).sample()
        else:  # reuse an existing theta
            self.theta[i] = self.theta[picked]

    def update(self, n=1):
        for j in xrange(n):
            for i in xrange(len(self.D)):
                self.update_1_theta(i)

class DPMM2(object):
    """Dirichlet Process Mixture Model.  Using algorithm 2 from Neal (2000).

    @param prior    The prior object for whatever model is being inferred.
    @param alpha    Concentration parameter.
    @param D        Data.
    @param phi      Optional initial state for each cluster.
    @param label    Optional initial cluster labels for each data point.
    """
    def __init__(self, prior, alpha, D, phi=None, label=None):
        self.prior = prior
        self.alpha = alpha
        self.D = D  # data
        self.n = len(self.D)

        if phi is None:
            # It's easier to create new clusters than to destroy existing clusters, so start off
            # with all data points in a single cluster.
            phi = [self.prior.post(D).sample()]
            nphi = [self.n]
            label = np.zeros((self.n), dtype=int)
        if nphi is None:
            nphi = [np.sum(label == i) for i in xrange(label.max())]

        self.phi = phi
        self.nphi = nphi
        self.label = label

        # Initialize r_i array again
        self.r_i = self.alpha * np.array([prior.pred(x) for x in D])

    def draw_new_label(self, i):
        p = [self.prior.like1(*phi, x=self.D[i])*nphi
             for phi, nphi in itertools.izip(self.phi, self.nphi)]
        p.append(self.r_i[i])
        p = np.array(p)
        p /= np.sum(p)
        picked = pick_discrete(p)
        return picked

    def update_c(self):
        for i in xrange(self.n):
            label = self.label[i]
            self.nphi[label] -= 1
            if self.nphi[label] == 0:
                del self.phi[label]
                del self.nphi[label]
                # Need to decrement labels for label beyond the one deleted...
                self.label[np.nonzero(self.label >= label)] -= 1
            new_label = self.draw_new_label(i)
            self.label[i] = new_label
            if new_label == len(self.phi):
                self.phi.append(self.prior.post(self.D[i]).sample())
                self.nphi.append(1)
            else:
                self.nphi[new_label] += 1

    def update_phi(self):
        for i in xrange(len(self.phi)):
            data = self.D[np.nonzero(self.label == i)]
            self.phi[i] = self.prior.post(data).sample()

    def update(self, n=1):
        for j in xrange(n):
            self.update_c()
            self.update_phi()
<commit_msg>initialize DPMM r_i variable more elegantly<commit_after>""" Going to try algorithm 1 from Neal (2000)
"""

import bisect
import itertools

import numpy as np

def pick_discrete(p):
    """Pick a discrete integer between 0 and len(p) - 1 with probability given by p array."""
    c = np.cumsum(p)
    u = np.random.uniform()
    return bisect.bisect_left(c, u)

class DPMM(object):
    """Dirichlet Process Mixture Model.  Using algorithm 1 from Neal (2000).

    @param prior    The prior object for whatever model is being inferred.
    @param alpha    Concentration parameter.
    @param D        Data.
    @param theta    Optional initial state for sampler.  Will be drawn from prior if not specified.
    """
    def __init__(self, prior, alpha, D, theta=None):
        self.prior = prior
        self.alpha = alpha
        self.D = D  # data
        self.n = len(self.D)

        if theta is None:
            # Draw from the prior
            theta = [prior.sample() for i in range(self.n)]
        self.theta = theta

        # Initialize r_i array
        self.r_i = self.alpha * prior.pred(D)

    def q(self, i):
        # compute and return row of q_ij matrix (we only ever need one row at a time).
        qs = np.array([self.prior.like1(*th_j, x=self.D[i]) for th_j in self.theta])
        qs[i] = self.r_i[i]  # cheat by placing r_i at q_ii.
        return qs

    def update_1_theta(self, i):
        x = self.D[i]
        qs = self.q(i)
        p = qs/np.sum(qs)
        picked = pick_discrete(p)
        if picked == i:  # This corresponds to picking r_i in Neal (2000); i.e. get a new theta
            # Neal (2000) H_i is the posterior given a single observation x.
            self.theta[i] = self.prior.post(x).sample()
        else:  # reuse an existing theta
            self.theta[i] = self.theta[picked]

    def update(self, n=1):
        for j in xrange(n):
            for i in xrange(len(self.D)):
                self.update_1_theta(i)

class DPMM2(object):
    """Dirichlet Process Mixture Model.  Using algorithm 2 from Neal (2000).

    @param prior    The prior object for whatever model is being inferred.
    @param alpha    Concentration parameter.
    @param D        Data.
    @param phi      Optional initial state for each cluster.
    @param label    Optional initial cluster labels for each data point.
    """
    def __init__(self, prior, alpha, D, phi=None, label=None):
        self.prior = prior
        self.alpha = alpha
        self.D = D  # data
        self.n = len(self.D)

        if phi is None:
            # It's easier to create new clusters than to destroy existing clusters, so start off
            # with all data points in a single cluster.
            phi = [self.prior.post(D).sample()]
            nphi = [self.n]
            label = np.zeros((self.n), dtype=int)
        if nphi is None:
            nphi = [np.sum(label == i) for i in xrange(label.max())]

        self.phi = phi
        self.nphi = nphi
        self.label = label

        # Initialize r_i array again
        self.r_i = self.alpha * prior.pred(D)

    def draw_new_label(self, i):
        p = [self.prior.like1(*phi, x=self.D[i])*nphi
             for phi, nphi in itertools.izip(self.phi, self.nphi)]
        p.append(self.r_i[i])
        p = np.array(p)
        p /= np.sum(p)
        picked = pick_discrete(p)
        return picked

    def update_c(self):
        for i in xrange(self.n):
            label = self.label[i]
            self.nphi[label] -= 1
            if self.nphi[label] == 0:
                del self.phi[label]
                del self.nphi[label]
                # Need to decrement labels for label beyond the one deleted...
                self.label[np.nonzero(self.label >= label)] -= 1
            new_label = self.draw_new_label(i)
            self.label[i] = new_label
            if new_label == len(self.phi):
                self.phi.append(self.prior.post(self.D[i]).sample())
                self.nphi.append(1)
            else:
                self.nphi[new_label] += 1

    def update_phi(self):
        for i in xrange(len(self.phi)):
            data = self.D[np.nonzero(self.label == i)]
            self.phi[i] = self.prior.post(data).sample()

    def update(self, n=1):
        for j in xrange(n):
            self.update_c()
            self.update_phi()
<|endoftext|>


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

from docutils.core import publish_file
import fileinput
import glob
import os
import shutil
import subprocess
import sys

stylesheets = {
    "stylesheet_path": ["basic.css", "nature.css"]
}

def get_git_ver_string():
    null = open(os.devnull, 'w')
    cwd = os.path.dirname(os.path.abspath(__file__))
    try:
        git_branch = subprocess.check_output(
            ['git', 'rev-parse', '--abbrev-ref', 'HEAD'],
            stderr=null,
            cwd=cwd,
        ).strip()
    except subprocess.CalledProcessError:
        git_branch = ""
    try:
        git_tag = subprocess.check_output(
            ['git', 'describe', '--exact-match'],
            stderr=null,
            cwd=cwd,
        ).strip()
        git_tag = "tag=" + git_tag
    except subprocess.CalledProcessError:
        git_tag = ""
    try:
        git_commit = subprocess.check_output(
            ['git', 'rev-parse', '--short', 'HEAD'],
            stderr=null,
            cwd=cwd,
        ).strip()
    except subprocess.CalledProcessError:
        git_commit = ""
    try:
        dirty_string = "-this_is_a_dirty_checkout"
        is_dirty = subprocess.check_output(
            ['git', 'describe', '--dirty=' + dirty_string, "--all"],
            stderr=null,
            cwd=cwd,
        ).strip().endswith(dirty_string)
        git_dirty = "dirty" if is_dirty else ""
    except subprocess.CalledProcessError:
        git_dirty = ""

    if git_branch or git_tag or git_commit or git_dirty:
        git_version = ",".join(
            s for s in
            (git_branch, git_tag, git_commit, git_dirty,)
            if s
        )
        return git_version.encode("ascii")
    return "Unknown rev"

def glob_spec_to(out_file_name):
    with open(out_file_name, "wb") as outfile:
        for f in sorted(glob.glob("../specification/*.rst")):
            with open(f, "rb") as infile:
                outfile.write(infile.read())

def set_git_version(filename):
    git_ver = get_git_ver_string()
    # inplace search and replace, stdout is redirected to the output
    # file, hence the "print" lines here.
    for line in fileinput.input(filename, inplace=True):
        if "$GIT_VERSION" in line:
            line = line.replace("$GIT_VERSION", git_ver)
        print line.rstrip("\n")

def rst2html(i, o):
    with open(i, "r") as in_file:
        with open(o, "w") as out_file:
            publish_file(
                source=in_file,
                destination=out_file,
                reader_name="standalone",
                parser_name="restructuredtext",
                writer_name="html",
                settings_overrides=stylesheets
            )

def prepare_env():
    try:
        os.makedirs("./gen")
    except OSError:
        pass
    try:
        os.makedirs("./tmp")
    except OSError:
        pass

def cleanup_env():
    pass
    #shutil.rmtree("./tmp")

def main():
    prepare_env()
    glob_spec_to("tmp/full_spec.rst")
    shutil.copy("../supporting-docs/howtos/client-server.rst", "tmp/howto.rst")
    set_git_version("tmp/full_spec.rst")
    set_git_version("tmp/howto.rst")
    rst2html("tmp/full_spec.rst", "gen/specification.html")
    rst2html("tmp/howto.rst", "gen/howtos.html")
    cleanup_env()

if __name__ == '__main__':
    main()
<commit_msg>lots of fixes based on kegan's review of https://github.com/matrix-org/matrix-doc/pull/13<commit_after>#! /usr/bin/env python

from docutils.core import publish_file
import fileinput
import glob
import os
import shutil
import subprocess
import sys

stylesheets = {
    "stylesheet_path": ["basic.css", "nature.css"]
}

def get_git_ver_string():
    null = open(os.devnull, 'w')
    cwd = os.path.dirname(os.path.abspath(__file__))
    try:
        git_branch = subprocess.check_output(
            ['git', 'rev-parse', '--abbrev-ref', 'HEAD'],
            stderr=null,
            cwd=cwd,
        ).strip()
    except subprocess.CalledProcessError:
        git_branch = ""
    try:
        git_tag = subprocess.check_output(
            ['git', 'describe', '--exact-match'],
            stderr=null,
            cwd=cwd,
        ).strip()
        git_tag = "tag=" + git_tag
    except subprocess.CalledProcessError:
        git_tag = ""
    try:
        git_commit = subprocess.check_output(
            ['git', 'rev-parse', '--short', 'HEAD'],
            stderr=null,
            cwd=cwd,
        ).strip()
    except subprocess.CalledProcessError:
        git_commit = ""
    try:
        dirty_string = "-this_is_a_dirty_checkout"
        is_dirty = subprocess.check_output(
            ['git', 'describe', '--dirty=' + dirty_string, "--all"],
            stderr=null,
            cwd=cwd,
        ).strip().endswith(dirty_string)
        git_dirty = "dirty" if is_dirty else ""
    except subprocess.CalledProcessError:
        git_dirty = ""

    if git_branch or git_tag or git_commit or git_dirty:
        git_version = ",".join(
            s for s in
            (git_branch, git_tag, git_commit, git_dirty,)
            if s
        )
        return git_version.encode("ascii")
    return "Unknown rev"

def glob_spec_to(out_file_name):
    with open(out_file_name, "wb") as outfile:
        for f in sorted(glob.glob("../specification/*.rst")):
            with open(f, "rb") as infile:
                outfile.write(infile.read())

def set_git_version(filename):
    git_ver = get_git_ver_string()
    # inplace search and replace, stdout is redirected to the output
    # file, hence the "print" lines here.
    for line in fileinput.input(filename, inplace=True):
        if "$GIT_VERSION" in line:
            line = line.replace("$GIT_VERSION", git_ver)
        print line.rstrip("\n")

def rst2html(i, o):
    with open(i, "r") as in_file:
        with open(o, "w") as out_file:
            publish_file(
                source=in_file,
                destination=out_file,
                reader_name="standalone",
                parser_name="restructuredtext",
                writer_name="html",
                settings_overrides=stylesheets
            )

def prepare_env():
    try:
        os.makedirs("./gen")
    except OSError:
        pass
    try:
        os.makedirs("./tmp")
    except OSError:
        pass

def cleanup_env():
    #pass
    shutil.rmtree("./tmp")

def main():
    prepare_env()
    glob_spec_to("tmp/full_spec.rst")
    shutil.copy("../supporting-docs/howtos/client-server.rst", "tmp/howto.rst")
    set_git_version("tmp/full_spec.rst")
    set_git_version("tmp/howto.rst")
    rst2html("tmp/full_spec.rst", "gen/specification.html")
    rst2html("tmp/howto.rst", "gen/howtos.html")
    cleanup_env()

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


<commit_before>from __future__ import division, print_function

__author__ = "adrn <adrn@astro.princeton.edu>"

# TODO: remove this shite
import os
import sys
sys.path.append(os.path.abspath(os.path.join(os.getcwd(), '..')))

# Third-party
from astropy.table import Table
import yaml

# Project
from twoface.util import Timer
from twoface.log import log
from twoface.db import Session, db_connect, AllStar, AllVisit, Status
from twoface.db.core import Base
from twoface.db.helper import copy_from_table

def main(allVisit_file, allStar_file, credentials_file, **kwargs):
    norm = lambda x: os.path.abspath(os.path.expanduser(x))
    allvisit_tbl = Table.read(norm(allVisit_file), format='fits', hdu=1)
    allstar_tbl = Table.read(norm(allStar_file), format='fits', hdu=1)

    # connect to database
    with open(credentials_file, 'r') as f:
        credentials = dict(yaml.load(f))
    credentials.setdefault('dbname', 'apogee')
    engine = db_connect(**credentials)
    log.debug("Connected to database '{}'".format(credentials['dbname']))

    # this is the magic that creates the tables based on the definitions in twoface/db/model.py
    Base.metadata.drop_all()
    Base.metadata.create_all()

    # Load data using COPY FROM because we are going to add a lot of rows...
    raw_conn = engine.raw_connection()
    _cursor = raw_conn.cursor()

    log.debug("Copying allStar file into database...")
    with Timer() as t:
        copy_from_table(_cursor, allstar_tbl, AllStar)
    log.debug("...done after {:.2f} seconds".format(t.time))

    log.debug("Copying allVisit file into database...")
    with Timer() as t:
        copy_from_table(_cursor, allvisit_tbl, AllVisit)
    log.debug("...done after {:.2f} seconds".format(t.time))

    _cursor.execute("commit")
    raw_conn.close()
    log.debug("allStar and allVisit committed to database tables")

    # add status table and modify star-visit mapping
    session = Session()

    # Load the status table
    log.debug("Populating Status table...")
    statuses = list()
    statuses.append(Status(id=0, message='untouched'))
    statuses.append(Status(id=1, message='pending'))
    statuses.append(Status(id=2, message='needs more prior samples'))
    statuses.append(Status(id=3, message='needs mcmc'))
    statuses.append(Status(id=4, message='error'))
    statuses.append(Status(id=5, message='completed'))

    session.add_all(statuses)
    session.flush()
    log.debug("...done")

    # Loop through and match up allstar to allvisit (many-to-many)
    batch_stride = 1000
    n_batches = len(allstar_tbl) // batch_stride

    log.debug("Matching star-visit...")
    with Timer() as t:
        for i,star in enumerate(session.query(AllStar).all()):
            visits = session.query(AllVisit).filter(AllVisit.apogee_id == star.apogee_id).all()
            star.visits = visits

            if i % batch_stride == 0 and i != 0:
                log.debug("Committing batch {}/{} to database [{:.2f} sec]".format(i//batch_stride,
                                                                                n_batches,
                                                                                t.elapsed()))
                session.commit()
                t.reset()

    log.debug("Committing final batch to database [{:.2f} sec]".format(t.elapsed()))
    session.commit()

    stars = session.query(AllStar).filter(AllStar.apogee_id == '2M00000032+5737103').all()
    print(stars[0])
    print(stars[0].visits)

    session.close()

if __name__ == "__main__":
    from argparse import ArgumentParser
    import logging

    # Define parser object
    parser = ArgumentParser(description="Initialize the TwoFace project database.")

    vq_group = parser.add_mutually_exclusive_group()
    vq_group.add_argument('-v', '--verbose', action='count', default=0, dest='verbosity')
    vq_group.add_argument('-q', '--quiet', action='count', default=0, dest='quietness')
    # parser.add_argument('-o', '--overwrite', action='store_true', dest='overwrite',
    #                     default=False, help='Destroy everything.')

    parser.add_argument("--allstar", dest="allStar_file", required=True,
                        type=str, help="Path to APOGEE allStar FITS file.")
    parser.add_argument("--allvisit", dest="allVisit_file", required=True,
                        type=str, help="Path to APOGEE allVisit FITS file.")
    parser.add_argument("--credentials", dest="credentials_file", required=True,
                        type=str, help="Path to YAML file with database credentials.")

    args = parser.parse_args()

    # Set logger level based on verbose flags
    if args.verbosity != 0:
        if args.verbosity == 1:
            log.setLevel(logging.DEBUG)
        else: # anything >= 2
            log.setLevel(1)

    elif args.quietness != 0:
        if args.quietness == 1:
            log.setLevel(logging.WARNING)
        else: # anything >= 2
            log.setLevel(logging.ERROR)

    else: # default
        log.setLevel(logging.INFO)

    main(**vars(args))
<commit_msg>remove debug line<commit_after>from __future__ import division, print_function

__author__ = "adrn <adrn@astro.princeton.edu>"

# TODO: remove this shite
import os
import sys
sys.path.append(os.path.abspath(os.path.join(os.getcwd(), '..')))

# Third-party
from astropy.table import Table
import yaml

# Project
from twoface.util import Timer
from twoface.log import log
from twoface.db import Session, db_connect, AllStar, AllVisit, Status
from twoface.db.core import Base
from twoface.db.helper import copy_from_table

def main(allVisit_file, allStar_file, credentials_file, **kwargs):
    norm = lambda x: os.path.abspath(os.path.expanduser(x))
    allvisit_tbl = Table.read(norm(allVisit_file), format='fits', hdu=1)
    allstar_tbl = Table.read(norm(allStar_file), format='fits', hdu=1)

    # connect to database
    with open(credentials_file, 'r') as f:
        credentials = dict(yaml.load(f))
    credentials.setdefault('dbname', 'apogee')
    engine = db_connect(**credentials)
    log.debug("Connected to database '{}'".format(credentials['dbname']))

    # this is the magic that creates the tables based on the definitions in twoface/db/model.py
    Base.metadata.drop_all()
    Base.metadata.create_all()

    # Load data using COPY FROM because we are going to add a lot of rows...
    raw_conn = engine.raw_connection()
    _cursor = raw_conn.cursor()

    log.debug("Copying allStar file into database...")
    with Timer() as t:
        copy_from_table(_cursor, allstar_tbl, AllStar)
    log.debug("...done after {:.2f} seconds".format(t.time))

    log.debug("Copying allVisit file into database...")
    with Timer() as t:
        copy_from_table(_cursor, allvisit_tbl, AllVisit)
    log.debug("...done after {:.2f} seconds".format(t.time))

    _cursor.execute("commit")
    raw_conn.close()
    log.debug("allStar and allVisit committed to database tables")

    # add status table and modify star-visit mapping
    session = Session()

    # Load the status table
    log.debug("Populating Status table...")
    statuses = list()
    statuses.append(Status(id=0, message='untouched'))
    statuses.append(Status(id=1, message='pending'))
    statuses.append(Status(id=2, message='needs more prior samples'))
    statuses.append(Status(id=3, message='needs mcmc'))
    statuses.append(Status(id=4, message='error'))
    statuses.append(Status(id=5, message='completed'))

    session.add_all(statuses)
    session.flush()
    log.debug("...done")

    # Loop through and match up allstar to allvisit (many-to-many)
    batch_stride = 1000
    n_batches = len(allstar_tbl) // batch_stride

    log.debug("Matching star-visit...")
    with Timer() as t:
        for i,star in enumerate(session.query(AllStar).all()):
            visits = session.query(AllVisit).filter(AllVisit.apogee_id == star.apogee_id).all()
            star.visits = visits

            if i % batch_stride == 0 and i != 0:
                log.debug("Committing batch {}/{} to database [{:.2f} sec]".format(i//batch_stride,
                                                                                n_batches,
                                                                                t.elapsed()))
                session.commit()
                t.reset()

    log.debug("Committing final batch to database [{:.2f} sec]".format(t.elapsed()))
    session.commit()

    session.close()

if __name__ == "__main__":
    from argparse import ArgumentParser
    import logging

    # Define parser object
    parser = ArgumentParser(description="Initialize the TwoFace project database.")

    vq_group = parser.add_mutually_exclusive_group()
    vq_group.add_argument('-v', '--verbose', action='count', default=0, dest='verbosity')
    vq_group.add_argument('-q', '--quiet', action='count', default=0, dest='quietness')
    # parser.add_argument('-o', '--overwrite', action='store_true', dest='overwrite',
    #                     default=False, help='Destroy everything.')

    parser.add_argument("--allstar", dest="allStar_file", required=True,
                        type=str, help="Path to APOGEE allStar FITS file.")
    parser.add_argument("--allvisit", dest="allVisit_file", required=True,
                        type=str, help="Path to APOGEE allVisit FITS file.")
    parser.add_argument("--credentials", dest="credentials_file", required=True,
                        type=str, help="Path to YAML file with database credentials.")

    args = parser.parse_args()

    # Set logger level based on verbose flags
    if args.verbosity != 0:
        if args.verbosity == 1:
            log.setLevel(logging.DEBUG)
        else: # anything >= 2
            log.setLevel(1)

    elif args.quietness != 0:
        if args.quietness == 1:
            log.setLevel(logging.WARNING)
        else: # anything >= 2
            log.setLevel(logging.ERROR)

    else: # default
        log.setLevel(logging.INFO)

    main(**vars(args))
<|endoftext|>


<commit_before>#! /usr/bin/env python
#
# Example program using irc.client.
#
# This program is free without restrictions; do anything you like with
# it.
#
# Joel Rosdahl <joel@rosdahl.net>

import argparse
import irc.client
import sys

target = None
"The nick or channel to which to send messages"

def on_connect(connection, event):
    if irc.client.is_channel(target):
        connection.join(target)
    else:
        while 1:
            line = sys.stdin.readline().strip()
            if not line:
                break
            connection.privmsg(target, line)
        connection.quit("Using irc.client.py")

def on_join(connection, event):
    while 1:
        line = sys.stdin.readline().strip()
        if not line:
            break
        connection.privmsg(target, line)
    connection.quit("Using irc.client.py")

def on_disconnect(connection, event):
    raise SystemExit()

def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('server')
    parser.add_argument('nickname')
    parser.add_argument('target', help="a nickname or channel")
    parser.add_argument('-p', '--port', default=6667, type=int)
    return parser.parse_args()

def main():
    global target

    args = get_args()
    target = args.target

    client = irc.client.IRC()
    try:
        c = client.server().connect(args.server, args.port, args.nickname)
    except irc.client.ServerConnectionError, x:
        print x
        raise SystemExit(1)

    c.add_global_handler("welcome", on_connect)
    c.add_global_handler("join", on_join)
    c.add_global_handler("disconnect", on_disconnect)

    client.process_forever()

if __name__ == '__main__':
    main()
<commit_msg>Add Python 3 compatibility<commit_after>#! /usr/bin/env python
#
# Example program using irc.client.
#
# This program is free without restrictions; do anything you like with
# it.
#
# Joel Rosdahl <joel@rosdahl.net>

import argparse
import irc.client
import sys

target = None
"The nick or channel to which to send messages"

def on_connect(connection, event):
    if irc.client.is_channel(target):
        connection.join(target)
    else:
        while 1:
            line = sys.stdin.readline().strip()
            if not line:
                break
            connection.privmsg(target, line)
        connection.quit("Using irc.client.py")

def on_join(connection, event):
    while 1:
        line = sys.stdin.readline().strip()
        if not line:
            break
        connection.privmsg(target, line)
    connection.quit("Using irc.client.py")

def on_disconnect(connection, event):
    raise SystemExit()

def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('server')
    parser.add_argument('nickname')
    parser.add_argument('target', help="a nickname or channel")
    parser.add_argument('-p', '--port', default=6667, type=int)
    return parser.parse_args()

def main():
    global target

    args = get_args()
    target = args.target

    client = irc.client.IRC()
    try:
        c = client.server().connect(args.server, args.port, args.nickname)
    except irc.client.ServerConnectionError:
        print(sys.exc_info()[1])
        raise SystemExit(1)

    c.add_global_handler("welcome", on_connect)
    c.add_global_handler("join", on_join)
    c.add_global_handler("disconnect", on_disconnect)

    client.process_forever()

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


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

#Maybe look into using this later??
#http://stackoverflow.com/questions/21613091/how-to-use-scapy-to-determine-wireless-encryption-type
from scapy.all import *
import cli
import signal

#Proto class
class Proto:
	pass

#create a structure to dump misc data that needs to persist across functions
stores = Proto()
stores.ap_list = []

#catch that control+c (SIGINT) input so we can exit gracefully
#Do this yourself: http://stackoverflow.com/questions/1112343/how-do-i-capture-sigint-in-python :D
def siginit_handler(signal, frame):
	print "One moment while we exit..."
	if stores.args.verbose: print('You pressed Ctrl+C. Gracefully exiting the program.')
	#get rid of the monitor interface
	DestoryMonitorInterface()
	#exit
	print "Exiting..."
	sys.exit(0)

#register the signal interupt handler
signal.signal(signal.SIGINT, siginit_handler)

#check to make sure the following dependencies are present. This should essentially echo the build.py
def check_dependencies():
	#CHECK FOR DEPENDENCIES
	if len(cli.check_sysfile('scapy'))==0:
		print 'scapy executable not found. Make sure you have installed scapy (pip install scapy) or this wont work.'
		return False
	else:
		return True

#could this be a simplier function? Probably...but then it wouldn't be as fun. :)
def ValidInterface():
	avail = False
	wlan = stores.args.interface
	if stores.args.verbose: print 'Looking for: ' + wlan
	if stores.args.alreadymon and not "mon" in wlan:
		print 'You must select a monitor interface (ie. mon0, mon1, etc/whatever) if you are are going to use -m as an option.'
		return
	if stores.args.verbose: print 'Verifying wireless interface is available...'
	s=cli.execute_shell('ifconfig | grep ' + wlan)
	lines = s.splitlines()
	if stores.args.verbose: print lines

	for line in lines:
		if wlan in line:
			avail = True

	if avail:
		if stores.args.verbose: print 'Interface found.'
		return True
	else:
		if stores.args.verbose: print 'Looking a little deeper for that interface you asked for.'
		s2=cli.execute_shell('ifconfig -a | grep ' + wlan)
		lines = s.splitlines()
		if stores.args.verbose: print lines
		for line in lines:
			if wlan in line:
				if stores.args.verbose: print 'Interface was found...but its not up. You need to fix that...or heck we can...'
                cli.execute_shell('ifconfig '+wlan+' up')

		if stores.args.verbose: print 'Interface NOT found anywhere.'
		return False

#interface gets transformed from wlan0 to wlan0.mon
def CreateMonitorInterface():
	#create the name for our eventual monitor interface
	stores.wlanMonName=str(stores.args.interface)+".mon"

	#Shut down the interface so we can make some changes
	if stores.args.verbose: print "Bringing down the "+str(stores.args.interface)+" like you asked."
	cli.execute_shell("ifconfig "+str(stores.args.interface)+" down")

	#Rename the interface -- ip link set peth0 name eth0
	if stores.args.verbose: print "Trying to rename the "+str(stores.args.interface)+" to "+wlanMonName
	cli.execute_shell("ip link set "+str(stores.args.interface)+" name "+wlanMonName)

	#Change the interface into a monitor interface
	if stores.args.verbose: print "Switching the "+wlanMonName+" to being a monitor interface."
	cli.execute_shell("iwconfig "+wlanMonName+" mode monitor")

	#Bring the interface
	#ifconfig <interface> up
	if stores.args.verbose: print "Raising the "+wlanMonName+" like you asked."
	cli.execute_shell("ifconfig "+wlanMonName+" up")
	return wlanMonName

#restore the original interface
def DestoryMonitorInterface():
	if stores.args.verbose: print "One moment...getting rid of the monitor interface that we made."
	#Shut down the interface so we can make some changes
	if stores.args.verbose: print "Bringing down the "+stores.wlanMonName+" like you asked."
	cli.execute_shell("ifconfig "+stores.wlanMonName+" down")

	#Rename the interface -- ip link set peth0 name eth0
	if stores.args.verbose: print "Trying to rename the "+stores.wlanMonName+" to "+str(stores.args.interface)
	cli.execute_shell("ip link set "+stores.wlanMonName+" name "+str(stores.args.interface))

	#Change the interface into a monitor interface
	if stores.args.verbose: print "Switching the "+str(stores.args.interface)+" back to being a managed interface."
	cli.execute_shell("iwconfig "+str(stores.args.interface)+" mode managed")

	#Bring the interface
	#ifconfig <interface> up
	if stores.args.verbose: print "Raising the "+str(stores.args.interface)+" like you asked."
	cli.execute_shell("ifconfig "+str(stores.args.interface)+" up")

	return True

#main loop handler
#the actual handler for scapy that we loop through
def PacketHandler(pkt):
	if pkt.haslayer(Dot11):
		if pkt.type == 0 and pkt.subtype == 8:
			if pkt.addr2 not in stores.ap_list:
				ap_list.append(pkt.addr2)
				print "AP MAC: %s with SSID: %s " %(pkt.addr2, pkt.info)

#main loop. This is where the application goes to
def main(args):
	#store our arguments so every function can access them
	stores.args = args
	cli.arguments = args #initialize args for cli
	#check deps
	if not check_dependencies():
		print 'Dependency check failed. Please make sure you have all dependencies installed.'
		return

	#check to make sure that the selected interface is valid
	if not ValidInterface() or stores.args.testing:
		print 'The interface you selected is not valid or does not exist.'
		return

	#create the monitor interface
	monint=""
	if stores.args.alreadymon: #if its already a monitor interface...? Maybe it would be better to determine this progamatically?
		monint=stores.args.interface
	else:
		monint=CreateMonitorInterface()

	#start sniffing
	if len(monint) > 0 and not stores.args.testing:
		sniff(iface=str(monint), prn = PacketHandler)
	else:
		print 'Error: Could not create monitor interface.'
<commit_msg>Added tcpdump dep and re-worked dependecy function a little.<commit_after>#!/usr/bin/env python

#Maybe look into using this later??
#http://stackoverflow.com/questions/21613091/how-to-use-scapy-to-determine-wireless-encryption-type
from scapy.all import *
import cli
import signal

#Proto class
class Proto:
	pass

#create a structure to dump misc data that needs to persist across functions
stores = Proto()
stores.ap_list = []

#catch that control+c (SIGINT) input so we can exit gracefully
#Do this yourself: http://stackoverflow.com/questions/1112343/how-do-i-capture-sigint-in-python :D
def siginit_handler(signal, frame):
	print "One moment while we exit..."
	if stores.args.verbose: print('You pressed Ctrl+C. Gracefully exiting the program.')
	#get rid of the monitor interface
	DestoryMonitorInterface()
	#exit
	print "Exiting..."
	sys.exit(0)

#register the signal interupt handler
signal.signal(signal.SIGINT, siginit_handler)

#check to make sure the following dependencies are present. This should essentially echo the build.py
def check_dependencies():
	#CHECK FOR DEPENDENCIES
	errors=int(0)
	if len(cli.check_sysfile('scapy'))==0:
		print 'scapy executable not found. Make sure you have installed scapy (pip install scapy) or this wont work.'
		errors = errors+1
	if len(cli.check_sysfile('tcpdump'))==0:
		print 'tcpdump executable not found. Make sure you have installed tcpdump or this wont work.'
		errors = errors+1
	if errors > 0:
		return False
	else:
		return True

#could this be a simplier function? Probably...but then it wouldn't be as fun. :)
def ValidInterface():
	avail = False
	wlan = stores.args.interface
	if stores.args.verbose: print 'Looking for: ' + wlan
	if stores.args.alreadymon and not "mon" in wlan:
		print 'You must select a monitor interface (ie. mon0, mon1, etc/whatever) if you are are going to use -m as an option.'
		return
	if stores.args.verbose: print 'Verifying wireless interface is available...'
	s=cli.execute_shell('ifconfig | grep ' + wlan)
	lines = s.splitlines()
	if stores.args.verbose: print lines

	for line in lines:
		if wlan in line:
			avail = True

	if avail:
		if stores.args.verbose: print 'Interface found.'
		return True
	else:
		if stores.args.verbose: print 'Looking a little deeper for that interface you asked for.'
		s2=cli.execute_shell('ifconfig -a | grep ' + wlan)
		lines = s.splitlines()
		if stores.args.verbose: print lines
		for line in lines:
			if wlan in line:
				if stores.args.verbose: print 'Interface was found...but its not up. You need to fix that...or heck we can...'
                cli.execute_shell('ifconfig '+wlan+' up')

		if stores.args.verbose: print 'Interface NOT found anywhere.'
		return False

#interface gets transformed from wlan0 to wlan0.mon
def CreateMonitorInterface():
	#create the name for our eventual monitor interface
	stores.wlanMonName=str(stores.args.interface)+".mon"

	#Shut down the interface so we can make some changes
	if stores.args.verbose: print "Bringing down the "+str(stores.args.interface)+" like you asked."
	cli.execute_shell("ifconfig "+str(stores.args.interface)+" down")

	#Rename the interface -- ip link set peth0 name eth0
	if stores.args.verbose: print "Trying to rename the "+str(stores.args.interface)+" to "+wlanMonName
	cli.execute_shell("ip link set "+str(stores.args.interface)+" name "+wlanMonName)

	#Change the interface into a monitor interface
	if stores.args.verbose: print "Switching the "+wlanMonName+" to being a monitor interface."
	cli.execute_shell("iwconfig "+wlanMonName+" mode monitor")

	#Bring the interface
	#ifconfig <interface> up
	if stores.args.verbose: print "Raising the "+wlanMonName+" like you asked."
	cli.execute_shell("ifconfig "+wlanMonName+" up")
	return wlanMonName

#restore the original interface
def DestoryMonitorInterface():
	if stores.args.verbose: print "One moment...getting rid of the monitor interface that we made."
	#Shut down the interface so we can make some changes
	if stores.args.verbose: print "Bringing down the "+stores.wlanMonName+" like you asked."
	cli.execute_shell("ifconfig "+stores.wlanMonName+" down")

	#Rename the interface -- ip link set peth0 name eth0
	if stores.args.verbose: print "Trying to rename the "+stores.wlanMonName+" to "+str(stores.args.interface)
	cli.execute_shell("ip link set "+stores.wlanMonName+" name "+str(stores.args.interface))

	#Change the interface into a monitor interface
	if stores.args.verbose: print "Switching the "+str(stores.args.interface)+" back to being a managed interface."
	cli.execute_shell("iwconfig "+str(stores.args.interface)+" mode managed")

	#Bring the interface
	#ifconfig <interface> up
	if stores.args.verbose: print "Raising the "+str(stores.args.interface)+" like you asked."
	cli.execute_shell("ifconfig "+str(stores.args.interface)+" up")

	return True

#main loop handler
#the actual handler for scapy that we loop through
def PacketHandler(pkt):
	if pkt.haslayer(Dot11):
		if pkt.type == 0 and pkt.subtype == 8:
			if pkt.addr2 not in stores.ap_list:
				ap_list.append(pkt.addr2)
				print "AP MAC: %s with SSID: %s " %(pkt.addr2, pkt.info)

#main loop. This is where the application goes to
def main(args):
	#store our arguments so every function can access them
	stores.args = args
	cli.arguments = args #initialize args for cli
	#check deps
	if not check_dependencies():
		print 'Dependency check failed. Please make sure you have all dependencies installed.'
		return

	#check to make sure that the selected interface is valid
	if not ValidInterface() or stores.args.testing:
		print 'The interface you selected is not valid or does not exist.'
		return

	#create the monitor interface
	monint=""
	if stores.args.alreadymon: #if its already a monitor interface...? Maybe it would be better to determine this progamatically?
		monint=stores.args.interface
	else:
		monint=CreateMonitorInterface()

	#start sniffing
	if len(monint) > 0 and not stores.args.testing:
		sniff(iface=str(monint), prn = PacketHandler)
	else:
		print 'Error: Could not create monitor interface.'
<|endoftext|>


<commit_before>#!/usr/bin/env python
# Source: https://github.com/Sh4d/LPD8806
# Modified by trizz

"""
LPD8806.py: Raspberry Pi library for the Adafruit LPD8806 RGB Strand

Provides the ability to drive a LPD8806 based strand of RGB leds from the Raspberry Pi

Colors are provided as RGB and converted internally to the strand's 7 bit values.

The leds are available here: http://adafruit.com/products/306

Wiring:
    Pi MOSI -> Strand DI
    Pi SCLK -> Strand CI

Make sure to use an external power supply to power the strand

Example:
    >> import LPD8806
    >> led = LPD8806.strand()
    >> led.fill(255, 0, 0)
"""

class ledBar:
    def __init__(self, leds=32, dev="/dev/spidev0.1"):
        """
        Variables:
            leds -- strand size
            dev -- spi device
        """
        self.dev = dev
        self.spi = file(self.dev, "wb")
        self.leds = leds
        self.gamma = bytearray(256)
        self.buffer = [0 for x in range(self.leds)]
        self.wheelOffset = 0

        for led in range(self.leds):
            self.buffer[led] = bytearray(3)

        for i in range(256):
            # Color calculations from http://learn.adafruit.com/light-painting-with-raspberry-pi
            self.gamma[i] = 0x80 | int(pow(float(i) / 255.0, 2.5) * 127.0 + 0.5)

    def fill(self, r, g, b, start=0, end=0):
        """
        Fill the strand (or a subset) with a single color
        """
        if start < 0: raise NameError("Start invalid:" + str(start))
        if end == 0: end = self.leds
        if end > self.leds: raise NameError("End invalid: " + str(end))

        for led in range(start, end):
            self.buffer[led][0] = self.gamma[g]
            self.buffer[led][1] = self.gamma[r]
            self.buffer[led][2] = self.gamma[b]

        self.update()

    def set(self, pixel, r, g, b):
        """
        Set a single LED a specific color
        """
        self.buffer[pixel][0] = self.gamma[g]
        self.buffer[pixel][1] = self.gamma[r]
        self.buffer[pixel][2] = self.gamma[b]

        self.update()

    def update(self):
        """
        Flush the buffer to the strand
        """
        for x in range(self.leds):
            self.spi.write(self.buffer[x])
            # self.spi.flush()

        self.spi.write(bytearray(b'\x00'))
        self.spi.flush()

    def wheel(self, start=0, end=0):
        """
        Generate a moving color wheel between a start and end
        """
        if end == 0: end = self.leds
        size = end - start
        self.wheelOffset += 1
        if self.wheelOffset == 384: self.wheelOffset = 0;
        for i in range(size):
            color = (i * (384 / size) + self.wheelOffset) % 384;
            if color < 128:
                r = 127 - color % 128
                g = color % 128
                b = 0
            elif color < 256:
                g = 127 - color % 128
                b = color % 128
                r = 0
            else:
                b = 127 - color % 128
                r = color % 128
                g = 0
            self.set(start + i, r, g, b)
            print r, ',', g, ',', b
        self.update()
<commit_msg>Add HSV support<commit_after>#!/usr/bin/env python
# Source: https://github.com/Sh4d/LPD8806
# Modified by trizz

"""
LPD8806.py: Raspberry Pi library for the Adafruit LPD8806 RGB Strand

Provides the ability to drive a LPD8806 based strand of RGB leds from the Raspberry Pi

Colors are provided as RGB and converted internally to the strand's 7 bit values.

The leds are available here: http://adafruit.com/products/306

Wiring:
    Pi MOSI -> Strand DI
    Pi SCLK -> Strand CI

Make sure to use an external power supply to power the strand

Example:
    >> import LPD8806
    >> led = LPD8806.strand()
    >> led.fill(255, 0, 0)
"""

import colorsys

class ledBar:
    def __init__(self, leds=32, dev="/dev/spidev0.1"):
        """
        Variables:
            leds -- strand size
            dev -- spi device
        """
        self.dev = dev
        self.spi = file(self.dev, "wb")
        self.leds = leds
        self.gamma = bytearray(256)
        self.buffer = [0 for x in range(self.leds)]
        self.wheelOffset = 0

        for led in range(self.leds):
            self.buffer[led] = bytearray(3)

        for i in range(256):
            # Color calculations from http://learn.adafruit.com/light-painting-with-raspberry-pi
            self.gamma[i] = 0x80 | int(pow(float(i) / 255.0, 2.5) * 127.0 + 0.5)

    def fillRGB(self, r, g, b, start=0, end=0):
        """
        Fill the strand (or a subset) with a single color
        """
        if start < 0: raise NameError("Start invalid:" + str(start))
        if end == 0: end = self.leds
        if end > self.leds: raise NameError("End invalid: " + str(end))

        for led in range(start, end):
            self.buffer[led][0] = self.gamma[g]
            self.buffer[led][1] = self.gamma[r]
            self.buffer[led][2] = self.gamma[b]

        self.update()

    # Fill the strand (or a subset) with a single color using HSV values
    def fillHSV(self, h, s, v, start=0, end=0):
        if start < 0: raise NameError("Start invalid:" + str(start))
        if end == 0: end = self.leds
        if end > self.leds: raise NameError("End invalid: " + str(end))

        rgb = colorsys.hsv_to_rgb(h/360.0, s, v)

        r = int(rgb[0]*255)
        g = int(rgb[1]*255)
        b = int(rgb[2]*255)

        for led in range(start, end):
            self.buffer[led][0] = self.gamma[g]
            self.buffer[led][1] = self.gamma[r]
            self.buffer[led][2] = self.gamma[b]

        self.update()

    def set(self, pixel, r, g, b):
        """
        Set a single LED a specific color
        """
        self.buffer[pixel][0] = self.gamma[g]
        self.buffer[pixel][1] = self.gamma[r]
        self.buffer[pixel][2] = self.gamma[b]

        self.update()

    def update(self):
        """
        Flush the buffer to the strand
        """
        for x in range(self.leds):
            self.spi.write(self.buffer[x])
            # self.spi.flush()

        self.spi.write(bytearray(b'\x00'))
        self.spi.flush()

    def wheel(self, start=0, end=0):
        """
        Generate a moving color wheel between a start and end
        """
        if end == 0: end = self.leds
        size = end - start
        self.wheelOffset += 1
        if self.wheelOffset == 384: self.wheelOffset = 0;
        for i in range(size):
            color = (i * (384 / size) + self.wheelOffset) % 384;
            if color < 128:
                r = 127 - color % 128
                g = color % 128
                b = 0
            elif color < 256:
                g = 127 - color % 128
                b = color % 128
                r = 0
            else:
                b = 127 - color % 128
                r = color % 128
                g = 0
            self.set(start + i, r, g, b)
            print r, ',', g, ',', b
        self.update()
<|endoftext|>


<commit_before>#!/usr/bin/python
import serial
import time
import logging
import traceback
import sys
import sqlite3
import random

info = logging.getLogger(__name__).info
error = logging.getLogger(__name__).error

SIMULATION = True

class SerialSimulator:
    """Class used for simulating serial data"""
    def __init__(self):
        """Init"""
        self.timeout=None
        self.baudrate = None
    def write(self, dataToWrite):
        """Simulated serial write"""
        pass
    def readlines(self):
        """Simulated serial read"""
        temperature0 = 15
        rh0 = 57
        dataStr=[]
        for sensorId in range(6):
            temperature = temperature0 + random.random()*4
            rh = rh0 + random.random()*5
            dataStr.append("%d;%.2f;%.2f\n" %(sensorId, temperature, rh))
        return dataStr

class Logger:
    def __init__(self, portName, logfile, sampleTime):
        """Init method"""
        if SIMULATION:
            self.ser = SerialSimulator()
        else:
            self.ser = serial.Serial(port=portName)
        self.ser.timeout=2 # [s] timeout
        self.ser.baudrate =9600
        self.sampleTime = sampleTime
        # configure logging
        self.log = logging.basicConfig(level=logging.INFO,
                        filename=logfile, # log to this file
                        format='%(asctime)s;%(levelname)s;%(message)s') # include timestamp
        self.db = None # Start with no database connection

    def attachDb(self, db):
        """Attach a database object"""
        self.db = db

    def start(self):
        """Start logging"""
        oldtime=time.time()-self.sampleTime
        timeToSleep=self.sampleTime
        oldTimeToSleep = timeToSleep
        while(True):
            try:
                realDelay=(time.time()-oldtime)
                operationTime = realDelay-oldTimeToSleep
                #print "Operation time: %g" %operationTime
                timeToSleep =self.sampleTime-operationTime
                #print "Real delay: %g" %(realDelay)
                oldtime=time.time()
                oldTimeToSleep = timeToSleep
                #print "Time to sleep: %g" %timeToSleep

                time.sleep(max(0, timeToSleep)) # Sleeping this time
                resp=self.getReading()
                ts = time.strftime("%Y-%m-%d %H:%M:%S") # Get timestamp
                # Do not log empty data
                if resp != '':
                    logString=""
                    for data in resp:
                        logString += data.strip() + ";"
                    logString = logString[:-1]
                    info(logString)

                    # Log to database
                    if self.db is not None:
                        data = []
                        for line in resp:
                            strippedData = line.strip()
                            dataList = strippedData.split(';')
                            sensorId = int(dataList[0])
                            temp    = dataList[1]
                            rh      = dataList[2]
                            if not (("Error" in temp) or ("Error" in rh)):
                                data.append({'sensor_id':sensorId, 'values':(float(temp),float(rh),)})
                            else:
                                error("Sensor read error: " + str(dataList))
                        self.db.addData(ts,data)
                        self.db.commit()

            except KeyboardInterrupt:
                break
            except:
                error(traceback.format_exc())

    def getReading(self):
        """Get a reading of all sensors"""
        self.ser.write("read\n")
        resp=self.ser.readlines()
        return resp

    def close(self):
        self.ser.close()

class Db:
    def __init__(self, dbFilename):
        self.conn = sqlite3.connect(dbFilename)

    def createTables(self):
        c = self.conn.cursor()

        # Create table senors
        c.execute('''
                CREATE TABLE sensors (
                    id integer primary key autoincrement not null,
                    name varchar,
                    description varchar,
                    enabled boolean default 1
                );
            ''')

        # Create table measurements
        c.execute('''
                CREATE TABLE measurements (
                    id integer primary key autoincrement not null,
                    ts datetime
                );
            ''')

        # Create table values
        c.execute('''
                CREATE TABLE measurement_values (
                    measurement_id integer not null,
                    sensor_id integer not null,
                    temperature float
                );
            ''')

        # Create indexes
        c.execute('''CREATE UNIQUE INDEX "unique_values" ON "measurement_values" ("measurement_id" ASC, "sensor_id" ASC)''')

        # Insert sensors
        c.execute("INSERT INTO sensors (name, description) VALUES ('Sensor 0','Blue. Position C. In wall, upper left.')")
        c.execute("INSERT INTO sensors (name, description) VALUES ('Sensor 1','Blue/White. Position A. In wall lower left.')")
        c.execute("INSERT INTO sensors (name, description) VALUES ('Sensor 2','Green. Position D2. In wall center.')")
        c.execute("INSERT INTO sensors (name, description) VALUES ('Sensor 3','Green/White. Position D1. In air gap center.')")
        c.execute("INSERT INTO sensors (name, description) VALUES ('Sensor 4','Purple. Position E1. In air gap right wall.')")
        c.execute("INSERT INTO sensors (name, description) VALUES ('Sensor 5','Purple/White. Position E2. In right wall.')")

        # Save (commit) the changes
        self.conn.commit()

    def close(self):
        # We can also close the connection if we are done with it.
        # Just be sure any changes have been committed or they will be lost.
        self.conn.close()

    def commit(self):
        """Commit the changes"""
        self.conn.commit()

    def update1(self):
        """Alter some tables"""
        c = self.conn.cursor()
        c.execute('''
                ALTER TABLE measurement_values ADD
                    rh float
            ''')
        # Save (commit) the changes
        self.conn.commit()

    def addData(self,ts,measurement_values):
        """Add one measurement to the database
        ts    A string with the timestamp to use
        measurement_values    A list with dicts with the keys sensor_id and values
        """
        c = self.conn.cursor()

        # Add measurement
        c.execute ('INSERT INTO measurements (ts) VALUES (?)', (ts,))
        measurement_id = c.lastrowid

        for value in measurement_values:
            c.execute('INSERT INTO measurement_values (measurement_id, sensor_id, temperature, rh) VALUES (?,?,?,?)',
                      (measurement_id,value['sensor_id'],) + value['values'])
    def addOldData(self, filename):
        inFile = open(filename,'r')
        for line in inFile:
            row = line.strip()
            inData = row.split(';')
            ts = inData[0][0:19]
            data = []
            for sensorId in range(6):
                temp = inData[3+sensorId*3]
                rh = inData[4+sensorId*3]
                if not (("Error" in temp) or ("Error" in rh)):
                    data.append({'sensor_id':sensorId, 'values':(float(temp),float(rh),)})
                else:
                    print "Error found here: " + row
            self.addData(ts,data)
        self.conn.commit()

    def getData(self):
        """
        SELECT ts, rh
FROM measurement_values mv
INNER JOIN measurements m ON m.id=mv.measurement_id
WHERE sensor_id=2 AND ts >="2016-06-15 00:00:00" AND ts <="2016-06-16 00:00:00"
"""
        pass

def createDb(dbFilename):
    """Create the database with the default tables"""
    myDb = Db(dbFilename)
    myDb.createTables()
    myDb.update1()

    myDb.close()

def testDb():
    """Test database functions"""
    dbFilename = "measurement.sqlite"
    createDb(dbFilename)

    # Add old log data
    myDb = Db(dbFilename)
    myDb.addOldData('room.log')

    # Connect the database to the logger and start logging
    myLogger = Logger("/dev/ttyUSB0", "test1.log", sampleTime=3)
    myLogger.attachDb(myDb)
    myLogger.start()

def testSimulation():
    """Test simulated data"""
    mode = 0
    if mode ==0:
        print "No input arguments, defaulting to /dev/ttyUSB0, room.log, measurement.sqlite, sampleTime=300"
        myLogger = Logger("/dev/ttyUSB0", "test1.log", sampleTime=3)
        myDb = Db("measurement.sqlite")
        myLogger.attachDb(myDb)
        myLogger.start()
        myLogger.close()
    else:
        print "Test mode..."
        while(1):
            myLogger = Logger("/dev/ttyUSB0", "test2.log", sampleTime=5)
            print myLogger.getReading()

if __name__=="__main__":
    if len(sys.argv) <2:
        sampleTime = 3
        print "No input arguments, defaulting to /dev/ttyUSB0, room.log, measurement.sqlite, sampleTime=%ds" %sampleTime
        myLogger = Logger("/dev/ttyUSB0", "room.log", sampleTime=sampleTime)
        myDb = Db("measurement.sqlite")
        myLogger.attachDb(myDb)
        myLogger.start()
        myLogger.close()
    else:
        if("test" in sys.argv[1]):
            print "Test mode..."
            while(1):
                myLogger = Logger("/dev/ttyUSB0", "test.log", sampleTime=5)
                print myLogger.getReading()
        elif "create_db" in sys.argv[1] and len(sys.argv)==(2+1):
            dbFilename = sys.argv[2]
            print "Creating empty database with name " + dbFilename
            createDb(dbFilename)

        elif "add_old" in sys.argv[1] and len(sys.argv)==(3+1):
            print "Adding old data to the database..."
            logFilename = sys.argv[2]
            dbFilename = sys.argv[3]
                # Add old log data
            myDb = Db(dbFilename)
            myDb.addOldData(logFilename)
            myDb.close()

<commit_msg>Defaulting to 5min sample time<commit_after>#!/usr/bin/python
import serial
import time
import logging
import traceback
import sys
import sqlite3
import random

info = logging.getLogger(__name__).info
error = logging.getLogger(__name__).error

SIMULATION = True

class SerialSimulator:
    """Class used for simulating serial data"""
    def __init__(self):
        """Init"""
        self.timeout=None
        self.baudrate = None
    def write(self, dataToWrite):
        """Simulated serial write"""
        pass
    def readlines(self):
        """Simulated serial read"""
        temperature0 = 15
        rh0 = 57
        dataStr=[]
        for sensorId in range(6):
            temperature = temperature0 + random.random()*4
            rh = rh0 + random.random()*5
            dataStr.append("%d;%.2f;%.2f\n" %(sensorId, temperature, rh))
        return dataStr

class Logger:
    def __init__(self, portName, logfile, sampleTime):
        """Init method"""
        if SIMULATION:
            self.ser = SerialSimulator()
        else:
            self.ser = serial.Serial(port=portName)
        self.ser.timeout=2 # [s] timeout
        self.ser.baudrate =9600
        self.sampleTime = sampleTime
        # configure logging
        self.log = logging.basicConfig(level=logging.INFO,
                        filename=logfile, # log to this file
                        format='%(asctime)s;%(levelname)s;%(message)s') # include timestamp
        self.db = None # Start with no database connection

    def attachDb(self, db):
        """Attach a database object"""
        self.db = db

    def start(self):
        """Start logging"""
        oldtime=time.time()-self.sampleTime
        timeToSleep=self.sampleTime
        oldTimeToSleep = timeToSleep
        while(True):
            try:
                realDelay=(time.time()-oldtime)
                operationTime = realDelay-oldTimeToSleep
                #print "Operation time: %g" %operationTime
                timeToSleep =self.sampleTime-operationTime
                #print "Real delay: %g" %(realDelay)
                oldtime=time.time()
                oldTimeToSleep = timeToSleep
                #print "Time to sleep: %g" %timeToSleep

                time.sleep(max(0, timeToSleep)) # Sleeping this time
                resp=self.getReading()
                ts = time.strftime("%Y-%m-%d %H:%M:%S") # Get timestamp
                # Do not log empty data
                if resp != '':
                    logString=""
                    for data in resp:
                        logString += data.strip() + ";"
                    logString = logString[:-1]
                    info(logString)

                    # Log to database
                    if self.db is not None:
                        data = []
                        for line in resp:
                            strippedData = line.strip()
                            dataList = strippedData.split(';')
                            sensorId = int(dataList[0])
                            temp    = dataList[1]
                            rh      = dataList[2]
                            if not (("Error" in temp) or ("Error" in rh)):
                                data.append({'sensor_id':sensorId, 'values':(float(temp),float(rh),)})
                            else:
                                error("Sensor read error: " + str(dataList))
                        self.db.addData(ts,data)
                        self.db.commit()

            except KeyboardInterrupt:
                break
            except:
                error(traceback.format_exc())

    def getReading(self):
        """Get a reading of all sensors"""
        self.ser.write("read\n")
        resp=self.ser.readlines()
        return resp

    def close(self):
        self.ser.close()

class Db:
    def __init__(self, dbFilename):
        self.conn = sqlite3.connect(dbFilename)

    def createTables(self):
        c = self.conn.cursor()

        # Create table senors
        c.execute('''
                CREATE TABLE sensors (
                    id integer primary key autoincrement not null,
                    name varchar,
                    description varchar,
                    enabled boolean default 1
                );
            ''')

        # Create table measurements
        c.execute('''
                CREATE TABLE measurements (
                    id integer primary key autoincrement not null,
                    ts datetime
                );
            ''')

        # Create table values
        c.execute('''
                CREATE TABLE measurement_values (
                    measurement_id integer not null,
                    sensor_id integer not null,
                    temperature float
                );
            ''')

        # Create indexes
        c.execute('''CREATE UNIQUE INDEX "unique_values" ON "measurement_values" ("measurement_id" ASC, "sensor_id" ASC)''')

        # Insert sensors
        c.execute("INSERT INTO sensors (name, description) VALUES ('Sensor 0','Blue. Position C. In wall, upper left.')")
        c.execute("INSERT INTO sensors (name, description) VALUES ('Sensor 1','Blue/White. Position A. In wall lower left.')")
        c.execute("INSERT INTO sensors (name, description) VALUES ('Sensor 2','Green. Position D2. In wall center.')")
        c.execute("INSERT INTO sensors (name, description) VALUES ('Sensor 3','Green/White. Position D1. In air gap center.')")
        c.execute("INSERT INTO sensors (name, description) VALUES ('Sensor 4','Purple. Position E1. In air gap right wall.')")
        c.execute("INSERT INTO sensors (name, description) VALUES ('Sensor 5','Purple/White. Position E2. In right wall.')")

        # Save (commit) the changes
        self.conn.commit()

    def close(self):
        # We can also close the connection if we are done with it.
        # Just be sure any changes have been committed or they will be lost.
        self.conn.close()

    def commit(self):
        """Commit the changes"""
        self.conn.commit()

    def update1(self):
        """Alter some tables"""
        c = self.conn.cursor()
        c.execute('''
                ALTER TABLE measurement_values ADD
                    rh float
            ''')
        # Save (commit) the changes
        self.conn.commit()

    def addData(self,ts,measurement_values):
        """Add one measurement to the database
        ts    A string with the timestamp to use
        measurement_values    A list with dicts with the keys sensor_id and values
        """
        c = self.conn.cursor()

        # Add measurement
        c.execute ('INSERT INTO measurements (ts) VALUES (?)', (ts,))
        measurement_id = c.lastrowid

        for value in measurement_values:
            c.execute('INSERT INTO measurement_values (measurement_id, sensor_id, temperature, rh) VALUES (?,?,?,?)',
                      (measurement_id,value['sensor_id'],) + value['values'])
    def addOldData(self, filename):
        inFile = open(filename,'r')
        for line in inFile:
            row = line.strip()
            inData = row.split(';')
            ts = inData[0][0:19]
            data = []
            for sensorId in range(6):
                temp = inData[3+sensorId*3]
                rh = inData[4+sensorId*3]
                if not (("Error" in temp) or ("Error" in rh)):
                    data.append({'sensor_id':sensorId, 'values':(float(temp),float(rh),)})
                else:
                    print "Error found here: " + row
            self.addData(ts,data)
        self.conn.commit()

    def getData(self):
        """
        SELECT ts, rh
FROM measurement_values mv
INNER JOIN measurements m ON m.id=mv.measurement_id
WHERE sensor_id=2 AND ts >="2016-06-15 00:00:00" AND ts <="2016-06-16 00:00:00"
"""
        pass

def createDb(dbFilename):
    """Create the database with the default tables"""
    myDb = Db(dbFilename)
    myDb.createTables()
    myDb.update1()

    myDb.close()

def testDb():
    """Test database functions"""
    dbFilename = "measurement.sqlite"
    createDb(dbFilename)

    # Add old log data
    myDb = Db(dbFilename)
    myDb.addOldData('room.log')

    # Connect the database to the logger and start logging
    myLogger = Logger("/dev/ttyUSB0", "test1.log", sampleTime=3)
    myLogger.attachDb(myDb)
    myLogger.start()

def testSimulation():
    """Test simulated data"""
    mode = 0
    if mode ==0:
        print "No input arguments, defaulting to /dev/ttyUSB0, room.log, measurement.sqlite, sampleTime=300"
        myLogger = Logger("/dev/ttyUSB0", "test1.log", sampleTime=3)
        myDb = Db("measurement.sqlite")
        myLogger.attachDb(myDb)
        myLogger.start()
        myLogger.close()
    else:
        print "Test mode..."
        while(1):
            myLogger = Logger("/dev/ttyUSB0", "test2.log", sampleTime=5)
            print myLogger.getReading()

if __name__=="__main__":
    if len(sys.argv) <2:
        sampleTime = 5*60 #[s]
        print "No input arguments, defaulting to /dev/ttyUSB0, room.log, measurement.sqlite, sampleTime=%ds" %sampleTime
        myLogger = Logger("/dev/ttyUSB0", "room.log", sampleTime=sampleTime)
        myDb = Db("measurement.sqlite")
        myLogger.attachDb(myDb)
        myLogger.start()
        myLogger.close()
    else:
        if("test" in sys.argv[1]):
            print "Test mode..."
            while(1):
                myLogger = Logger("/dev/ttyUSB0", "test.log", sampleTime=5)
                print myLogger.getReading()
        elif "create_db" in sys.argv[1] and len(sys.argv)==(2+1):
            dbFilename = sys.argv[2]
            print "Creating empty database with name " + dbFilename
            createDb(dbFilename)

        elif "add_old" in sys.argv[1] and len(sys.argv)==(3+1):
            print "Adding old data to the database..."
            logFilename = sys.argv[2]
            dbFilename = sys.argv[3]
                # Add old log data
            myDb = Db(dbFilename)
            myDb.addOldData(logFilename)
            myDb.close()

<|endoftext|>


<commit_before>from event import Signal
import pysndfile
import numpy

class Action(object):
    """Describes an action, and a way to revert that action"""

    def __init__(self, do, undo):
        """do and undo are tuples in the form (fun, args) where fun is a
        function and args contains the arguments"""
        self._do = do
        self._undo = undo

    def do(self):
        fun, args = self._do
        return fun(*args)

    def undo(self):
        fun, args = self._undo
        return fun(*args)

class History(object):
    "A list of actions, that can be undone and redone."

    def __init__(self):
        self._actions = []
        self._last = -1

    def push(self, action):
        if self._last < len(self._actions) - 1:
            del self._actions[self._last + 1:]
        self._actions.append(action)
        self._last = self._last + 1

    def undo(self):
        if self._last < 0:
            return None
        else:
            action = self._actions[self._last]
            self._last = self._last - 1
            return action.undo()

    def redo(self):
        if self._last == len(self._actions) - 1:
            return None
        else:
            self._last = self._last + 1
            action = self._actions[self._last]
            return action.do()

class Sound(object):

    # _data is a numpy.ndarray, as returned by pysndfile

    # For convenience, some operations (ex: cut(), copy(), ...) are
    # performed on list(_data), and the result is then converted to a
    # numpy array.

    def __init__(self, filename=None):
        self.filename = filename
        if filename == None:
            # empty sound
            self._data = numpy.array([])
            self.numchan = 1
        else:
            f = pysndfile.sndfile(filename)
            nframes = f.get_nframes()
            self._data = f.read_frames(nframes)
            self.numchan = f.get_channels()
        self.history = History()
        self.changed = Signal()

    def save(self, format):
        self.save_as(self.filename, format)

    def save_as(self, filename, format):
        pass

    def cut(self, start, end):
        clip = self._data[start:end]
        do = (self._do_cut, (start, end))
        undo = (self._do_paste, (start, self._data[start:end]))
        action = Action(do, undo)
        action.do()
        self.history.push(action)
        self.changed()
        return clip

    def _do_cut(self, start, end):
        # using del on numpy.ndarray raises a ValueError. Converting
        # to list.
        data = list(self._data)
        del data[start:end]
        self._data = numpy.array(data)

    def copy(self, start, end):
        clip = self._data[start:end]
        return clip

    def paste(self, start, clip):
        do = (self._do_paste, (start, clip))
        undo = (self._do_cut, (start, start + len(clip)))
        action = Action(do, undo)
        action.do()
        self.history.push(action)
        self.changed()

    def _do_paste(self, start, clip):
        data = list(self._data)
        data = data[:start] + list(clip) + data[start:]
        self._data = numpy.array(data)

    def normalize(self, start, end):
        pass

    def reverse(self, start, end):
        pass

    def monoize(self, start, end):
        pass

    def undo(self):
        self.history.undo()
        self.changed()

    def redo(self):
        self.history.redo()
        self.changed()

# -- Tests

def testAction():
    f = lambda x: x
    do = (f, (1,))
    undo = (f, (2,))
    a = Action(do, undo)
    assert a.do() == 1
    assert a.undo() == 2

    g = lambda : 1
    do = (g, ())
    undo = (g, ())
    a = Action(do, undo)
    assert a.do() == 1
    assert a.undo() == 1

def testHistory():
    history = History()
    f = lambda x: x
    do = (f, (1,))
    undo = (f, (2,))
    action = Action(do, undo)
    history.push(action)
    assert history.undo() == 2
    assert history.undo() == None
    assert history.redo() == 1
    assert history.redo() == None
    assert history.undo() == 2
    history.push(action)
    history.push(action)
    assert history.undo() == 2
    assert history.undo() == 2
    assert history.redo() == 1
    assert history.redo() == 1
    assert history.redo() == None

def testSound():
    from copy import copy
    snd = Sound()

    # synthesize a sine wave
    from math import sin
    SR = 44100
    f0 = 440
    time = 5
    sine = [sin(2 * 3.14 * f0/SR * x) for x in range(time * SR)]
    start, end = 2*SR, 4*SR
    sine2 = copy(sine)
    snd._data = copy(sine)
    del sine2[start:end]
    snd.cut(start, end)
    assert snd._data.tolist() == sine2

    snd.history.undo()
    assert snd._data.tolist() == sine
    snd.history.undo()
    assert snd._data.tolist() == sine
    snd.history.redo()
    assert snd._data.tolist() == sine2

    clip = snd.copy(start, end)
    snd.paste(0, clip)
    assert snd._data.tolist() == sine2[start:end] + sine2
    snd.history.undo()
    assert snd._data.tolist() == sine2
    snd.history.redo()
    assert snd._data.tolist() == sine2[start:end] + sine2

    # test with a mono file
    snd = Sound("sounds/test1.wav")
    assert snd._data != []
    start = 4444
    end = 55555
    data = snd._data.tolist()
    data2 = snd._data.tolist()
    del data2[start:end]
    snd.cut(start, end)
    assert snd._data.tolist() == data2
    snd.history.undo()
    assert snd._data.tolist() == data
    snd.history.undo()
    assert snd._data.tolist() == data
    snd.history.redo()
    assert snd._data.tolist() == data2
    clip = snd.copy(start, end)
    snd.paste(0, clip)
    assert snd._data.tolist() == data2[start:end] + data2
    snd.history.undo()
    assert snd._data.tolist() == data2
    snd.paste(0, clip)
    assert snd._data.tolist() == data2[start:end] + data2

    # test with a stereo file
    snd = Sound("sounds/test2.wav")
    assert snd._data.tolist() != []
    start = 4444
    end = 55555
    data = copy(snd._data.tolist())
    data2 = copy(snd._data.tolist())
    del data2[start:end]
    snd.cut(start, end)
    assert snd._data.tolist() == data2
    snd.history.undo()
    assert snd._data.tolist() == data
    snd.history.undo()
    assert snd._data.tolist() == data
    snd.history.redo()
    assert snd._data.tolist() == data2
    clip = snd.copy(start, end)
    snd.paste(0, clip)
    assert snd._data.tolist() == data2[start:end] + data2
    snd.history.undo()
    assert snd._data.tolist() == data2
    snd.paste(0, clip)
    assert snd._data.tolist() == data2[start:end] + data2

if __name__ == '__main__':
    testAction()
    testSound()
    testHistory()
<commit_msg>more efficient cut and paste.<commit_after>from event import Signal
import pysndfile
import numpy

class Action(object):
    """Describes an action, and a way to revert that action"""

    def __init__(self, do, undo):
        """do and undo are tuples in the form (fun, args) where fun is a
        function and args contains the arguments"""
        self._do = do
        self._undo = undo

    def do(self):
        fun, args = self._do
        return fun(*args)

    def undo(self):
        fun, args = self._undo
        return fun(*args)

class History(object):
    "A list of actions, that can be undone and redone."

    def __init__(self):
        self._actions = []
        self._last = -1

    def push(self, action):
        if self._last < len(self._actions) - 1:
            del self._actions[self._last + 1:]
        self._actions.append(action)
        self._last = self._last + 1

    def undo(self):
        if self._last < 0:
            return None
        else:
            action = self._actions[self._last]
            self._last = self._last - 1
            return action.undo()

    def redo(self):
        if self._last == len(self._actions) - 1:
            return None
        else:
            self._last = self._last + 1
            action = self._actions[self._last]
            return action.do()

class Sound(object):

    # _data is a numpy.ndarray, as returned by pysndfile

    # For convenience, some operations (ex: cut(), copy(), ...) are
    # performed on list(_data), and the result is then converted to a
    # numpy array.

    def __init__(self, filename=None):
        self.filename = filename
        if filename == None:
            # empty sound
            self._data = numpy.array([])
            self.numchan = 1
        else:
            f = pysndfile.sndfile(filename)
            nframes = f.get_nframes()
            self._data = f.read_frames(nframes)
            self.numchan = f.get_channels()
        self.history = History()
        self.changed = Signal()

    def save(self, format):
        self.save_as(self.filename, format)

    def save_as(self, filename, format):
        pass

    def cut(self, start, end):
        clip = self._data[start:end]
        do = (self._do_cut, (start, end))
        undo = (self._do_paste, (start, self._data[start:end]))
        action = Action(do, undo)
        action.do()
        self.history.push(action)
        self.changed()
        return clip

    def _do_cut(self, start, end):
        data = numpy.concatenate((self._data[:start], self._data[end:]))
        self._data = data

    def copy(self, start, end):
        clip = self._data[start:end]
        return clip

    def paste(self, start, clip):
        do = (self._do_paste, (start, clip))
        undo = (self._do_cut, (start, start + len(clip)))
        action = Action(do, undo)
        action.do()
        self.history.push(action)
        self.changed()

    def _do_paste(self, start, clip):
        data = numpy.concatenate((self._data[:start], clip,self._data[start:]))
        self._data = data

    def normalize(self, start, end):
        pass

    def reverse(self, start, end):
        pass

    def monoize(self, start, end):
        pass

    def undo(self):
        self.history.undo()
        self.changed()

    def redo(self):
        self.history.redo()
        self.changed()

# -- Tests

def testAction():
    f = lambda x: x
    do = (f, (1,))
    undo = (f, (2,))
    a = Action(do, undo)
    assert a.do() == 1
    assert a.undo() == 2

    g = lambda : 1
    do = (g, ())
    undo = (g, ())
    a = Action(do, undo)
    assert a.do() == 1
    assert a.undo() == 1

def testHistory():
    history = History()
    f = lambda x: x
    do = (f, (1,))
    undo = (f, (2,))
    action = Action(do, undo)
    history.push(action)
    assert history.undo() == 2
    assert history.undo() == None
    assert history.redo() == 1
    assert history.redo() == None
    assert history.undo() == 2
    history.push(action)
    history.push(action)
    assert history.undo() == 2
    assert history.undo() == 2
    assert history.redo() == 1
    assert history.redo() == 1
    assert history.redo() == None

def testSound():
    from copy import copy
    snd = Sound()

    # synthesize a sine wave
    from math import sin
    SR = 44100
    f0 = 440
    time = 5
    sine = [sin(2 * 3.14 * f0/SR * x) for x in range(time * SR)]
    start, end = 2*SR, 4*SR
    sine2 = copy(sine)
    snd._data = copy(sine)
    del sine2[start:end]
    snd.cut(start, end)
    assert snd._data.tolist() == sine2

    snd.history.undo()
    assert snd._data.tolist() == sine
    snd.history.undo()
    assert snd._data.tolist() == sine
    snd.history.redo()
    assert snd._data.tolist() == sine2

    clip = snd.copy(start, end)
    snd.paste(0, clip)
    assert snd._data.tolist() == sine2[start:end] + sine2
    snd.history.undo()
    assert snd._data.tolist() == sine2
    snd.history.redo()
    assert snd._data.tolist() == sine2[start:end] + sine2

    # test with a mono file
    snd = Sound("sounds/test1.wav")
    assert snd._data != []
    start = 4444
    end = 55555
    data = snd._data.tolist()
    data2 = snd._data.tolist()
    del data2[start:end]
    snd.cut(start, end)
    assert snd._data.tolist() == data2
    snd.history.undo()
    assert snd._data.tolist() == data
    snd.history.undo()
    assert snd._data.tolist() == data
    snd.history.redo()
    assert snd._data.tolist() == data2
    clip = snd.copy(start, end)
    snd.paste(0, clip)
    assert snd._data.tolist() == data2[start:end] + data2
    snd.history.undo()
    assert snd._data.tolist() == data2
    snd.paste(0, clip)
    assert snd._data.tolist() == data2[start:end] + data2

    # test with a stereo file
    snd = Sound("sounds/test2.wav")
    assert snd._data.tolist() != []
    start = 4444
    end = 55555
    data = copy(snd._data.tolist())
    data2 = copy(snd._data.tolist())
    del data2[start:end]
    snd.cut(start, end)
    assert snd._data.tolist() == data2
    snd.history.undo()
    assert snd._data.tolist() == data
    snd.history.undo()
    assert snd._data.tolist() == data
    snd.history.redo()
    assert snd._data.tolist() == data2
    clip = snd.copy(start, end)
    snd.paste(0, clip)
    assert snd._data.tolist() == data2[start:end] + data2
    snd.history.undo()
    assert snd._data.tolist() == data2
    snd.paste(0, clip)
    assert snd._data.tolist() == data2[start:end] + data2

if __name__ == '__main__':
    testAction()
    testSound()
    testHistory()
<|endoftext|>