<commit_before>#!/usr/bin/env python
import os
from spa_sequence.spa_sequence import net, pThal

import pygtk
pygtk.require('2.0')
import gtk
import cairo
import math

import view.components.spectrogram as spectrogram
#import view.components.input_panel as Input_Panel
from view.components.input_panel import Input_Panel
from view.components.controller_panel import Controller_Panel
from view.components.menu_bar import Menu_Bar
import simulator
import simulator.watchers
from old_plots.xy_plot import XY_Plot
from old_plots.voltage_grid import Voltage_Grid_Plot

from matplotlib.backends.backend_gtkcairo import FigureCanvasGTKCairo as FigureCanvas

class MainFrame:
    def __init__(self):

        self.vbox = gtk.VBox(False, 0)
        self.playing = False
        self.press = None
        self.resize = False
        self.resize_info = None

        self.sim = simulator.Simulator(net, net.dt)
        self.sim.add_watcher(simulator.watchers.LFPSpectrogramWatcher())
        self.sim.add_watcher(simulator.watchers.XYWatcher())
        self.sim.add_watcher(simulator.watchers.Voltage_Grid_Watcher())
        self.sim.watcher_manager.add_object("pThal", pThal)
        self.spectrogram = None

        self.all_plots = []
        self.all_canvas = []

        net.run(0.001) #run for one timestep
        self.sim.tick()
        self.sim.tick()

        for name, type, data in [("pThal", "LFP Spectrogram", None)]:
            if name in self.sim.watcher_manager.objects.keys():
                for (t, view_class, args) in self.sim.watcher_manager.list_watcher_views(name):
                    if t == type:
                        component = view_class(self.sim, name, **args)
                        # we know we only have the spectrogram in our example
                        self.spectrogram = component
                    elif (t == "XY"):
                        self.xy_plot = view_class(self.sim, name, **args)
                    elif (t == "Voltage Grid"):
                        self.voltage_grid = view_class(self.sim, name, **args)

        #TODO(amtinits): this should go in a super-class for all plots
        def button_press(widget, event, canvas):
            if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
                export_pdf_item = gtk.MenuItem("Export to PDF")
                export_pdf_item.connect("activate", self.on_export_pdf, canvas)
                export_pdf_item.show()
                context_menu = gtk.Menu()
                context_menu.append(export_pdf_item)
                context_menu.popup(None, None, None, event.button, event.time)
                return True
            return False

        self.spec_canvas = FigureCanvas(self.spectrogram.get_figure())
        self.spec_canvas.connect("event", button_press, self.spec_canvas)
        self.all_plots.append(self.spectrogram)
        self.all_canvas.append(self.spec_canvas)

        self.xy_canvas = FigureCanvas(self.xy_plot.get_figure())
        self.xy_canvas.connect("event", button_press, self.xy_canvas)
        self.all_plots.append(self.xy_plot)
        self.all_canvas.append(self.xy_canvas)

        self.vg_canvas = FigureCanvas(self.voltage_grid.get_figure())
        self.vg_canvas.connect("event", button_press, self.vg_canvas)
        self.all_plots.append(self.voltage_grid)
        self.all_canvas.append(self.vg_canvas)

        map(lambda x:x.mpl_connect('figure_enter_event', self.enter_figure), self.all_canvas)
        map(lambda x:x.mpl_connect('figure_leave_event', self.leave_figure), self.all_canvas)
        map(lambda x:x.mpl_connect('button_press_event', self.mouse_on_press), self.all_canvas)
        map(lambda x:x.mpl_connect('button_release_event', self.mouse_on_release), self.all_canvas)
        map(lambda x:x.mpl_connect('motion_notify_event', self.mouse_on_motion), self.all_canvas)

        # create a new window
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_size_request(200, 100)
        self.window.set_title("Nengo Python Visualizer")
        self.window.connect("delete_event", lambda w,e: gtk.main_quit())

        self.input_panel = Input_Panel(self)
        self.controller_panel = Controller_Panel(self)
        self.menu_bar = Menu_Bar(self)

        self.canvas_layout = gtk.Layout(None, None)
        self.canvas_layout.set_size(600, 600)

        figure = self.spectrogram.get_figure()

        # Used to control framerate for redrawing graph components
        self.sim_rate = 6 # rate at which we call sim.tick()
        self.framerate = 2
        self.next_gcomponent_redraw = 0

        self.canvas = FigureCanvas(figure)  # a gtk.DrawingArea
        self.timer = self.canvas.new_timer(interval=1000/self.sim_rate)
        self.timer.add_callback(self.tick)

        self.vbox.pack_start(self.menu_bar, False, False, 0)
        self.vbox.pack_start(self.controller_panel, False, False, 0)
        self.vbox.pack_start(self.canvas_layout, True, True, 0)
        self.window.add(self.vbox)

        self.menu_bar.show()
        self.controller_panel.show()
        self.spec_canvas.show()
        self.canvas_layout.show()
        self.vbox.show()

        self.window.set_size_request(800, 600)
        self.window.show()
        self.window.show_all()

        self.menu_bar.spectrogram_menu_item.set_active(True)

    def toggle_resize(self, widget):
        if (widget.get_active()):
            self.resize = True
        else:
            self.resize = False

    def mouse_on_press(self, event):
        canvas = event.canvas
        x0 = self.canvas_layout.child_get_property(canvas, "x")
        y0 = self.canvas_layout.child_get_property(canvas, "y")
        widget_x, widget_y = self.canvas_layout.get_pointer()
        self.press = x0, y0, widget_x, widget_y

    def mouse_on_motion(self, event):
        if self.press is None: return

        x0, y0, xpress, ypress = self.press
        owidth, oheight = event.canvas.get_width_height()

        canvas_layout_x, canvas_layout_y = self.canvas_layout.get_pointer()

        if (self.resize):
            if (self.resize_info == None):
                self.resize_info = xpress, ypress
            old_x, old_y = self.resize_info
            old_y = oheight - old_y
            o_mag = self.magnitude(old_x, old_y)

            new_mag = self.magnitude(canvas_layout_x, canvas_layout_y)
            self.resize_info = canvas_layout_x, canvas_layout_y
            scale = new_mag / o_mag
            scale = scale * scale
            new_width = int(owidth * scale)
            new_height = int(oheight * scale)
            event.canvas.set_size_request(new_width, new_height)
        else:
            # calc dx = currx - pressx
            widget_x, widget_y = self.canvas_layout.get_pointer()
            self.press = x0, y0, canvas_layout_x, canvas_layout_y
            dx = canvas_layout_x - xpress
            dy = canvas_layout_y - ypress
            new_x = int(round(x0 + dx))
            new_y = int(round(y0 + dy))
            self.canvas_layout.move(event.canvas, new_x, new_y)
            self.press = new_x, new_y, canvas_layout_x, canvas_layout_y

    def magnitude(self, x, y):
        sq1 = x * x
        sq2 = y * y
        return math.sqrt(sq1 + sq2)

    def mouse_on_release(self, event):
        self.press = None
        event.canvas.draw()

    def leave_figure(self, event):
        event.canvas.figure.patch.set_facecolor('white')
        event.canvas.draw()

    def enter_figure(self, event):
        event.canvas.figure.patch.set_facecolor('grey')
        event.canvas.draw()

    def hscale_change(self, range, scroll, value):
        self.sim.current_tick = value
        self.update_canvas()

    def tick(self):
        self.sim.tick()

        self.controller_panel.update_slider(self.sim.min_tick, self.sim.max_tick,
                                            self.sim.current_tick, self.sim.dt)

        if (self.next_gcomponent_redraw == 0):
            self.update_canvas()
            self.next_gcomponent_redraw = self.sim_rate/self.framerate
        else:
            self.next_gcomponent_redraw -= 1

    def update_canvas(self):

        if (self.xy_canvas.get_visible()):
            self.xy_plot.tick()
            self.xy_canvas.draw()
        if (self.vg_canvas.get_visible()):
            self.voltage_grid.tick()
            self.vg_canvas.draw()
        #self.i=(self.i+1) % 25
        if (self.spec_canvas.get_visible()):
            self.spectrogram.tick()
            self.spec_canvas.draw()

    #Controller code for controller_panel
    def format_slider_value(self, scale, value):
        return str(value * self.sim.dt)

    def play_pause_button(self, widget):
        if (self.playing == True):
            self.timer.stop()
            self.playing = False
            self.controller_panel.toggle_play(self.playing)
        else:
            self.timer.start()
            self.playing = True
            self.controller_panel.toggle_play(self.playing)

    def reset_button(self, widget):
        self.timer.stop()
        self.playing = False
        self.controller_panel.toggle_play(self.playing)
        self.sim.reset()
        self.jump_to(widget, self.sim.min_tick)
        self.clear_all_graphs()

    def jump_to_front(self, widget):
        self.jump_to(widget, self.sim.min_tick)

    def jump_to(self, widget, value):
        self.playing = True
        self.play_pause_button(widget)
        self.sim.current_tick = value
        self.controller_panel.set_slider(self.sim.current_tick)
        self.update_canvas()

    def jump_to_end(self, widget):
        self.jump_to(widget, self.sim.max_tick)

    def button_press(self, widget, event):
        if event.type == gtk.gdk.BUTTON_PRESS:
            widget.popup(None, None, None, event.button, event.time)
            # Tell calling code that we have handled this event the buck
            # stops here.
            return True
        # Tell calling code that we have not handled this event pass it on.
        return False

    # Print a string when a menu item is selected
    def menuitem_response(self, widget, string):
        print "%s" % string

    def toggle_plot(self, widget, canvas):
        if (widget.get_active()):
            canvas.set_visible(True)
            canvas.set_size_request(300, 300)
            canvas.show()
            self.canvas_layout.put(canvas, 0, 0)
        else:
            canvas.set_visible(False)
            self.canvas_layout.remove(canvas)

    def toggle_panel(self, widget, panel):
        if (widget.get_active()):
            panel.set_visible(True)
            self.control_panel.add(panel)
        else:
            panel.set_visible(False)
            self.control_panel.remove(panel)

    def clear_all_graphs(self):
        map(lambda x:x.clear(), self.all_plots)

    def repaint_all_canvas(self):
        map(lambda x:x.draw(), self.all_canvas)

    def on_export_pdf(self, widget, canvas=None):
        filename = self.file_browse(gtk.FILE_CHOOSER_ACTION_SAVE, "screenshot.pdf")
        if not filename:
            return
        with open(filename, "wb") as f:
            if canvas:
                canvas.print_pdf(f)
            else:
                cr = cairo.Context(cairo.PDFSurface(f, *self.window.get_size()))
                cr.set_source_surface(self.window.window.cairo_create().get_target())
                cr.set_operator(cairo.OPERATOR_SOURCE)
                cr.paint()
                cr.show_page()
                cr.get_target().finish()

    def file_browse(self, action, name="", ext="", ext_name=""):
        if (action == gtk.FILE_CHOOSER_ACTION_OPEN):
            buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)
        else:
            buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)
        dialog = gtk.FileChooserDialog(title="Select File", action=action, buttons=buttons)
        dialog.set_do_overwrite_confirmation(True)
        dialog.set_current_folder(os.getcwd())
        dialog.set_current_name(name)

        if ext:
            filt = gtk.FileFilter()
            filt.set_name(ext_name if ext_name else ext)
            filt.add_pattern("*." + ext)
            dialog.add_filter(filt)

        filt = gtk.FileFilter()
        filt.set_name("All files")
        filt.add_pattern("*")
        dialog.add_filter(filt)

        result = ""
        if dialog.run() == gtk.RESPONSE_OK:
            result = dialog.get_filename()
        dialog.destroy()
        return result

if __name__ == "__main__":
    MainFrame()
    gtk.main()
<commit_msg>Make canvas background white<commit_after>#!/usr/bin/env python
import os
from spa_sequence.spa_sequence import net, pThal

import pygtk
pygtk.require('2.0')
import gtk
import cairo
import math

import view.components.spectrogram as spectrogram
#import view.components.input_panel as Input_Panel
from view.components.input_panel import Input_Panel
from view.components.controller_panel import Controller_Panel
from view.components.menu_bar import Menu_Bar
import simulator
import simulator.watchers
from old_plots.xy_plot import XY_Plot
from old_plots.voltage_grid import Voltage_Grid_Plot

from matplotlib.backends.backend_gtkcairo import FigureCanvasGTKCairo as FigureCanvas

class MainFrame:
    def __init__(self):

        self.vbox = gtk.VBox(False, 0)
        self.playing = False
        self.press = None
        self.resize = False
        self.resize_info = None

        self.sim = simulator.Simulator(net, net.dt)
        self.sim.add_watcher(simulator.watchers.LFPSpectrogramWatcher())
        self.sim.add_watcher(simulator.watchers.XYWatcher())
        self.sim.add_watcher(simulator.watchers.Voltage_Grid_Watcher())
        self.sim.watcher_manager.add_object("pThal", pThal)
        self.spectrogram = None

        self.all_plots = []
        self.all_canvas = []

        net.run(0.001) #run for one timestep
        self.sim.tick()
        self.sim.tick()

        for name, type, data in [("pThal", "LFP Spectrogram", None)]:
            if name in self.sim.watcher_manager.objects.keys():
                for (t, view_class, args) in self.sim.watcher_manager.list_watcher_views(name):
                    if t == type:
                        component = view_class(self.sim, name, **args)
                        # we know we only have the spectrogram in our example
                        self.spectrogram = component
                    elif (t == "XY"):
                        self.xy_plot = view_class(self.sim, name, **args)
                    elif (t == "Voltage Grid"):
                        self.voltage_grid = view_class(self.sim, name, **args)

        #TODO(amtinits): this should go in a super-class for all plots
        def button_press(widget, event, canvas):
            if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
                export_pdf_item = gtk.MenuItem("Export to PDF")
                export_pdf_item.connect("activate", self.on_export_pdf, canvas)
                export_pdf_item.show()
                context_menu = gtk.Menu()
                context_menu.append(export_pdf_item)
                context_menu.popup(None, None, None, event.button, event.time)
                return True
            return False

        self.spec_canvas = FigureCanvas(self.spectrogram.get_figure())
        self.spec_canvas.connect("event", button_press, self.spec_canvas)
        self.all_plots.append(self.spectrogram)
        self.all_canvas.append(self.spec_canvas)

        self.xy_canvas = FigureCanvas(self.xy_plot.get_figure())
        self.xy_canvas.connect("event", button_press, self.xy_canvas)
        self.all_plots.append(self.xy_plot)
        self.all_canvas.append(self.xy_canvas)

        self.vg_canvas = FigureCanvas(self.voltage_grid.get_figure())
        self.vg_canvas.connect("event", button_press, self.vg_canvas)
        self.all_plots.append(self.voltage_grid)
        self.all_canvas.append(self.vg_canvas)

        map(lambda x:x.mpl_connect('figure_enter_event', self.enter_figure), self.all_canvas)
        map(lambda x:x.mpl_connect('figure_leave_event', self.leave_figure), self.all_canvas)
        map(lambda x:x.mpl_connect('button_press_event', self.mouse_on_press), self.all_canvas)
        map(lambda x:x.mpl_connect('button_release_event', self.mouse_on_release), self.all_canvas)
        map(lambda x:x.mpl_connect('motion_notify_event', self.mouse_on_motion), self.all_canvas)

        # create a new window
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_size_request(200, 100)
        self.window.set_title("Nengo Python Visualizer")
        self.window.connect("delete_event", lambda w,e: gtk.main_quit())

        self.input_panel = Input_Panel(self)
        self.controller_panel = Controller_Panel(self)
        self.menu_bar = Menu_Bar(self)

        self.canvas_layout = gtk.Layout(None, None)
        self.canvas_layout.set_size(600, 600)
        self.canvas_layout.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#ffffff"))

        figure = self.spectrogram.get_figure()

        # Used to control framerate for redrawing graph components
        self.sim_rate = 6 # rate at which we call sim.tick()
        self.framerate = 2
        self.next_gcomponent_redraw = 0

        self.canvas = FigureCanvas(figure)  # a gtk.DrawingArea
        self.timer = self.canvas.new_timer(interval=1000/self.sim_rate)
        self.timer.add_callback(self.tick)

        self.vbox.pack_start(self.menu_bar, False, False, 0)
        self.vbox.pack_start(self.controller_panel, False, False, 0)
        self.vbox.pack_start(self.canvas_layout, True, True, 0)
        self.window.add(self.vbox)

        self.menu_bar.show()
        self.controller_panel.show()
        self.spec_canvas.show()
        self.canvas_layout.show()
        self.vbox.show()

        self.window.set_size_request(800, 600)
        self.window.show()
        self.window.show_all()

        self.menu_bar.spectrogram_menu_item.set_active(True)

    def toggle_resize(self, widget):
        if (widget.get_active()):
            self.resize = True
        else:
            self.resize = False

    def mouse_on_press(self, event):
        canvas = event.canvas
        x0 = self.canvas_layout.child_get_property(canvas, "x")
        y0 = self.canvas_layout.child_get_property(canvas, "y")
        widget_x, widget_y = self.canvas_layout.get_pointer()
        self.press = x0, y0, widget_x, widget_y

    def mouse_on_motion(self, event):
        if self.press is None: return

        x0, y0, xpress, ypress = self.press
        owidth, oheight = event.canvas.get_width_height()

        canvas_layout_x, canvas_layout_y = self.canvas_layout.get_pointer()

        if (self.resize):
            if (self.resize_info == None):
                self.resize_info = xpress, ypress
            old_x, old_y = self.resize_info
            old_y = oheight - old_y
            o_mag = self.magnitude(old_x, old_y)

            new_mag = self.magnitude(canvas_layout_x, canvas_layout_y)
            self.resize_info = canvas_layout_x, canvas_layout_y
            scale = new_mag / o_mag
            scale = scale * scale
            new_width = int(owidth * scale)
            new_height = int(oheight * scale)
            event.canvas.set_size_request(new_width, new_height)
        else:
            # calc dx = currx - pressx
            widget_x, widget_y = self.canvas_layout.get_pointer()
            self.press = x0, y0, canvas_layout_x, canvas_layout_y
            dx = canvas_layout_x - xpress
            dy = canvas_layout_y - ypress
            new_x = int(round(x0 + dx))
            new_y = int(round(y0 + dy))
            self.canvas_layout.move(event.canvas, new_x, new_y)
            self.press = new_x, new_y, canvas_layout_x, canvas_layout_y

    def magnitude(self, x, y):
        sq1 = x * x
        sq2 = y * y
        return math.sqrt(sq1 + sq2)

    def mouse_on_release(self, event):
        self.press = None
        event.canvas.draw()

    def leave_figure(self, event):
        event.canvas.figure.patch.set_facecolor('white')
        event.canvas.draw()

    def enter_figure(self, event):
        event.canvas.figure.patch.set_facecolor('grey')
        event.canvas.draw()

    def hscale_change(self, range, scroll, value):
        self.sim.current_tick = value
        self.update_canvas()

    def tick(self):
        self.sim.tick()

        self.controller_panel.update_slider(self.sim.min_tick, self.sim.max_tick,
                                            self.sim.current_tick, self.sim.dt)

        if (self.next_gcomponent_redraw == 0):
            self.update_canvas()
            self.next_gcomponent_redraw = self.sim_rate/self.framerate
        else:
            self.next_gcomponent_redraw -= 1

    def update_canvas(self):

        if (self.xy_canvas.get_visible()):
            self.xy_plot.tick()
            self.xy_canvas.draw()
        if (self.vg_canvas.get_visible()):
            self.voltage_grid.tick()
            self.vg_canvas.draw()
        #self.i=(self.i+1) % 25
        if (self.spec_canvas.get_visible()):
            self.spectrogram.tick()
            self.spec_canvas.draw()

    #Controller code for controller_panel
    def format_slider_value(self, scale, value):
        return str(value * self.sim.dt)

    def play_pause_button(self, widget):
        if (self.playing == True):
            self.timer.stop()
            self.playing = False
            self.controller_panel.toggle_play(self.playing)
        else:
            self.timer.start()
            self.playing = True
            self.controller_panel.toggle_play(self.playing)

    def reset_button(self, widget):
        self.timer.stop()
        self.playing = False
        self.controller_panel.toggle_play(self.playing)
        self.sim.reset()
        self.jump_to(widget, self.sim.min_tick)
        self.clear_all_graphs()

    def jump_to_front(self, widget):
        self.jump_to(widget, self.sim.min_tick)

    def jump_to(self, widget, value):
        self.playing = True
        self.play_pause_button(widget)
        self.sim.current_tick = value
        self.controller_panel.set_slider(self.sim.current_tick)
        self.update_canvas()

    def jump_to_end(self, widget):
        self.jump_to(widget, self.sim.max_tick)

    def button_press(self, widget, event):
        if event.type == gtk.gdk.BUTTON_PRESS:
            widget.popup(None, None, None, event.button, event.time)
            # Tell calling code that we have handled this event the buck
            # stops here.
            return True
        # Tell calling code that we have not handled this event pass it on.
        return False

    # Print a string when a menu item is selected
    def menuitem_response(self, widget, string):
        print "%s" % string

    def toggle_plot(self, widget, canvas):
        if (widget.get_active()):
            canvas.set_visible(True)
            canvas.set_size_request(300, 300)
            canvas.show()
            self.canvas_layout.put(canvas, 0, 0)
        else:
            canvas.set_visible(False)
            self.canvas_layout.remove(canvas)

    def toggle_panel(self, widget, panel):
        if (widget.get_active()):
            panel.set_visible(True)
            self.control_panel.add(panel)
        else:
            panel.set_visible(False)
            self.control_panel.remove(panel)

    def clear_all_graphs(self):
        map(lambda x:x.clear(), self.all_plots)

    def repaint_all_canvas(self):
        map(lambda x:x.draw(), self.all_canvas)

    def on_export_pdf(self, widget, canvas=None):
        filename = self.file_browse(gtk.FILE_CHOOSER_ACTION_SAVE, "screenshot.pdf")
        if not filename:
            return
        with open(filename, "wb") as f:
            if canvas:
                canvas.print_pdf(f)
            else:
                cr = cairo.Context(cairo.PDFSurface(f, *self.window.get_size()))
                cr.set_source_surface(self.window.window.cairo_create().get_target())
                cr.set_operator(cairo.OPERATOR_SOURCE)
                cr.paint()
                cr.show_page()
                cr.get_target().finish()

    def file_browse(self, action, name="", ext="", ext_name=""):
        if (action == gtk.FILE_CHOOSER_ACTION_OPEN):
            buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)
        else:
            buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)
        dialog = gtk.FileChooserDialog(title="Select File", action=action, buttons=buttons)
        dialog.set_do_overwrite_confirmation(True)
        dialog.set_current_folder(os.getcwd())
        dialog.set_current_name(name)

        if ext:
            filt = gtk.FileFilter()
            filt.set_name(ext_name if ext_name else ext)
            filt.add_pattern("*." + ext)
            dialog.add_filter(filt)

        filt = gtk.FileFilter()
        filt.set_name("All files")
        filt.add_pattern("*")
        dialog.add_filter(filt)

        result = ""
        if dialog.run() == gtk.RESPONSE_OK:
            result = dialog.get_filename()
        dialog.destroy()
        return result

if __name__ == "__main__":
    MainFrame()
    gtk.main()
<|endoftext|>


<commit_before>import pandas as pd
import numpy as np
import emcee
import warnings
from functools import wraps

class BayesianSampler(object):
    """A sampling class to estimate the uncertainties in an epistasis model's
    coefficients using a Bayesian approach. This object samples from
    the experimental uncertainty in the phenotypes to estimate confidence
    intervals for the coefficients in an epistasis model according to Bayes
    Theorem:

    .. math::
        P(H|E) = \\frac{ P(E|H) \cdot P(H) }{ P(E) }

    This reads: "the probability of epistasis model :math:`H` given the data
    :math:`E` is equal to the probability of the data given the model times the
    probability of the model."

    Parameters
    ----------
    model :
        Epistasis model to run a bootstrap calculation.
    """

    def __init__(self, model, lnprior=None):
        # Get needed features from ML model.
        self.model = model
        self.lnlikelihood = model.lnlikelihood
        self.ml_thetas = self.model.thetas

        # Set the log-prior function
        if lnprior is not None:
            self.lnprior = lnprior

        # Prepare emcee sampler
        # Get dimensions of the sampler (number of walkers, number of coefs to
        # sample)
        self.ndim = len(self.ml_thetas)
        self.nwalkers = 2 * self.ndim

        # Construct sampler
        self.sampler_engine = emcee.EnsembleSampler(
            self.nwalkers, self.ndim, self.lnprob, args=(self.lnlikelihood,))

    @staticmethod
    def lnprior(thetas):
        """Prior probability for the given set of model parameters."""
        return 0.0

    @staticmethod
    def lnprob(thetas, lnlike):
        """The posterior probability of a given set of model parameters and
        likelihood function."""
        lp = BayesianSampler.lnprior(thetas)
        if not np.isfinite(lp):
            return -np.inf
        return lp + lnlike(thetas=thetas)

    def get_initial_walkers(self, relative_widths=1e-2):
        """Place the walkers in Gaussian balls in parameter space around
        the ML values for each coefficient.
        """
        middle_positions = np.array(self.ml_thetas)
        # Construct walkers for each coefficient
        deviations = np.random.randn(self.nwalkers, self.ndim)

        # Scale deviations appropriately for coefficient magnitude.
        scales = (relative_widths * middle_positions)

        # Scale deviations
        rel_deviations = np.multiply(deviations, scales)

        # Return walker positions
        walker_positions = middle_positions + rel_deviations
        return walker_positions

    def sample(self, n_steps=100, n_burn=0, previous_state=None):
        """Sample the likelihood of the model by walking n_steps with each
        walker."""
        # Suppress warnings that occur when sampling the model.
        warnings.simplefilter("ignore", RuntimeWarning)

        # Check if a previous run was given
        if previous_state is None:
            # Get initialize positions
            pos = self.get_initial_walkers()

            # Run the MCMC walks, burning these states to equilibrate.
            if n_burn != 0:
                pos, lnprob, rstate = self.sampler_engine.run_mcmc(
                    pos0=pos, N=n_burn, storechain=False)
            else:
                lnprob, rstate = None, None
        else:
            # Get previous state.
            pos = previous_state['pos']
            lnprob = previous_state['lnprob']
            rstate = previous_state['rstate']

        # Run sampler from previous position
        pos, lnprob, rstate = self.sampler_engine.run_mcmc(pos0=pos,
                                                           N=n_steps,
                                                           rstate0=rstate,
                                                           lnprob0=lnprob,
                                                           storechain=True)

        # Store previous run in a dictionary
        previous_state = {'pos': pos, 'lnprob': lnprob, 'rstate': rstate}
        return self.sampler_engine.flatchain, previous_state
<commit_msg>Fixed minor bug<commit_after>import pandas as pd
import numpy as np
import emcee
import warnings
from functools import wraps

class BayesianSampler(object):
    """A sampling class to estimate the uncertainties in an epistasis model's
    coefficients using a Bayesian approach. This object samples from
    the experimental uncertainty in the phenotypes to estimate confidence
    intervals for the coefficients in an epistasis model according to Bayes
    Theorem:

    .. math::
        P(H|E) = \\frac{ P(E|H) \cdot P(H) }{ P(E) }

    This reads: "the probability of epistasis model :math:`H` given the data
    :math:`E` is equal to the probability of the data given the model times the
    probability of the model."

    Parameters
    ----------
    model :
        Epistasis model to run a bootstrap calculation.
    """

    def __init__(self, model, lnprior=None):
        # Get needed features from ML model.
        self.model = model
        self.lnlikelihood = model.lnlikelihood
        self.ml_thetas = self.model.thetas

        # Set the log-prior function
        if lnprior is not None:
            self.lnprior = lnprior

        # Prepare emcee sampler
        # Get dimensions of the sampler (number of walkers, number of coefs to
        # sample)
        self.ndim = len(self.ml_thetas)
        self.nwalkers = 2 * self.ndim

        # Construct sampler
        self.sampler_engine = emcee.EnsembleSampler(
            self.nwalkers, self.ndim, self.lnprob, args=(self.lnlikelihood,))

    @staticmethod
    def lnprior(thetas):
        """Prior probability for the given set of model parameters."""
        return 0.0

    @staticmethod
    def lnprob(thetas, lnlike):
        """The posterior probability of a given set of model parameters and
        likelihood function."""
        lp = BayesianSampler.lnprior(thetas)
        if not np.isfinite(lp):
            return -np.inf
        return lp + lnlike(thetas=thetas)

    def get_initial_walkers(self, relative_widths=1e-2):
        """Place the walkers in Gaussian balls in parameter space around
        the ML values for each coefficient.
        """
        middle_positions = np.array(self.ml_thetas)
        # Construct walkers for each coefficient
        deviations = np.random.randn(self.nwalkers, self.ndim)

        # Scale deviations appropriately for coefficient magnitude.
        scales = (relative_widths * middle_positions)

        # Scale deviations
        rel_deviations = np.multiply(deviations, scales)

        # Return walker positions
        walker_positions = middle_positions + rel_deviations
        return walker_positions

    def sample(self, n_steps=100, n_burn=0, previous_state=None):
        """Sample the likelihood of the model by walking n_steps with each
        walker."""
        # Suppress warnings that occur when sampling the model.
        warnings.simplefilter("ignore", RuntimeWarning)

        # Check if a previous run was given
        if previous_state is None:
            # Get initialize positions
            pos = self.get_initial_walkers()

            # Run the MCMC walks, burning these states to equilibrate.
            if n_burn != 0:
                pos, lnprob, rstate = self.sampler_engine.run_mcmc(
                    pos0=pos, N=n_burn, storechain=False)
            else:
                lnprob, rstate = None, None
        else:
            # Get previous state.
            pos = previous_state['pos']
            lnprob = previous_state['lnprob']
            rstate = previous_state['rstate']

        # Run sampler from previous position
        pos, lnprob, rstate = self.sampler_engine.run_mcmc(initial_state=pos,
                                                           nsteps=n_steps,
                                                           rstate0=rstate,
                                                           log_prob0=lnprob,
                                                           store=True,
                                                           progress=True)

        # Store previous run in a dictionary
        previous_state = {'pos': pos, 'lnprob': lnprob, 'rstate': rstate}
        return self.sampler_engine.flatchain, previous_state
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This script is intended for use debugging parse issues on replays.

    sc2parse [FILES..]

Recursively parses all the files. When exceptions are thrown it catches them
and attempts to print out any information that might be needed for debug. If
information you need isn't available feel free to add new handlers or add to
existing exception handlers.

Also sets logging to INFO so that missing unit type and ability type messages
are caught and reported. At some point these things should be moved to WARN.

If there are parse exceptions, this script should be run to generate an info
for the ticket filed.
"""

import sys
import sc2reader
import traceback

sc2reader.log_utils.log_to_console('INFO')

def main():
    for argument in sys.argv[1:]:
        for path in sc2reader.utils.get_files(argument,extension='SC2Replay'):
            try:
                replay = sc2reader.load_replay(path, debug=True, verbose=True)
            except sc2reader.exceptions.ReadError as e:
                print
                print path
                print '{build} - {real_type} on {map_name} - Played {start_time}'.format(**e.replay.__dict__)
                print '[ERROR]', e.message
                for event in e.game_events[-5:]:
                    print '{0} - {1}'.format(hex(event.type),event.bytes.encode('hex'))
                e.buffer.seek(e.location)
                print e.buffer.peek(50).encode('hex')
                print
            except Exception as e:
                print
                print path
                replay = sc2reader.load_replay(path, debug=True, load_level=1)
                print '{build} - {real_type} on {map_name} - Played {start_time}'.format(**replay.__dict__)
                print '[ERROR]', e.message
                for pid, attributes in replay.attributes.items():
                    print pid, attributes
                for pid, info in enumerate(replay.raw_data['replay.details'].players):
                    print pid, info
                print replay.raw_data['replay.initData'].player_names
                traceback.print_exc()
                print

if __name__ == '__main__':
    main()<commit_msg>optionally parse only one replay per release_string for quick regression testing. if load_level 1 dies, fall back to load_level 0 rather than ending the run completely<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This script is intended for use debugging parse issues on replays.

    sc2parse [FILES..]

Recursively parses all the files. When exceptions are thrown it catches them
and attempts to print out any information that might be needed for debug. If
information you need isn't available feel free to add new handlers or add to
existing exception handlers.

Also sets logging to INFO so that missing unit type and ability type messages
are caught and reported. At some point these things should be moved to WARN.

If there are parse exceptions, this script should be run to generate an info
for the ticket filed.
"""

import argparse
import sys
import sc2reader
import traceback

sc2reader.log_utils.log_to_console('INFO')

def main():
    parser = argparse.ArgumentParser(description="Recursively parses replay files, inteded for debugging parse issues.")
    parser.add_argument('--one_each', help="Attempt to parse only one replay for each release_string", action="store_true")
    parser.add_argument('folders', metavar='folder', type=str, nargs='+', help="Path to a folder")
    args = parser.parse_args()

    releases_parsed = set()
    for folder in args.folders:
        print "dealing with {}".format(folder)
        for path in sc2reader.utils.get_files(folder,extension='SC2Replay'):
            try:
                rs = sc2reader.load_replay(path, load_level=0).release_string
                already_did = rs in releases_parsed
                releases_parsed.add(rs)
                if not args.one_each or not already_did:
                    replay = sc2reader.load_replay(path, debug=True, verbose=True)
            except sc2reader.exceptions.ReadError as e:
                print
                print path
                print '{build} - {real_type} on {map_name} - Played {start_time}'.format(**e.replay.__dict__)
                print '[ERROR]', e.message
                for event in e.game_events[-5:]:
                    print '{0} - {1}'.format(hex(event.type),event.bytes.encode('hex'))
                e.buffer.seek(e.location)
                print e.buffer.peek(50).encode('hex')
                print
            except Exception as e:
                print
                print path
                try:
                    replay = sc2reader.load_replay(path, debug=True, load_level=1)
                    print '{build} - {real_type} on {map_name} - Played {start_time}'.format(**replay.__dict__)
                    print '[ERROR]', e.message
                    for pid, attributes in replay.attributes.items():
                        print pid, attributes
                    for pid, info in enumerate(replay.raw_data['replay.details'].players):
                        print pid, info
                    print replay.raw_data['replay.initData'].player_names
                    traceback.print_exc()
                    print
                except Exception as e2:
                    replay = sc2reader.load_replay(path, debug=True, load_level=0)
                    print '[ERROR]', e.message
                    print '[ERROR]', e2.message
                    traceback.print_exc()
                    print

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


<commit_before>#!/usr/bin env python
# -*- coding: utf-8 -*-
"""Make some plots of the velocity widths from the cosmo runs"""

import matplotlib
matplotlib.use('PDF')

import matplotlib.pyplot as plt

import plot_spectra as ps
import vel_data
import os.path as path
import numpy as np
from save_figure import save_figure

base="/home/spb/scratch/Cosmo/"
outdir = base + "plots/checks/"
print "Plots at: ",outdir

def plot_vel_width_metcol(sim, snap, ff=False):
    """Load a simulation and plot its velocity width"""
    halo = "Cosmo"+str(sim)+"_V6"
    if ff:
        halo+="_512"
    #Load from a save file only
    hspec = ps.PlottingSpectra(snap, base+halo, None, None)
    hspec.plot_vel_width("Si", 2, met_cut = None)
    hspec.plot_vel_width("Si", 2, met_cut = 1e13, color="blue")
    vel_data.plot_prochaska_2008_data()
    save_figure(path.join(outdir,"cosmo"+str(ii)+"_low_metals_z"+str(snap)))
    plt.clf()
    (vbin, vels1) = hspec.vel_width_hist("Si", 2, met_cut = None)
    (vbin, vels2) = hspec.vel_width_hist("Si", 2, met_cut = 1e13)
    mm = np.min((np.size(vels2), np.size(vels1)))
    plt.semilogx(vbin[:mm], vels2[:mm]/vels1[:mm], color="black")
    save_figure(path.join(outdir,"cosmo"+str(ii)+"_low_metals_rel_z"+str(snap)))
    plt.clf()

def plot_vel_width_unres(sim, snap, ff=False):
    """Load a simulation and plot its velocity width"""
    halo = "Cosmo"+str(sim)+"_V6"
    if ff:
        halo+="_512"
    #Load from a save file only
    hspec = ps.PlottingSpectra(snap, base+halo, None, None)
    hspec.plot_vel_width("Si", 2, unres = None)
    hspec.plot_vel_width("Si", 2, unres=5, color="blue")
    vel_data.plot_prochaska_2008_data()
    save_figure(path.join(outdir,"cosmo"+str(ii)+"_unres_z"+str(snap)))
    plt.clf()
    (vbin, vels1) = hspec.vel_width_hist("Si", 2, unres = None)
    (vbin, vels2) = hspec.vel_width_hist("Si", 2, unres=5)
    mm = np.min((np.size(vels2), np.size(vels1)))
    plt.semilogx(vbin[:mm], vels2[:mm]/vels1[:mm], color="black")
    save_figure(path.join(outdir,"cosmo"+str(ii)+"_unres_rel_z"+str(snap)))
    plt.clf()

def plot_vel_width_DLA(sim, snap, ff=False):
    """Plot the effect of the HI cut"""
    halo = "Cosmo"+str(sim)+"_V6"
    if ff:
        halo+="_512"
    #Load from a save file only
    hspec = ps.PlottingSpectra(snap, base+halo, None, None)
    hspec.plot_vel_width("Si", 2, color="red", HI_cut = None)
    hspec.plot_vel_width("Si", 2, color="blue", HI_cut = 10**20.3)
    vel_data.plot_prochaska_2008_data()
    save_figure(path.join(outdir,"cosmo"+str(ii)+"_vel_DLA_z"+str(snap)))
    plt.clf()
    (vbin, vels1) = hspec.vel_width_hist("Si", 2, HI_cut = None)
    (vbin, vels2) = hspec.vel_width_hist("Si", 2, HI_cut = 10**20.3)
    mm = np.min((np.size(vels2), np.size(vels1)))
    plt.semilogx(vbin[:mm], vels2[:mm]/vels1[:mm], color="black")
    save_figure(path.join(outdir,"cosmo"+str(ii)+"_vel_DLA_rel_z"+str(snap)))
    plt.clf()

def test_spec_resolution():
    """Plot the velocity widths for different spectral resolutions"""
    #Do spectral resolution test
    halo = "Cosmo0_V6"
    #Higher resolution spectrum
    hspec = ps.PlottingSpectra(68, base+halo, None, None, savefile="spectra.hdf5")
    hspec.plot_vel_width("Si",2, color="red")
    hspec2 = ps.PlottingSpectra(68, base+halo, None, None, savefile="spectra4096.hdf5")
    hspec2.plot_vel_width("Si", 2, color="blue")
    vel_data.plot_prochaska_2008_data()
    plt.xlim(1, 1000)
    plt.ylim(1e-5, 2e-2)
    save_figure(path.join(outdir,"cosmo_vel_width_z3_spectra_pix"))
    plt.clf()

    metal_col_den = np.max(hspec.get_col_density("Si", 2),axis=1)
    vel= hspec.vel_width(hspec.metals[("Si",2)][3])
    plt.loglog(metal_col_den, vel, 'o')
    save_figure(path.join(outdir,"cosmo0_vel_col_spectra_pix_low"))
    plt.clf()

    metal_col_den = np.max(hspec2.get_col_density("Si", 2),axis=1)
    vel= hspec.vel_width(hspec2.metals[("Si",2)][3])
    plt.loglog(metal_col_den, vel, 'o')
    save_figure(path.join(outdir,"cosmo0_vel_col_spectra_pix"))
    plt.clf()

#test_spec_resolution()

for ii in (0,3):
    #Plot effect of ignoring low column density metals
    plot_vel_width_metcol(ii, 60)

for ii in (0,3):
    #Plot effect of HI cut
    plot_vel_width_DLA(ii,60)

for ii in (0,3):
    #Plot effect of HI cut
    plot_vel_width_unres(ii,60)
<commit_msg>Check effect of making Si track HI<commit_after>#!/usr/bin env python
# -*- coding: utf-8 -*-
"""Make some plots of the velocity widths from the cosmo runs"""

import matplotlib
matplotlib.use('PDF')

import matplotlib.pyplot as plt

import plot_spectra as ps
import vel_data
import os.path as path
import numpy as np
from save_figure import save_figure

base="/home/spb/scratch/Cosmo/"
outdir = base + "plots/checks/"
print "Plots at: ",outdir

def plot_vel_width_metcol(sim, snap, ff=False):
    """Load a simulation and plot its velocity width"""
    halo = "Cosmo"+str(sim)+"_V6"
    if ff:
        halo+="_512"
    #Load from a save file only
    hspec = ps.PlottingSpectra(snap, base+halo, None, None)
    hspec.plot_vel_width("Si", 2, met_cut = None)
    hspec.plot_vel_width("Si", 2, met_cut = 1e13, color="blue")
    vel_data.plot_prochaska_2008_data()
    save_figure(path.join(outdir,"cosmo"+str(sim)+"_low_metals_z"+str(snap)))
    plt.clf()
    (vbin, vels1) = hspec.vel_width_hist("Si", 2, met_cut = None)
    (vbin, vels2) = hspec.vel_width_hist("Si", 2, met_cut = 1e13)
    mm = np.min((np.size(vels2), np.size(vels1)))
    plt.semilogx(vbin[:mm], vels2[:mm]/vels1[:mm], color="black")
    save_figure(path.join(outdir,"cosmo"+str(sim)+"_low_metals_rel_z"+str(snap)))
    plt.clf()

def plot_vel_width_unres(sim, snap, ff=False):
    """Load a simulation and plot its velocity width"""
    halo = "Cosmo"+str(sim)+"_V6"
    if ff:
        halo+="_512"
    #Load from a save file only
    hspec = ps.PlottingSpectra(snap, base+halo, None, None)
    hspec.plot_vel_width("Si", 2, unres = None)
    hspec.plot_vel_width("Si", 2, unres=5, color="blue")
    vel_data.plot_prochaska_2008_data()
    save_figure(path.join(outdir,"cosmo"+str(sim)+"_unres_z"+str(snap)))
    plt.clf()
    (vbin, vels1) = hspec.vel_width_hist("Si", 2, unres = None)
    (vbin, vels2) = hspec.vel_width_hist("Si", 2, unres=5)
    mm = np.min((np.size(vels2), np.size(vels1)))
    plt.semilogx(vbin[:mm], vels2[:mm]/vels1[:mm], color="black")
    save_figure(path.join(outdir,"cosmo"+str(sim)+"_unres_rel_z"+str(snap)))
    plt.clf()

def plot_vel_width_SiII(sim, snap, ff=False):
    """
       Plot the change in velocity widths between the full calculation and
       setting n(Si+)/n(Si) = n(HI)/n(H)
    """
    halo = "Cosmo"+str(sim)+"_V6"
    if ff:
        halo+="_512"
    #Load from a save file only
    hspec = ps.PlotHaloSpectra(snap, base+halo)
    hspec.plot_vel_width("Si", 2)
    hspecSi = ps.PlotHaloSpectra(snap, base+halo,savefile="SiHI_spectra.hdf5")
    hspecSi.plot_vel_width("Si", 2, color="blue")
    vel_data.plot_prochaska_2008_data()
    save_figure(path.join(outdir,"cosmo"+str(sim)+"_SiHI_z"+str(snap)))
    plt.clf()
    (vbin, vels1) = hspec.vel_width_hist("Si", 2)
    (vbin, vels2) = hspecSi.vel_width_hist("Si", 2)
    mm = np.min((np.size(vels2), np.size(vels1)))
    plt.semilogx(vbin[:mm], vels2[:mm]/vels1[:mm], color="black")
    save_figure(path.join(outdir,"cosmo"+str(sim)+"_SiHI_rel_z"+str(snap)))
    plt.clf()

def plot_vel_width_DLA(sim, snap, ff=False):
    """Plot the effect of the HI cut"""
    halo = "Cosmo"+str(sim)+"_V6"
    if ff:
        halo+="_512"
    #Load from a save file only
    hspec = ps.PlottingSpectra(snap, base+halo, None, None)
    hspec.plot_vel_width("Si", 2, color="red", HI_cut = None)
    hspec.plot_vel_width("Si", 2, color="blue", HI_cut = 10**20.3)
    vel_data.plot_prochaska_2008_data()
    save_figure(path.join(outdir,"cosmo"+str(sim)+"_vel_DLA_z"+str(snap)))
    plt.clf()
    (vbin, vels1) = hspec.vel_width_hist("Si", 2, HI_cut = None)
    (vbin, vels2) = hspec.vel_width_hist("Si", 2, HI_cut = 10**20.3)
    mm = np.min((np.size(vels2), np.size(vels1)))
    plt.semilogx(vbin[:mm], vels2[:mm]/vels1[:mm], color="black")
    save_figure(path.join(outdir,"cosmo"+str(sim)+"_vel_DLA_rel_z"+str(snap)))
    plt.clf()

def test_spec_resolution():
    """Plot the velocity widths for different spectral resolutions"""
    #Do spectral resolution test
    halo = "Cosmo0_V6"
    #Higher resolution spectrum
    hspec = ps.PlottingSpectra(68, base+halo, None, None, savefile="spectra.hdf5")
    hspec.plot_vel_width("Si",2, color="red")
    hspec2 = ps.PlottingSpectra(68, base+halo, None, None, savefile="spectra4096.hdf5")
    hspec2.plot_vel_width("Si", 2, color="blue")
    vel_data.plot_prochaska_2008_data()
    plt.xlim(1, 1000)
    plt.ylim(1e-5, 2e-2)
    save_figure(path.join(outdir,"cosmo_vel_width_z3_spectra_pix"))
    plt.clf()

    metal_col_den = np.max(hspec.get_col_density("Si", 2),axis=1)
    vel= hspec.vel_width(hspec.metals[("Si",2)][3])
    plt.loglog(metal_col_den, vel, 'o')
    save_figure(path.join(outdir,"cosmo0_vel_col_spectra_pix_low"))
    plt.clf()

    metal_col_den = np.max(hspec2.get_col_density("Si", 2),axis=1)
    vel= hspec.vel_width(hspec2.metals[("Si",2)][3])
    plt.loglog(metal_col_den, vel, 'o')
    save_figure(path.join(outdir,"cosmo0_vel_col_spectra_pix"))
    plt.clf()

#test_spec_resolution()

plot_vel_width_SiII(0, 60)

for ii in (0,3):
    #Plot effect of ignoring low column density metals
    plot_vel_width_metcol(ii, 60)

for ii in (0,3):
    #Plot effect of HI cut
    plot_vel_width_DLA(ii,60)

for ii in (0,3):
    #Plot effect of HI cut
    plot_vel_width_unres(ii,60)
<|endoftext|>


<commit_before>#!/usr/bin/env python3
# imports go here
import itertools
import pandas as pd

import plotly.plotly as py
from plotly.graph_objs import *

#
# Free Coding session for 2015-05-25
# Written by Matt Warren
#

years = list(range(2015, 2045))

YEARS_TO_SIMULATE = 30
INFLATION_RATE = 0.02

KWH_PRICE = 0.10  # 2015 dollars

INSTALL_COST_PER_WATT = 3.00  # in 2015
INSTALL_COST_PER_WATT_2025 = 2.00

INSTALLS_IN_FIRST_YEAR = 200
AVG_INSTALL_SIZE_KW = 3

cost_per_watt = [INSTALL_COST_PER_WATT]
for i in range(YEARS_TO_SIMULATE):
    if i < 10:
        # linear interpolation
        cost = ((INSTALL_COST_PER_WATT_2025 - INSTALL_COST_PER_WATT) / 10) * i + INSTALL_COST_PER_WATT
    else:
        cost = cost_per_watt[i] * (1+INFLATION_RATE)
    cost_per_watt.append(cost)

data = zip(years, cost_per_watt)

df = pd.DataFrame(data=list(data), columns=['Year', 'Cost Per Watt'])

# extend the DataFrame with prices for electricity
def inflate(initial, inflation):
    current = initial
    while True:
        yield current
        current = current * (1+inflation)

price_over_time = list(itertools.islice(inflate(KWH_PRICE, INFLATION_RATE), 0, YEARS_TO_SIMULATE))
df['Price Per KWH'] = pd.Series(price_over_time, index=df.index)

sales_growth_per_year = [1, 0.9, 0.9, 0.9, 0.9, 0.8, 0.8, 0.8, 0.5, 0.5, 0.2] + ([0.01] * (YEARS_TO_SIMULATE-11))

installs_per_year = [INSTALLS_IN_FIRST_YEAR, ]
for i in range(YEARS_TO_SIMULATE-1):
    installs_per_year.append(installs_per_year[i]*(1+sales_growth_per_year[i]))
df['Installs'] = pd.Series(installs_per_year, index=df.index)
df['EOY net new capacity (KW)'] = pd.Series([i * AVG_INSTALL_SIZE_KW for i in installs_per_year], index=df.index)
df['EOY total capacity (KW)'] = pd.Series(list(itertools.accumulate([i * AVG_INSTALL_SIZE_KW for i in installs_per_year])), index=df.index)

#
# Electricty production
PEAK_EFFICIENCY = 0.66  # weather, obstructions, electrical overhead etc
EFFECTIVE_EFFICIENCY = 0.56  # avg % of peak - due to non-direct sunlight
DAYLIGHT_HOURS = 12.0

# avg_install_cost_per_house = INSTALL_COST_PER_WATT * avg_home_install_watts
annual_kwh_per_kw = EFFECTIVE_EFFICIENCY * DAYLIGHT_HOURS * PEAK_EFFICIENCY * 365
df['KWH generated'] = (df['EOY total capacity (KW)'] - (df['EOY net new capacity (KW)'] * 0.5)) * annual_kwh_per_kw

df['Revenue'] = df['KWH generated'] * df['Price Per KWH']

print(df)

line = Scatter(x=df['Year'], y=df['Cost Per Watt'])
line2 = Scatter(x=df['Year'], y=df['Price Per KWH'])
line3 = Scatter(x=df['Year'], y=df['Installs'])
line4 = Scatter(x=df['Year'], y=df['Revenue'])
data = Data([line, line2, line3, line4])
layout = Layout(
    title='Cost per Watt',
    xaxis=XAxis(
        title='Year',
        showgrid=False,
        zeroline=False
    ),
    yaxis=YAxis(
        title='Cost Per Watt',
        showline=False
    )
)
fig = Figure(data=data, layout=layout)
plot_url = py.plot(fig, filename='Cost Per watt')
<commit_msg>playing witih more numbers.<commit_after>#!/usr/bin/env python3
# imports go here
import itertools
import pandas as pd

import plotly.plotly as py
from plotly.graph_objs import *

#
# Free Coding session for 2015-05-25
# Written by Matt Warren
#

years = list(range(2015, 2045))

YEARS_TO_SIMULATE = 30
INFLATION_RATE = 0.02
INTEREST_RATE = 0.04

KWH_PRICE = 0.15  # 2015 dollars

INSTALL_COST_PER_WATT = 3.00  # in 2015
INSTALL_COST_PER_WATT_2025 = 2.00

INSTALLS_IN_FIRST_YEAR = 200
AVG_INSTALL_SIZE_KW = 3

cost_per_watt = [INSTALL_COST_PER_WATT]
for i in range(YEARS_TO_SIMULATE):
    if i < 10:
        # linear interpolation
        cost = ((INSTALL_COST_PER_WATT_2025 - INSTALL_COST_PER_WATT) / 10) * i + INSTALL_COST_PER_WATT
    else:
        cost = cost_per_watt[i] * (1+INFLATION_RATE)
    cost_per_watt.append(cost)

data = zip(years, cost_per_watt)

df = pd.DataFrame(data=list(data), columns=['Year', 'Cost Per Watt'])

# extend the DataFrame with prices for electricity
def inflate(initial, inflation):
    current = initial
    while True:
        yield current
        current = current * (1+inflation)

price_over_time = list(itertools.islice(inflate(KWH_PRICE, INFLATION_RATE), 0, YEARS_TO_SIMULATE))
df['Price Per KWH'] = pd.Series(price_over_time, index=df.index)

sales_growth_per_year = [1, 0.9, 0.9, 0.9, 0.9, 0.8, 0.8, 0.8, 0.5, 0.5, 0.2] + ([0.01] * (YEARS_TO_SIMULATE-11))

installs_per_year = [INSTALLS_IN_FIRST_YEAR, ]
for i in range(YEARS_TO_SIMULATE-1):
    installs_per_year.append(installs_per_year[i]*(1+sales_growth_per_year[i]))
df['Installs'] = pd.Series(installs_per_year, index=df.index)
df['EOY net new capacity (KW)'] = pd.Series([i * AVG_INSTALL_SIZE_KW for i in installs_per_year], index=df.index)
df['EOY total capacity (KW)'] = pd.Series(list(itertools.accumulate([i * AVG_INSTALL_SIZE_KW for i in installs_per_year])), index=df.index)
df['YOY growth'] = pd.Series(sales_growth_per_year, index=df.index)
#
# Electricty production
PEAK_EFFICIENCY = 0.66  # weather, obstructions, electrical overhead etc
EFFECTIVE_EFFICIENCY = 0.56  # avg % of peak - due to non-direct sunlight
DAYLIGHT_HOURS = 12.0

# avg_install_cost_per_house = INSTALL_COST_PER_WATT * avg_home_install_watts
annual_kwh_per_kw = EFFECTIVE_EFFICIENCY * DAYLIGHT_HOURS * PEAK_EFFICIENCY * 365
df['KWH generated'] = (df['EOY total capacity (KW)']) * annual_kwh_per_kw

df['Revenue'] = df['KWH generated'] * df['Price Per KWH']

df['Capital for installations'] = df['EOY net new capacity (KW)'] * df['Cost Per Watt'] * 1000

# fixed costs
# warehouse per city
# van/truck per install captial_requirements_per_year
df['warehouse costs'] = pd.Series(list(itertools.accumulate([100000] * YEARS_TO_SIMULATE)), index=df.index)
df['vehicles'] = pd.Series(list(itertools.islice(inflate(60000, INFLATION_RATE), 0, YEARS_TO_SIMULATE)), index=df.index)

salaries_per_year = [200000, ]
for i in range(YEARS_TO_SIMULATE-1):
    salaries_per_year.append(salaries_per_year[i]*(1+sales_growth_per_year[i]))

df['salaries'] = pd.Series(salaries_per_year, index=df.index)

# gas, insurance, tooling, computers, servers, hosting, electricity, development
df['gas'] = pd.Series(list(itertools.accumulate(itertools.islice(inflate(2000, INFLATION_RATE), 0, YEARS_TO_SIMULATE))), index=df.index)
# df['insurance']
df['tools'] = pd.Series(list(itertools.islice(inflate(50000, INFLATION_RATE), 0, YEARS_TO_SIMULATE)), index=df.index)
df['computers'] = pd.Series(list(itertools.islice(inflate(6000, INFLATION_RATE), 0, YEARS_TO_SIMULATE)), index=df.index)
df['hosting'] = pd.Series(list(itertools.islice(inflate(5000, INFLATION_RATE), 0, YEARS_TO_SIMULATE)), index=df.index)
df['electricity'] = pd.Series(list(itertools.islice(inflate(3000, INFLATION_RATE), 0, YEARS_TO_SIMULATE)), index=df.index)

df['capital required per year'] = df['Capital for installations'] + df['warehouse costs'] + df['vehicles'] + df['salaries'] + df['gas'] + df['tools'] + df['computers'] + df['hosting'] + df['electricity']

net_new_debt = []
prev_revenue = 0
accum_debt = 0
for i, capital in enumerate(df['capital required per year']):
    new_debt = capital + (accum_debt * INTEREST_RATE) - prev_revenue
    net_new_debt.append(new_debt)
    prev_revenue = df['Revenue'][i]
    accum_debt += new_debt

df['net new debt'] = pd.Series(net_new_debt, index=df.index)
# df['debt servicing'] =

df['accumulated debt'] = pd.Series(list(itertools.accumulate([i for i in df['net new debt']])), index=df.index)

print(df)

line = Scatter(x=df['Year'], y=df['Cost Per Watt'])
line2 = Scatter(x=df['Year'], y=df['Price Per KWH'])
line3 = Scatter(x=df['Year'], y=df['Installs'])
line4 = Scatter(x=df['Year'], y=df['Revenue'])
data = Data([line, line2, line3, line4])
layout = Layout(
    title='Cost per Watt',
    xaxis=XAxis(
        title='Year',
        showgrid=False,
        zeroline=False
    ),
    yaxis=YAxis(
        title='Cost Per Watt',
        showline=False
    )
)
fig = Figure(data=data, layout=layout)
plot_url = py.plot(fig, filename='Cost Per watt')
<|endoftext|>


<commit_before># -*- coding: utf8 -*-
# This file is part of PyBossa.
#
# Copyright (C) 2015 SF Isle of Man Limited
#
# PyBossa is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyBossa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with PyBossa.  If not, see <http://www.gnu.org/licenses/>.
"""
Enki module for analyzing the results of a PyBossa project.

This module exports:
    * Enki Class: to import an project, its tasks and task runs

"""
import pandas
import pbclient
import json
from exceptions import ProjectNotFound, ProjectError, \
    ProjectWithoutTasks, ProjectWithoutTaskRuns

class Enki(object):

    """General class for Enki."""

    def __init__(self, api_key, endpoint, project_short_name):
        """Initiate."""
        self.api_key = api_key
        self.endpoint = endpoint
        self.project = None
        self.pbclient = pbclient
        self.pbclient.set('api_key', self.api_key)
        self.pbclient.set('endpoint', self.endpoint)
        if self.project is None:
            self.project = self.get_project(project_short_name)

    def get_project(self, project_short_name):
        """Return project object."""
        project = self.pbclient.find_project(short_name=project_short_name)
        if (len(project) == 1):
            return project[0]
        else:
            raise ProjectNotFound(project_short_name)

    def explode_info(self, item):
        """Return the a dict of the object but with info field exploded."""
        tmp = item.__dict__['data']
        if type(item.info) == dict:
            keys = tmp['info'].keys()
            for k in keys:
                tmp[k] = tmp['info'][k]
        return tmp

    def get_tasks(self, task_id=None, state='completed', json_file=None):
        """Load all project Tasks."""
        if task_id:
            offset = 0
            limit = 1
        else:
            offset = 0
            limit = 100
        self.tasks = []
        if self.project and task_id:
            query = dict(project_id=self.project.id,
                         state=state,
                         id=task_id,
                         limit=limit,
                         offset=offset)
        elif self.project and task_id is None:
            query = dict(project_id=self.project.id,
                         state=state,
                         limit=limit,
                         offset=offset)
        else:
            raise ProjectError()

        tmp = self.pbclient.find_tasks(**query)
        if json_file:
            json_file_data = open(json_file).read()
            tmp_tasks = json.loads(json_file_data)
            for t in tmp_tasks:
                self.tasks.append(pbclient.Task(t))
        else:
            while(len(tmp) != 0):
                self.tasks += tmp
                offset += limit
                query['offset'] += limit
                tmp = self.pbclient.find_tasks(**query)

        # Create the data frame for tasks
        try:
            self.tasks[0]
            data = [self.explode_info(t) for t in self.tasks]
            index = [t.__dict__['data']['id'] for t in self.tasks]
            self.tasks_df = pandas.DataFrame(data, index)
        except:
            raise ProjectWithoutTasks

    def get_task_runs(self, json_file=None):
        """Load all project Task Runs from Tasks."""
        self.task_runs = {}
        self.task_runs_file = []
        self.task_runs_df = {}

        if json_file:
            json_file_data = open(json_file).read()
            tmp_task_runs = json.loads(json_file_data)
            for tr in tmp_task_runs:
                self.task_runs_file.append(pbclient.TaskRun(tr))

        if self.project:
            task_without_taskruns_count = 0
            for t in self.tasks:
                offset = 0
                limit = 100
                self.task_runs[t.id] = []
                if json_file:
                    self.task_runs[t.id] = [tr for tr in self.task_runs_file
                                            if (tr.task_id == t.id
                                                and
                                                tr.project_id == self.project.id)]
                else:
                    tmp = self.pbclient.find_taskruns(project_id=self.project.id,
                                                      task_id=t.id,
                                                      limit=limit,
                                                      offset=offset)
                    while(len(tmp) != 0):
                        self.task_runs[t.id] += tmp
                        offset += limit
                        tmp = self.pbclient.find_taskruns(
                            project_id=self.project.id,
                            task_id=t.id,
                            limit=limit,
                            offset=offset)

                if len(self.task_runs[t.id]) > 0:
                    data = [self.explode_info(tr)
                            for tr in self.task_runs[t.id]]
                    index = [tr.__dict__['data']['id'] for tr in
                             self.task_runs[t.id]]
                    self.task_runs_df[t.id] = pandas.DataFrame(data, index)
                else:
                    task_without_taskruns_count += 1
            if task_without_taskruns_count == len(self.tasks):
                raise ProjectWithoutTaskRuns
        else:
            raise ProjectError()

    def get_all(self):  # pragma: no cover
        """Get task and task_runs from project."""
        self.get_tasks()
        self.get_task_runs()

    def describe(self, element):  # pragma: no cover
        """Return tasks or task_runs Panda describe."""
        if (element == 'tasks'):
            return self.tasks_df.describe()
        elif (element == 'task_runs'):
            return self.task_runs_df.describe()
        else:
            return "ERROR: %s not found" % element
<commit_msg>Refactor<commit_after># -*- coding: utf8 -*-
# This file is part of PyBossa.
#
# Copyright (C) 2015 SF Isle of Man Limited
#
# PyBossa is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyBossa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with PyBossa.  If not, see <http://www.gnu.org/licenses/>.
"""
Enki module for analyzing the results of a PyBossa project.

This module exports:
    * Enki Class: to import an project, its tasks and task runs

"""
import pandas
import pbclient
import json
from exceptions import ProjectNotFound, ProjectError, \
    ProjectWithoutTasks, ProjectWithoutTaskRuns

class Enki(object):

    """General class for Enki."""

    def __init__(self, api_key, endpoint, project_short_name):
        """Initiate."""
        self.project = None
        pbclient.set('api_key', api_key)
        pbclient.set('endpoint', endpoint)
        if self.project is None:
            self.project = self.get_project(project_short_name)

    def get_project(self, project_short_name):
        """Return project object."""
        project = pbclient.find_project(short_name=project_short_name)
        if (len(project) == 1):
            return project[0]
        else:
            raise ProjectNotFound(project_short_name)

    def explode_info(self, item):
        """Return the a dict of the object but with info field exploded."""
        item_data = item.__dict__['data']
        if type(item.info) == dict:
            keys = item_data['info'].keys()
            for k in keys:
                item_data[k] = item_data['info'][k]
        return item_data

    def get_tasks(self, task_id=None, state='completed', json_file=None):
        """Load all project Tasks."""
        if self.project is None:
            raise ProjectError
        if task_id:
            offset = 0
            limit = 1
            query = dict(project_id=self.project.id,
                         state=state,
                         id=task_id,
                         limit=limit,
                         offset=offset)
        else:
            offset = 0
            limit = 100
            query = dict(project_id=self.project.id,
                         state=state,
                         limit=limit,
                         offset=offset)
        self.tasks = []

        tmp = pbclient.find_tasks(**query)
        if json_file:
            json_file_data = open(json_file).read()
            tmp_tasks = json.loads(json_file_data)
            for t in tmp_tasks:
                self.tasks.append(pbclient.Task(t))
        else:
            while(len(tmp) != 0):
                self.tasks += tmp
                offset += limit
                query['offset'] += limit
                tmp = pbclient.find_tasks(**query)

        # Create the data frame for tasks
        try:
            self.tasks[0]
            data = [self.explode_info(t) for t in self.tasks]
            index = [t.__dict__['data']['id'] for t in self.tasks]
            self.tasks_df = pandas.DataFrame(data, index)
        except:
            raise ProjectWithoutTasks

    def get_task_runs(self, json_file=None):
        """Load all project Task Runs from Tasks."""
        self.task_runs = {}
        self.task_runs_file = []
        self.task_runs_df = {}

        if json_file:
            json_file_data = open(json_file).read()
            tmp_task_runs = json.loads(json_file_data)
            for tr in tmp_task_runs:
                self.task_runs_file.append(pbclient.TaskRun(tr))

        if self.project:
            task_without_taskruns_count = 0
            for t in self.tasks:
                offset = 0
                limit = 100
                self.task_runs[t.id] = []
                if json_file:
                    self.task_runs[t.id] = [tr for tr in self.task_runs_file
                                            if (tr.task_id == t.id
                                                and
                                                tr.project_id == self.project.id)]
                else:
                    tmp = pbclient.find_taskruns(project_id=self.project.id,
                                                      task_id=t.id,
                                                      limit=limit,
                                                      offset=offset)
                    while(len(tmp) != 0):
                        self.task_runs[t.id] += tmp
                        offset += limit
                        tmp = pbclient.find_taskruns(
                            project_id=self.project.id,
                            task_id=t.id,
                            limit=limit,
                            offset=offset)

                if len(self.task_runs[t.id]) > 0:
                    data = [self.explode_info(tr)
                            for tr in self.task_runs[t.id]]
                    index = [tr.__dict__['data']['id'] for tr in
                             self.task_runs[t.id]]
                    self.task_runs_df[t.id] = pandas.DataFrame(data, index)
                else:
                    task_without_taskruns_count += 1
            if task_without_taskruns_count == len(self.tasks):
                raise ProjectWithoutTaskRuns
        else:
            raise ProjectError()

    def get_all(self):  # pragma: no cover
        """Get task and task_runs from project."""
        self.get_tasks()
        self.get_task_runs()

    def describe(self, element):  # pragma: no cover
        """Return tasks or task_runs Panda describe."""
        if (element == 'tasks'):
            return self.tasks_df.describe()
        elif (element == 'task_runs'):
            return self.task_runs_df.describe()
        else:
            return "ERROR: %s not found" % element
<|endoftext|>


<commit_before># Copyright (c) 2013, SoftLayer Technologies, Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#  * Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
#  * Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#  * Neither SoftLayer Technologies, Inc. nor the names of its contributors may
#    be used to endorse or promote products derived from this software without
#    specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

"""
SoftLayer API bindings

See U{http://sldn.softlayer.com/article/Python}
"""

from urlparse import urlparse
import socket
import xmlrpclib
import os

API_USERNAME = None
API_KEY = None
API_PUBLIC_ENDPOINT = 'https://api.softlayer.com/xmlrpc/v3/'
API_PRIVATE_ENDPOINT = 'https://api.service.softlayer.com/xmlrpc/v3/'
API_BASE_URL = API_PUBLIC_ENDPOINT

class SoftLayerError(Exception):
    pass

class Client:
    """A SoftLayer API client
    Clients are intended to be declared once per service and used for all calls
    made to that service.

    :param service_name: The name of the SoftLayer API service to query.
    :param id: An optional object if if you're instantiating a particular
        SoftLayer_API object. Setting an id defines this client's
        initialization parameter.
    :param username: An optional API username if you wish to bypass the
        package's built-in username.
    :param api_key: An optional API key if you wish to bypass the package's
        built in API key.
    :param endpoint_url: The API endpoint base URL you wish to connect to.
        Set this to API_PRIVATE_ENDPOINT to connect via SoftLayer's private
        network.
    :param timeout: Timeout for API requests
    :param verbose: When true, prints details about every HTTP request.

    Usage::

        >>> import SoftLayer
        >>> client = SoftLayer.Client(username="username", api_key="api_key")
        >>> resp = client['SoftLayer_Account'].getObject()
        >>> resp['companyName']
        'Your Company'

    """
    _prefix = "SoftLayer_"

    def __init__(self, service_name=None, id=None, username=None, api_key=None,
                 endpoint_url=None, timeout=None, verbose=False):
        self.verbose = verbose
        self._service_name = service_name
        self._headers = {}
        self._raw_headers = {}

        self.username = username or API_USERNAME or os.environ.get('SL_USERNAME')
        self.api_key = api_key or API_KEY or os.environ.get('SL_API_KEY')

        if not all((self.username, self.api_key)):
            raise SoftLayerError(
                'Must supply username, api_key and service_name')

        self.set_authentication(self.username, self.api_key)

        if id is not None:
            self.set_init_parameter(int(id))

        self._endpoint_url = (endpoint_url or API_BASE_URL or \
            API_PUBLIC_ENDPOINT).rstrip('/')
        http_protocol = urlparse(self._endpoint_url).scheme

        if http_protocol == "https":
            self.transport = SecureProxyTransport()
        else:
            self.transport = ProxyTransport()

        self._timeout = timeout

    def add_raw_header(self, name, value):
        self._raw_headers[name] = value

    def add_header(self, name, value):
        """ Set a SoftLayer API call header; deprecated

        :param name: The name of the header to add
        :param value: The header to add.
        """
        name = name.strip()

        if name is None or name is '':
            raise SoftLayerError('Please specify a header name.')

        self._headers[name] = value

    def remove_header(self, name):
        """ Remove a SoftLayer API call header; deprecated

        :param name: The name of the header to remove.
        """

        if name in self._headers:
            del self._headers[name.strip()]

    def set_authentication(self, username, api_key):
        """ Set user and key to authenticate a SoftLayer API call

        Use this method if you wish to bypass the API_USER and API_KEY class
        constants and set custom authentication per API call.

        See U{https://manage.softlayer.com/Administrative/apiKeychain} for more
        information.

        :param username: The username to authenticate an API call.
        :param api_key: The user's API key.
        """

        self.add_header('authenticate', {
            'username': username.strip(),
            'apiKey': api_key.strip(),
        })

    def set_init_parameter(self, id):
        """ Set an initialization parameter header; deprecated

        Initialization parameters instantiate a SoftLayer API service object to
        act upon during your API method call. For instance, if your account has
        a server with id number 1234, then setting an initialization parameter
        of 1234 in the SoftLayer_Hardware_Server Service instructs the API to
        act on server record 1234 in your method calls.

        See U{http://sldn.softlayer.com/article/Using-Initialization-Parameters-SoftLayer-API}
        for more information.

        :param id: The id number of the SoftLayer API object to instantiate
        """

        self.add_header(self._service_name + 'InitParameters', {
            'id': int(id)
        })

    def set_object_mask(self, mask):
        """ Set an object mask to a SoftLayer API call; deprecated

        Use an object mask to retrieve data related your API call's result.
        Object masks are skeleton objects, or strings that define nested
        relational properties to retrieve along with an object's local
        properties. See
        U{http://sldn.softlayer.com/article/Using-Object-Masks-SoftLayer-API}
        for more information.

        :param mask: The object mask you wish to define
        """

        header = 'SoftLayer_ObjectMask'

        if isinstance(mask, dict):
            header = '%sObjectMask' % self._service_name

        self.add_header(header, {'mask': mask})

    def set_result_limit(self, limit, offset=0):
        """ Set a result limit on a SoftLayer API call; deprecated

        Many SoftLayer API methods return a group of results. These methods
        support a way to limit the number of results retrieved from the
        SoftLayer API in a way akin to an SQL LIMIT statement.

        :param limit: The number of results to limit a SoftLayer API call to.
        :param offset: An optional offset to begin a SoftLayer API call's
        returned result at.
        """

        self.add_header('resultLimit', {
            'limit': int(limit),
            'offset': int(offset)
        })

    def __getitem__(self, name):
        """ Get a SoftLayer Service

        :param name: The name of the service. E.G. SoftLayer_Account
        """
        if not name.startswith(self._prefix):
            name = self._prefix + name
        return Service(self, name)

    def __call__(self, service, method, *args, **kwargs):
        """ Place a SoftLayer API call """
        objectid = kwargs.get('id')
        objectmask = kwargs.get('mask')
        objectfilter = kwargs.get('filter')
        headers = kwargs.get('headers')
        limit = kwargs.get('limit')
        offset = kwargs.get('offset', 0)

        if headers is None:
            headers = {
                'authenticate': {
                    'username': self.username,
                    'apiKey': self.api_key,
                }}

        if objectid is not None:
            headers[service + 'InitParameters'] = {'id': int(objectid)}

        if objectmask is not None:
            mheader = self._prefix + 'ObjectMask'
            if isinstance(objectmask, dict):
                mheader = '%sObjectMask' % service
            headers[mheader] = {'mask': objectmask}

        if objectfilter is not None:
            _objectfilter = {}
            for name, value in objectfilter.items():
                parts = name.split('.')
                _type = parts.pop(0)
                _filter = {}
                _working = _filter
                for i, part in enumerate(parts):
                    if part not in _working:
                        if i == len(parts) - 1:
                            _working[part] = {'operation': value}
                        else:
                            _working[part] = {}
                    _working = _working[part]
                _objectfilter[_type] = _filter
            headers['%sObjectFilter' % service] = _objectfilter

        if limit:
            headers['resultLimit'] = {
                    'limit': int(limit),
                    'offset': int(offset)
                }
        _old_timeout = socket.getdefaulttimeout()
        socket.setdefaulttimeout(self._timeout)
        try:
            uri = '/'.join([self._endpoint_url, service])
            self.transport.__extra_headers = self._raw_headers
            proxy = xmlrpclib.ServerProxy(uri, transport=self.transport,
                                          verbose=self.verbose)
            return proxy.__getattr__(method)({'headers': headers}, *args)
        except xmlrpclib.Fault, e:
            raise SoftLayerError(e.faultString)
        finally:
            self._raw_headers = {}
            socket.setdefaulttimeout(_old_timeout)

    def __getattr__(self, name):
        """ Attempt a SoftLayer API call

        Use this as a catch-all so users can call SoftLayer API methods
        directly against their client object. If the property or method
        relating to their client object doesn't exist then assume the user is
        attempting a SoftLayer API call and return a simple function that makes
        an XML-RPC call.
        """
        try:
            return object.__getattr__(self, name)
        except AttributeError:
            def call_handler(*args, **kwargs):
                return self(self._service_name, name, *args,
                    headers=self._headers, **kwargs)
            return call_handler

    def __repr__(self):
        return "<Client: endpoint=%s, user=%s>" \
            % (self._endpoint_url, self.username)

class Service:
    def __init__(self, client, name):
        self.client = client
        self.name = name

    def __call__(self, name, *args, **kwargs):
        return self.client(self.name, name, *args, **kwargs)

    def __getattr__(self, name):
        try:
            return object.__getattr__(self, name)
        except AttributeError:
            def call_handler(*args, **kwargs):
                return self(name, *args, **kwargs)
            return call_handler

    def __repr__(self):
        return "<Service: %s>" % (self.name,)

class ProxyTransport(xmlrpclib.Transport):
    __extra_headers = {}

    def send_content(self, connection, request_body):
        for k, v in self.__extra_headers:
            connection.putheader(k, v)

        connection.putheader("Content-Type", "text/xml")
        connection.putheader("Content-Length", str(len(request_body)))
        connection.endheaders()
        if request_body:
            connection.send(request_body)

class SecureProxyTransport(xmlrpclib.SafeTransport, ProxyTransport):
    pass

<commit_msg>Sets allow_none=True on the xmlrpc proxy. This allows None instead of '' when defining object masks<commit_after># Copyright (c) 2013, SoftLayer Technologies, Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#  * Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
#  * Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#  * Neither SoftLayer Technologies, Inc. nor the names of its contributors may
#    be used to endorse or promote products derived from this software without
#    specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

"""
SoftLayer API bindings

See U{http://sldn.softlayer.com/article/Python}
"""

from urlparse import urlparse
import socket
import xmlrpclib
import os

API_USERNAME = None
API_KEY = None
API_PUBLIC_ENDPOINT = 'https://api.softlayer.com/xmlrpc/v3/'
API_PRIVATE_ENDPOINT = 'https://api.service.softlayer.com/xmlrpc/v3/'
API_BASE_URL = API_PUBLIC_ENDPOINT

class SoftLayerError(Exception):
    pass

class Client:
    """A SoftLayer API client
    Clients are intended to be declared once per service and used for all calls
    made to that service.

    :param service_name: The name of the SoftLayer API service to query.
    :param id: An optional object if if you're instantiating a particular
        SoftLayer_API object. Setting an id defines this client's
        initialization parameter.
    :param username: An optional API username if you wish to bypass the
        package's built-in username.
    :param api_key: An optional API key if you wish to bypass the package's
        built in API key.
    :param endpoint_url: The API endpoint base URL you wish to connect to.
        Set this to API_PRIVATE_ENDPOINT to connect via SoftLayer's private
        network.
    :param timeout: Timeout for API requests
    :param verbose: When true, prints details about every HTTP request.

    Usage::

        >>> import SoftLayer
        >>> client = SoftLayer.Client(username="username", api_key="api_key")
        >>> resp = client['SoftLayer_Account'].getObject()
        >>> resp['companyName']
        'Your Company'

    """
    _prefix = "SoftLayer_"

    def __init__(self, service_name=None, id=None, username=None, api_key=None,
                 endpoint_url=None, timeout=None, verbose=False):
        self.verbose = verbose
        self._service_name = service_name
        self._headers = {}
        self._raw_headers = {}

        self.username = username or API_USERNAME or os.environ.get('SL_USERNAME')
        self.api_key = api_key or API_KEY or os.environ.get('SL_API_KEY')

        if not all((self.username, self.api_key)):
            raise SoftLayerError(
                'Must supply username, api_key and service_name')

        self.set_authentication(self.username, self.api_key)

        if id is not None:
            self.set_init_parameter(int(id))

        self._endpoint_url = (endpoint_url or API_BASE_URL or \
            API_PUBLIC_ENDPOINT).rstrip('/')
        http_protocol = urlparse(self._endpoint_url).scheme

        if http_protocol == "https":
            self.transport = SecureProxyTransport()
        else:
            self.transport = ProxyTransport()

        self._timeout = timeout

    def add_raw_header(self, name, value):
        self._raw_headers[name] = value

    def add_header(self, name, value):
        """ Set a SoftLayer API call header; deprecated

        :param name: The name of the header to add
        :param value: The header to add.
        """
        name = name.strip()

        if name is None or name is '':
            raise SoftLayerError('Please specify a header name.')

        self._headers[name] = value

    def remove_header(self, name):
        """ Remove a SoftLayer API call header; deprecated

        :param name: The name of the header to remove.
        """

        if name in self._headers:
            del self._headers[name.strip()]

    def set_authentication(self, username, api_key):
        """ Set user and key to authenticate a SoftLayer API call

        Use this method if you wish to bypass the API_USER and API_KEY class
        constants and set custom authentication per API call.

        See U{https://manage.softlayer.com/Administrative/apiKeychain} for more
        information.

        :param username: The username to authenticate an API call.
        :param api_key: The user's API key.
        """

        self.add_header('authenticate', {
            'username': username.strip(),
            'apiKey': api_key.strip(),
        })

    def set_init_parameter(self, id):
        """ Set an initialization parameter header; deprecated

        Initialization parameters instantiate a SoftLayer API service object to
        act upon during your API method call. For instance, if your account has
        a server with id number 1234, then setting an initialization parameter
        of 1234 in the SoftLayer_Hardware_Server Service instructs the API to
        act on server record 1234 in your method calls.

        See U{http://sldn.softlayer.com/article/Using-Initialization-Parameters-SoftLayer-API}
        for more information.

        :param id: The id number of the SoftLayer API object to instantiate
        """

        self.add_header(self._service_name + 'InitParameters', {
            'id': int(id)
        })

    def set_object_mask(self, mask):
        """ Set an object mask to a SoftLayer API call; deprecated

        Use an object mask to retrieve data related your API call's result.
        Object masks are skeleton objects, or strings that define nested
        relational properties to retrieve along with an object's local
        properties. See
        U{http://sldn.softlayer.com/article/Using-Object-Masks-SoftLayer-API}
        for more information.

        :param mask: The object mask you wish to define
        """

        header = 'SoftLayer_ObjectMask'

        if isinstance(mask, dict):
            header = '%sObjectMask' % self._service_name

        self.add_header(header, {'mask': mask})

    def set_result_limit(self, limit, offset=0):
        """ Set a result limit on a SoftLayer API call; deprecated

        Many SoftLayer API methods return a group of results. These methods
        support a way to limit the number of results retrieved from the
        SoftLayer API in a way akin to an SQL LIMIT statement.

        :param limit: The number of results to limit a SoftLayer API call to.
        :param offset: An optional offset to begin a SoftLayer API call's
        returned result at.
        """

        self.add_header('resultLimit', {
            'limit': int(limit),
            'offset': int(offset)
        })

    def __getitem__(self, name):
        """ Get a SoftLayer Service

        :param name: The name of the service. E.G. SoftLayer_Account
        """
        if not name.startswith(self._prefix):
            name = self._prefix + name
        return Service(self, name)

    def __call__(self, service, method, *args, **kwargs):
        """ Place a SoftLayer API call """
        objectid = kwargs.get('id')
        objectmask = kwargs.get('mask')
        objectfilter = kwargs.get('filter')
        headers = kwargs.get('headers')
        limit = kwargs.get('limit')
        offset = kwargs.get('offset', 0)

        if headers is None:
            headers = {
                'authenticate': {
                    'username': self.username,
                    'apiKey': self.api_key,
                }}

        if objectid is not None:
            headers[service + 'InitParameters'] = {'id': int(objectid)}

        if objectmask is not None:
            mheader = self._prefix + 'ObjectMask'
            if isinstance(objectmask, dict):
                mheader = '%sObjectMask' % service
            headers[mheader] = {'mask': objectmask}

        if objectfilter is not None:
            _objectfilter = {}
            for name, value in objectfilter.items():
                parts = name.split('.')
                _type = parts.pop(0)
                _filter = {}
                _working = _filter
                for i, part in enumerate(parts):
                    if part not in _working:
                        if i == len(parts) - 1:
                            _working[part] = {'operation': value}
                        else:
                            _working[part] = {}
                    _working = _working[part]
                _objectfilter[_type] = _filter
            headers['%sObjectFilter' % service] = _objectfilter

        if limit:
            headers['resultLimit'] = {
                    'limit': int(limit),
                    'offset': int(offset)
                }
        _old_timeout = socket.getdefaulttimeout()
        socket.setdefaulttimeout(self._timeout)
        try:
            uri = '/'.join([self._endpoint_url, service])
            self.transport.__extra_headers = self._raw_headers
            proxy = xmlrpclib.ServerProxy(uri, transport=self.transport,
                                          verbose=self.verbose, allow_none=True)
            return proxy.__getattr__(method)({'headers': headers}, *args)
        except xmlrpclib.Fault, e:
            raise SoftLayerError(e.faultString)
        finally:
            self._raw_headers = {}
            socket.setdefaulttimeout(_old_timeout)

    def __getattr__(self, name):
        """ Attempt a SoftLayer API call

        Use this as a catch-all so users can call SoftLayer API methods
        directly against their client object. If the property or method
        relating to their client object doesn't exist then assume the user is
        attempting a SoftLayer API call and return a simple function that makes
        an XML-RPC call.
        """
        try:
            return object.__getattr__(self, name)
        except AttributeError:
            def call_handler(*args, **kwargs):
                return self(self._service_name, name, *args,
                    headers=self._headers, **kwargs)
            return call_handler

    def __repr__(self):
        return "<Client: endpoint=%s, user=%s>" \
            % (self._endpoint_url, self.username)

class Service:
    def __init__(self, client, name):
        self.client = client
        self.name = name

    def __call__(self, name, *args, **kwargs):
        return self.client(self.name, name, *args, **kwargs)

    def __getattr__(self, name):
        try:
            return object.__getattr__(self, name)
        except AttributeError:
            def call_handler(*args, **kwargs):
                return self(name, *args, **kwargs)
            return call_handler

    def __repr__(self):
        return "<Service: %s>" % (self.name,)

class ProxyTransport(xmlrpclib.Transport):
    __extra_headers = {}

    def send_content(self, connection, request_body):
        for k, v in self.__extra_headers:
            connection.putheader(k, v)

        connection.putheader("Content-Type", "text/xml")
        connection.putheader("Content-Length", str(len(request_body)))
        connection.endheaders()
        if request_body:
            connection.send(request_body)

class SecureProxyTransport(xmlrpclib.SafeTransport, ProxyTransport):
    pass

<|endoftext|>