<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2018 Comunitea
#
#    This program 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.
#
#    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import models, fields, api
from datetime import datetime
from dateutil.rrule import rrule
import logging

_logger = logging.getLogger(__name__)

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    channel = fields.Selection([
        ('erp', 'ERP'),
        ('tablet', 'Tablet'),
        ('other', 'Other'),
        ('ecommerce', 'E-commerce')
        ], string='Channel', readonly=True)
    app_note = fields.Text(string='App notes')

    @api.model
    def create_and_confirm(self, vals):
        sale_obj = self.env['sale.order']
        sale_line_obj = self.env['sale.order.line']

        partner_shipping_id = vals.get('partner_shipping_id', False)
        shipping_dir = self.env['res.partner'].browse(partner_shipping_id)
        partner = shipping_dir.commercial_partner_id
        addr = partner.address_get(['delivery', 'invoice', 'contact'])
        invoice_dir = addr['invoice']
        company_id = self.env.user.company_id
        shop_id = vals.get('shop_id', False)
        if not shop_id:
            ir_values = self.env['ir.values']
            shop_id = ir_values.get_default('sale.order', 'shop_id', company_id=company_id.id)
        create_date = vals.get('create_date', False) or fields.Datetime.now()
        date_order = vals.get('date_order', False) or fields.Datetime.now()
        requested_date = vals.get('requested_date', False)
        client_order_ref = vals.get('client_order_ref', False)
        pricelist_id = vals.get('pricelist_id', False)
        warehouse_id = self.env['stock.warehouse'].search([], limit=1) # El valor que envía la app no sirve
        channel = vals.get('channel', False)
        note = vals.get('note', '')
        order_line = vals.get('order_line', [])
        values = {
            'create_date': create_date,
            'date_order': date_order,
            'requested_date': requested_date,
            'client_order_ref': client_order_ref,
            'partner_id': partner.id,
            'partner_invoice_id': invoice_dir,
            'partner_shipping_id': shipping_dir.id,
            'pricelist_id': pricelist_id,
            'fiscal_position': False,
            'payment_term': False,
            'payment_mode_id': False,
            'early_payment_discount': False,
            'user_id': shipping_dir.user_id.id,
            'shop_id': shop_id,
            'warehouse_id': warehouse_id.id,
            'channel': channel,
            'company_id': company_id.id,
            'app_note': note,
        }
        # Creamos el pedido
        order_id = sale_obj.with_context(mail_notrack=True).create(values)
        # Se van a ejecutar los onchanges de la cabecera para actualizar valores
        # onchange shop_id
        order_id.onchange_shop_id()
        read_fields = [
            'date_order', 'partner_id', 'partner_shipping_id', 'pricelist_id',
            'fiscal_position', 'payment_term', 'early_payment_discount',
            'shop_id', 'warehouse_id', 'company_id',
        ]
        values = order_id.read(fields=read_fields, load='_classic_write')[0]
        # onchange partner_id
        data = {}
        data.update(
            sale_obj.with_context(no_check_risk=True).onchange_partner_id3(
                values['partner_id'],
                early_payment_discount=values['early_payment_discount'],
                payment_term=False, shop=values['shop_id'])['value']
        )
        if 'partner_shipping_id' in data and data['partner_shipping_id']:
            del data['partner_shipping_id']
        values.update(data)
        # onchange partner_shipping_id
        data = {}
        data.update(
            sale_obj.onchange_delivery_id(
                values['company_id'],
                values['partner_id'], values['partner_shipping_id'],
                values['fiscal_position'])['value']
        )
        values.update(data)
        dp = self.env['decimal.precision'].precision_get('Product Price')
        # onchange payment_term
        data = {}
        data.update(
            sale_obj.onchange_payment_term(
                values['payment_term'],
                values['partner_id'])['value']
        )
        values.update(data)
        # Consultamos la ruta de transporte y ponemos mensaje fuera de ruta en notas app si procede
        delivery_route_id = shipping_dir.delivery_route_id or \
            shipping_dir.commercial_partner_id.delivery_route_id
        loading_date = delivery_route_id.next_loading_date
        if loading_date:
            today = fields.Date.context_today(self)
            initial_date = datetime.strptime(today, "%Y-%m-%d")
            end_date = datetime.strptime(loading_date, "%Y-%m-%d")
            diff_days = 1 + len(rrule(
                freq=3, # Daily
                byweekday=(0, 1, 2, 3, 4),
                wkst=0,
                dtstart=initial_date,
                until=end_date,
                interval=1)
                .between(initial_date, end_date, inc=False)
            )
            if diff_days == 0:
                app_note = '*** RUTA CARGANDOSE/CARGADA ***' + ((note and '\n' + note) or '')
                values.update({'app_note': app_note})
            elif diff_days > 4:
                app_note = '*** FUERA DE RUTA ***' + ((note and '\n' + note) or '')
                values.update({'app_note': app_note})

        # Obtenemos las lineas del pedido
        order_lines = []
        for line in order_line:
            product_id = line[2]['product_id']
            product_uom_qty = line[2]['product_uom_qty']
            product_uos_qty = line[2]['product_uos_qty']
            uom_id = line[2]['product_uom']
            uos_id = line[2]['product_uos']
            price_unit = round(line[2]['price_unit'], dp)
            discount = round(line[2]['discount'], 2)
            app_discount_type = line[2].get('discount_type', False)
            if app_discount_type not in ('-1', '0', '1', '2', '3'):
                app_discount_type = False
            if app_discount_type == '0' and discount > 0 or app_discount_type == '-1':
                app_discount_type = False
            line_values = {
                'order_id': order_id.id,
                'product_id': product_id,
                'name': '',
                'product_uom_qty': product_uom_qty,
                'product_uom': uom_id,
                'product_uos_qty': product_uos_qty,
                'product_uos': uos_id,
                'price_unit': price_unit,
                'discount': discount,
                'app_discount_type': app_discount_type,
            }
            # Se van a ejecutar los onchanges de las lineas para actualizar valores
            # Llamo al onchange del producto
            data = {}
            ctx = dict(
                self._context,
                partner_id=values['partner_id'],
                address_id=values['partner_shipping_id'],
                fiscal_position=values['fiscal_position'],
                quantity=line_values['product_uom_qty'],
                pricelist=values['pricelist_id'],
                shop=values['shop_id'], # Necesario en eln_partner_discount
                company_id=values['company_id'],
                uom=False
            )
            data.update(
                sale_line_obj.with_context(ctx).product_id_change_with_wh(
                    values['pricelist_id'], product_id, qty=product_uom_qty,
                    uom=uom_id, qty_uos=product_uos_qty, uos=uos_id, name='',
                    partner_id=values['partner_id'],
                    lang=False, update_tax=True, date_order=values['date_order'],
                    packaging=False, fiscal_position=values['fiscal_position'],
                    flag=False, warehouse_id=values['warehouse_id'])['value']
            )
            if 'product_uom_qty' in data:
                del data['product_uom_qty']
            if 'tax_id' in data:
                data['tax_id'] = [(6, 0, data['tax_id'])]
            if 'price_unit' in data:
                del data['price_unit']
            if 'discount' in data:
                if discount: # Hacemos descuento encadenado
                    data['discount'] = 100 - (100 * (1 - data['discount'] / 100) * (1 - discount / 100))
                # del data['discount']
            line_values.update(data)
            order_lines.append((0, 0, line_values))
        # Contexto para que asigne las comisiones en las lineas
        ctx = dict(
            self._context,
            partner_id=values['partner_id'],          # Necesario en módulo sale_commission
            address_id=values['partner_shipping_id'], # Necesario en módulo sale_commission
            mail_notrack=True,
        )
        # Creamos las lineas del pedido
        values['order_line'] = order_lines
        order_id.with_context(ctx).write(values)
        if order_id:
            # Para diferenciar del estado 'draft' ponemos el estado como 'quotation_sent'.
            order_id.signal_workflow('quotation_sent')
            _logger.info("SALES APP: Pedido <%s> OK. Usuario: <%s>" % (order_id.name, self.env.user.name))
            return order_id.id
        _logger.info("SALES APP: ERROR creando pedido. Usuario: <%s>" % (self.env.user.name))
        return False

    @api.model
    def easy_modification(self, order_id, vals):
        # TODO
        _logger.info("SALES APP: ERROR modificando pedido <%s>. Usuario: <%s>" % (vals.get('name', order_id), self.env.user.name))
        return True

class SaleOrderLine(models.Model):
    _inherit = 'sale.order.line'

    app_discount_type = fields.Selection([
        ('0', 'Type 0'),
        ('1', 'Type 1'),
        ('2', 'Type 2'),
        ('3', 'Type 3')
        ], string='App disc. type', readonly=True,
        help="Discount type applied from sales app")

    @api.onchange('discount', 'price_unit')
    def onchange_discount(self):
        self.app_discount_type = False

<commit_msg>Modificado cálculo diff_days<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2018 Comunitea
#
#    This program 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.
#
#    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import models, fields, api
from datetime import datetime
from dateutil.rrule import rrule
import logging

_logger = logging.getLogger(__name__)

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    channel = fields.Selection([
        ('erp', 'ERP'),
        ('tablet', 'Tablet'),
        ('other', 'Other'),
        ('ecommerce', 'E-commerce')
        ], string='Channel', readonly=True)
    app_note = fields.Text(string='App notes')

    @api.model
    def create_and_confirm(self, vals):
        sale_obj = self.env['sale.order']
        sale_line_obj = self.env['sale.order.line']

        partner_shipping_id = vals.get('partner_shipping_id', False)
        shipping_dir = self.env['res.partner'].browse(partner_shipping_id)
        partner = shipping_dir.commercial_partner_id
        addr = partner.address_get(['delivery', 'invoice', 'contact'])
        invoice_dir = addr['invoice']
        company_id = self.env.user.company_id
        shop_id = vals.get('shop_id', False)
        if not shop_id:
            ir_values = self.env['ir.values']
            shop_id = ir_values.get_default('sale.order', 'shop_id', company_id=company_id.id)
        create_date = vals.get('create_date', False) or fields.Datetime.now()
        date_order = vals.get('date_order', False) or fields.Datetime.now()
        requested_date = vals.get('requested_date', False)
        client_order_ref = vals.get('client_order_ref', False)
        pricelist_id = vals.get('pricelist_id', False)
        warehouse_id = self.env['stock.warehouse'].search([], limit=1) # El valor que envía la app no sirve
        channel = vals.get('channel', False)
        note = vals.get('note', '')
        order_line = vals.get('order_line', [])
        values = {
            'create_date': create_date,
            'date_order': date_order,
            'requested_date': requested_date,
            'client_order_ref': client_order_ref,
            'partner_id': partner.id,
            'partner_invoice_id': invoice_dir,
            'partner_shipping_id': shipping_dir.id,
            'pricelist_id': pricelist_id,
            'fiscal_position': False,
            'payment_term': False,
            'payment_mode_id': False,
            'early_payment_discount': False,
            'user_id': shipping_dir.user_id.id,
            'shop_id': shop_id,
            'warehouse_id': warehouse_id.id,
            'channel': channel,
            'company_id': company_id.id,
            'app_note': note,
        }
        # Creamos el pedido
        order_id = sale_obj.with_context(mail_notrack=True).create(values)
        # Se van a ejecutar los onchanges de la cabecera para actualizar valores
        # onchange shop_id
        order_id.onchange_shop_id()
        read_fields = [
            'date_order', 'partner_id', 'partner_shipping_id', 'pricelist_id',
            'fiscal_position', 'payment_term', 'early_payment_discount',
            'shop_id', 'warehouse_id', 'company_id',
        ]
        values = order_id.read(fields=read_fields, load='_classic_write')[0]
        # onchange partner_id
        data = {}
        data.update(
            sale_obj.with_context(no_check_risk=True).onchange_partner_id3(
                values['partner_id'],
                early_payment_discount=values['early_payment_discount'],
                payment_term=False, shop=values['shop_id'])['value']
        )
        if 'partner_shipping_id' in data and data['partner_shipping_id']:
            del data['partner_shipping_id']
        values.update(data)
        # onchange partner_shipping_id
        data = {}
        data.update(
            sale_obj.onchange_delivery_id(
                values['company_id'],
                values['partner_id'], values['partner_shipping_id'],
                values['fiscal_position'])['value']
        )
        values.update(data)
        dp = self.env['decimal.precision'].precision_get('Product Price')
        # onchange payment_term
        data = {}
        data.update(
            sale_obj.onchange_payment_term(
                values['payment_term'],
                values['partner_id'])['value']
        )
        values.update(data)
        # Consultamos la ruta de transporte y ponemos mensaje fuera de ruta en notas app si procede
        delivery_route_id = shipping_dir.delivery_route_id or \
            shipping_dir.commercial_partner_id.delivery_route_id
        loading_date = delivery_route_id.next_loading_date
        if loading_date:
            today = fields.Date.context_today(self)
            initial_date = datetime.strptime(today, "%Y-%m-%d")
            end_date = datetime.strptime(loading_date, "%Y-%m-%d")
            diff_days = -1 + len(rrule(
                freq=3, # Daily
                byweekday=(0, 1, 2, 3, 4),
                wkst=0,
                dtstart=initial_date,
                until=end_date,
                interval=1)
                .between(initial_date, end_date, inc=True)
            )
            if diff_days == 0:
                app_note = '*** RUTA CARGANDOSE/CARGADA ***' + ((note and '\n' + note) or '')
                values.update({'app_note': app_note})
            elif diff_days > 4:
                app_note = '*** FUERA DE RUTA ***' + ((note and '\n' + note) or '')
                values.update({'app_note': app_note})

        # Obtenemos las lineas del pedido
        order_lines = []
        for line in order_line:
            product_id = line[2]['product_id']
            product_uom_qty = line[2]['product_uom_qty']
            product_uos_qty = line[2]['product_uos_qty']
            uom_id = line[2]['product_uom']
            uos_id = line[2]['product_uos']
            price_unit = round(line[2]['price_unit'], dp)
            discount = round(line[2]['discount'], 2)
            app_discount_type = line[2].get('discount_type', False)
            if app_discount_type not in ('-1', '0', '1', '2', '3'):
                app_discount_type = False
            if app_discount_type == '0' and discount > 0 or app_discount_type == '-1':
                app_discount_type = False
            line_values = {
                'order_id': order_id.id,
                'product_id': product_id,
                'name': '',
                'product_uom_qty': product_uom_qty,
                'product_uom': uom_id,
                'product_uos_qty': product_uos_qty,
                'product_uos': uos_id,
                'price_unit': price_unit,
                'discount': discount,
                'app_discount_type': app_discount_type,
            }
            # Se van a ejecutar los onchanges de las lineas para actualizar valores
            # Llamo al onchange del producto
            data = {}
            ctx = dict(
                self._context,
                partner_id=values['partner_id'],
                address_id=values['partner_shipping_id'],
                fiscal_position=values['fiscal_position'],
                quantity=line_values['product_uom_qty'],
                pricelist=values['pricelist_id'],
                shop=values['shop_id'], # Necesario en eln_partner_discount
                company_id=values['company_id'],
                uom=False
            )
            data.update(
                sale_line_obj.with_context(ctx).product_id_change_with_wh(
                    values['pricelist_id'], product_id, qty=product_uom_qty,
                    uom=uom_id, qty_uos=product_uos_qty, uos=uos_id, name='',
                    partner_id=values['partner_id'],
                    lang=False, update_tax=True, date_order=values['date_order'],
                    packaging=False, fiscal_position=values['fiscal_position'],
                    flag=False, warehouse_id=values['warehouse_id'])['value']
            )
            if 'product_uom_qty' in data:
                del data['product_uom_qty']
            if 'tax_id' in data:
                data['tax_id'] = [(6, 0, data['tax_id'])]
            if 'price_unit' in data:
                del data['price_unit']
            if 'discount' in data:
                if discount: # Hacemos descuento encadenado
                    data['discount'] = 100 - (100 * (1 - data['discount'] / 100) * (1 - discount / 100))
                # del data['discount']
            line_values.update(data)
            order_lines.append((0, 0, line_values))
        # Contexto para que asigne las comisiones en las lineas
        ctx = dict(
            self._context,
            partner_id=values['partner_id'],          # Necesario en módulo sale_commission
            address_id=values['partner_shipping_id'], # Necesario en módulo sale_commission
            mail_notrack=True,
        )
        # Creamos las lineas del pedido
        values['order_line'] = order_lines
        order_id.with_context(ctx).write(values)
        if order_id:
            # Para diferenciar del estado 'draft' ponemos el estado como 'quotation_sent'.
            order_id.signal_workflow('quotation_sent')
            _logger.info("SALES APP: Pedido <%s> OK. Usuario: <%s>" % (order_id.name, self.env.user.name))
            return order_id.id
        _logger.info("SALES APP: ERROR creando pedido. Usuario: <%s>" % (self.env.user.name))
        return False

    @api.model
    def easy_modification(self, order_id, vals):
        # TODO
        _logger.info("SALES APP: ERROR modificando pedido <%s>. Usuario: <%s>" % (vals.get('name', order_id), self.env.user.name))
        return True

class SaleOrderLine(models.Model):
    _inherit = 'sale.order.line'

    app_discount_type = fields.Selection([
        ('0', 'Type 0'),
        ('1', 'Type 1'),
        ('2', 'Type 2'),
        ('3', 'Type 3')
        ], string='App disc. type', readonly=True,
        help="Discount type applied from sales app")

    @api.onchange('discount', 'price_unit')
    def onchange_discount(self):
        self.app_discount_type = False

<|endoftext|>


<commit_before>from ctypes import *
from ctypes.util import find_library
import inspect
import os

_DLL_PATH = @ESN_PY_DLL_PATH@
# Need to check the path, otherwise CDLL.LoadLibrary()
# raises an exception under Windows.
if _DLL_PATH :
    _DLL = cdll.LoadLibrary( _DLL_PATH )

class Network :

    def __init__( self, pointer ) :
        self.pointer = pointer

    def __del__( self ) :
        self.release()

    def release( self ) :
        _DLL.esnNetworkDestruct( self.pointer )

    def set_inputs( self, inputs ) :
        InputsArrayType = c_float * len( inputs )
        inputsArray = InputsArrayType( *inputs )
        _DLL.esnNetworkSetInputs( self.pointer, pointer( inputsArray ),
            len( inputs ) )

    def set_input_scalings( self, scalings ) :
        ScalingsArrayType = c_float * len( scalings )
        scalingsArray = ScalingsArrayType( *scalings )
        _DLL.esnNetworkSetInputScalings( self.pointer,
            pointer( scalingsArray ), len( scalings ) )

    def set_feedback_scalings( self, scalings ) :
        ScalingsArrayType = c_float * len( scalings )
        scalingsArray = ScalingsArrayType( *scalings )
        _DLL.esnNetworkSetFeedbackScalings( self.pointer,
            pointer( scalingsArray ), len( scalings ) )

    def step( self, step ) :
        _DLL.esnNetworkStep( self.pointer, c_float( step ) )

    def capture_activations( self, count ) :
        ActivationsArrayType = c_float * count
        activationsArray = ActivationsArrayType()
        _DLL.esnNetworkCaptureActivations( self.pointer,
            pointer( activationsArray ), count )
        return [ activationsArray[i] for i in range( count ) ]

    def capture_output( self, count ) :
        OutputArrayType = c_float * count
        outputArray = OutputArrayType()
        _DLL.esnNetworkCaptureOutput( self.pointer,
            pointer( outputArray ), count )
        output = [ outputArray[ i ] for i in range( count ) ]
        return output

    def train_online( self, output, forceOutput = False ) :
        OutputArrayType = c_float * len( output )
        outputArray = OutputArrayType( *output )
        _DLL.esnNetworkTrainOnline( self.pointer, pointer( outputArray ),
            len( output ), forceOutput )

class NetworkParamsNSLI( Structure ) :
    _fields_ = [
            ( "structSize", c_uint ),
            ( "inputCount", c_uint ),
            ( "neuronCount", c_uint ),
            ( "outputCount", c_uint ),
            ( "leakingRate", c_float ),
            ( "useOrthonormalMatrix", c_bool ),
            ( "spectralRadius", c_float ),
            ( "connectivity", c_float ),
            ( "linearOutput", c_bool ),
            ( "onlineTrainingForgettingFactor", c_float ),
            ( "onlineTrainingInitialCovariance", c_float )
        ]

def create_network(
    inputCount,
    neuronCount,
    outputCount,
    leakingRate = 1.0,
    useOrthonormalMatrix = False,
    spectralRadius = 1.0,
    connectivity = 1.0,
    linearOutput = False,
    onlineTrainingForgettingFactor = 0.999,
    onlineTrainingInitialCovariance = 1000.0 ) :

    if not _DLL._name :
        raise RuntimeError( "ESN shared library hasn't been loaded." )

    params = NetworkParamsNSLI(
        structSize = sizeof( NetworkParamsNSLI ),
        inputCount = inputCount,
        neuronCount = neuronCount,
        outputCount = outputCount,
        leakingRate = leakingRate,
        useOrthonormalMatrix = useOrthonormalMatrix,
        spectralRadius = spectralRadius,
        connectivity = connectivity,
        linearOutput = linearOutput,
        onlineTrainingForgettingFactor = onlineTrainingForgettingFactor,
        onlineTrainingInitialCovariance = onlineTrainingInitialCovariance )

    _DLL.esnCreateNetworkNSLI.restype = c_void_p
    return Network( _DLL.esnCreateNetworkNSLI( pointer( params ) ) )
<commit_msg>esn : define python enum Error<commit_after>from ctypes import *
from ctypes.util import find_library
from enum import Enum
import inspect
import os

_DLL_PATH = @ESN_PY_DLL_PATH@
# Need to check the path, otherwise CDLL.LoadLibrary()
# raises an exception under Windows.
if _DLL_PATH :
    _DLL = cdll.LoadLibrary( _DLL_PATH )

class Error( Enum ) :
    NO_ERROR = 0
    OUTPUT_IS_NOT_FINITE = 1

class Network :

    def __init__( self, pointer ) :
        self.pointer = pointer

    def __del__( self ) :
        self.release()

    def release( self ) :
        _DLL.esnNetworkDestruct( self.pointer )

    def set_inputs( self, inputs ) :
        InputsArrayType = c_float * len( inputs )
        inputsArray = InputsArrayType( *inputs )
        _DLL.esnNetworkSetInputs( self.pointer, pointer( inputsArray ),
            len( inputs ) )

    def set_input_scalings( self, scalings ) :
        ScalingsArrayType = c_float * len( scalings )
        scalingsArray = ScalingsArrayType( *scalings )
        _DLL.esnNetworkSetInputScalings( self.pointer,
            pointer( scalingsArray ), len( scalings ) )

    def set_feedback_scalings( self, scalings ) :
        ScalingsArrayType = c_float * len( scalings )
        scalingsArray = ScalingsArrayType( *scalings )
        _DLL.esnNetworkSetFeedbackScalings( self.pointer,
            pointer( scalingsArray ), len( scalings ) )

    def step( self, step ) :
        _DLL.esnNetworkStep( self.pointer, c_float( step ) )

    def capture_activations( self, count ) :
        ActivationsArrayType = c_float * count
        activationsArray = ActivationsArrayType()
        _DLL.esnNetworkCaptureActivations( self.pointer,
            pointer( activationsArray ), count )
        return [ activationsArray[i] for i in range( count ) ]

    def capture_output( self, count ) :
        OutputArrayType = c_float * count
        outputArray = OutputArrayType()
        _DLL.esnNetworkCaptureOutput( self.pointer,
            pointer( outputArray ), count )
        output = [ outputArray[ i ] for i in range( count ) ]
        return output

    def train_online( self, output, forceOutput = False ) :
        OutputArrayType = c_float * len( output )
        outputArray = OutputArrayType( *output )
        _DLL.esnNetworkTrainOnline( self.pointer, pointer( outputArray ),
            len( output ), forceOutput )

class NetworkParamsNSLI( Structure ) :
    _fields_ = [
            ( "structSize", c_uint ),
            ( "inputCount", c_uint ),
            ( "neuronCount", c_uint ),
            ( "outputCount", c_uint ),
            ( "leakingRate", c_float ),
            ( "useOrthonormalMatrix", c_bool ),
            ( "spectralRadius", c_float ),
            ( "connectivity", c_float ),
            ( "linearOutput", c_bool ),
            ( "onlineTrainingForgettingFactor", c_float ),
            ( "onlineTrainingInitialCovariance", c_float )
        ]

def create_network(
    inputCount,
    neuronCount,
    outputCount,
    leakingRate = 1.0,
    useOrthonormalMatrix = False,
    spectralRadius = 1.0,
    connectivity = 1.0,
    linearOutput = False,
    onlineTrainingForgettingFactor = 0.999,
    onlineTrainingInitialCovariance = 1000.0 ) :

    if not _DLL._name :
        raise RuntimeError( "ESN shared library hasn't been loaded." )

    params = NetworkParamsNSLI(
        structSize = sizeof( NetworkParamsNSLI ),
        inputCount = inputCount,
        neuronCount = neuronCount,
        outputCount = outputCount,
        leakingRate = leakingRate,
        useOrthonormalMatrix = useOrthonormalMatrix,
        spectralRadius = spectralRadius,
        connectivity = connectivity,
        linearOutput = linearOutput,
        onlineTrainingForgettingFactor = onlineTrainingForgettingFactor,
        onlineTrainingInitialCovariance = onlineTrainingInitialCovariance )

    _DLL.esnCreateNetworkNSLI.restype = c_void_p
    return Network( _DLL.esnCreateNetworkNSLI( pointer( params ) ) )
<|endoftext|>


<commit_before># Copyright 2012 OpenStack Foundation
# Copyright (c) 2016 Hewlett-Packard Enterprise Development Company, L.P.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import copy
import importlib
import inspect
import logging

from tempest.lib import auth
from tempest.lib import exceptions
from tempest.lib.services import clients
from tempest.lib.services import compute
from tempest.lib.services import image
from tempest.lib.services import network

LOG = logging.getLogger(__name__)

client_modules_by_service_name = {
    'compute': compute,
    'image.v1': image.v1,
    'image.v2': image.v2,
    'network': network
}

def tempest_modules():
    """List of service client modules available in Tempest.

    Provides a list of service modules available Tempest.
    """
    return set(['compute', 'identity.v2', 'identity.v3', 'image.v1',
                'image.v2', 'network', 'object-storage', 'volume.v1',
                'volume.v2', 'volume.v3'])

def available_modules():
    """List of service client modules available in Tempest and plugins

    The list of available modules can be used for automatic configuration.

    :raise PluginRegistrationException: if a plugin exposes a service_version
        already defined by Tempest or another plugin.

    Examples:

        >>> from tempest import config
        >>> params = {}
        >>> for service_version in available_modules():
        >>>     service = service_version.split('.')[0]
        >>>     params[service] = config.service_client_config(service)
        >>> service_clients = ServiceClients(creds, identity_uri,
        >>>                                  client_parameters=params)
    """
    extra_service_versions = set([])
    plugin_services = clients.ClientsRegistry().get_service_clients()
    for plugin_name in plugin_services:
        plug_service_versions = set([x['service_version'] for x in
                                     plugin_services[plugin_name]])
        # If a plugin exposes a duplicate service_version raise an exception
        if plug_service_versions:
            if not plug_service_versions.isdisjoint(extra_service_versions):
                detailed_error = (
                    'Plugin %s is trying to register a service %s already '
                    'claimed by another one' % (plugin_name,
                                                extra_service_versions &
                                                plug_service_versions))
                raise exceptions.PluginRegistrationException(
                    name=plugin_name, detailed_error=detailed_error)
            if not plug_service_versions.isdisjoint(tempest_modules()):
                detailed_error = (
                    'Plugin %s is trying to register a service %s already '
                    'claimed by a Tempest one' % (plugin_name,
                                                  tempest_modules() &
                                                  plug_service_versions))
                raise exceptions.PluginRegistrationException(
                    name=plugin_name, detailed_error=detailed_error)
        extra_service_versions |= plug_service_versions
    return tempest_modules() | extra_service_versions

class ClientsFactory(object):
    """Builds service clients for a service client module

    This class implements the logic of feeding service client parameters
    to service clients from a specific module. It allows setting the
    parameters once and obtaining new instances of the clients without the
    need of passing any parameter.

    ClientsFactory can be used directly, or consumed via the `ServiceClients`
    class, which manages the authorization part.
    """

    def __init__(self, module_path, client_names, auth_provider, **kwargs):
        """Initialises the client factory

        :param module_path Path to module that includes all service clients.
            All service client classes must be exposed by a single module.
            If they are separated in different modules, defining __all__
            in the root module can help, similar to what is done by service
            clients in tempest.
        :param client_names List or set of names of the service client classes.
        :param auth_provider The auth provider used to initialise client.
        :param kwargs Parameters to be passed to all clients. Parameters values
            can be overwritten when clients are initialised, but parameters
            cannot be deleted.
        :raise ImportError if the specified module_path cannot be imported

        Example:

            >>> # Get credentials and an auth_provider
            >>> clients = ClientsFactory(
            >>>     module_path='my_service.my_service_clients',
            >>>     client_names=['ServiceClient1', 'ServiceClient2'],
            >>>     auth_provider=auth_provider,
            >>>     service='my_service',
            >>>     region='region1')
            >>> my_api_client = clients.MyApiClient()
            >>> my_api_client_region2 = clients.MyApiClient(region='region2')

        """
        # Import the module. If it's not importable, the raised exception
        # provides good enough information about what happened
        _module = importlib.import_module(module_path)
        # If any of the classes is not in the module we fail
        for class_name in client_names:
            # TODO(andreaf) This always passes all parameters to all clients.
            # In future to allow clients to specify the list of parameters
            # that they accept based out of a list of standard ones.

            # Obtain the class
            klass = self._get_class(_module, class_name)
            final_kwargs = copy.copy(kwargs)

            # Set the function as an attribute of the factory
            setattr(self, class_name, self._get_partial_class(
                klass, auth_provider, final_kwargs))

    @classmethod
    def _get_partial_class(cls, klass, auth_provider, kwargs):

        # Define a function that returns a new class instance by
        # combining default kwargs with extra ones
        def partial_class(**later_kwargs):
            kwargs.update(later_kwargs)
            return klass(auth_provider=auth_provider, **kwargs)

        return partial_class

    @classmethod
    def _get_class(cls, module, class_name):
        klass = getattr(module, class_name, None)
        if not klass:
            msg = 'Invalid class name, %s is not found in %s'
            raise AttributeError(msg % (class_name, module))
        if not inspect.isclass(klass):
            msg = 'Expected a class, got %s of type %s instead'
            raise TypeError(msg % (klass, type(klass)))
        return klass

class ServiceClients(object):
    """Service client provider class

    The ServiceClients object provides a useful means for tests to access
    service clients configured for a specified set of credentials.
    It hides some of the complexity from the authorization and configuration
    layers.

    Examples:

        >>> from tempest import service_clients
        >>> johndoe = cred_provider.get_creds_by_role(['johndoe'])
        >>> johndoe_clients = service_clients.ServiceClients(johndoe,
        >>>                                                  identity_uri)
        >>> johndoe_servers = johndoe_clients.servers_client.list_servers()

    """
    # NOTE(andreaf) This class does not depend on tempest configuration
    # and its meant for direct consumption by external clients such as tempest
    # plugins. Tempest provides a wrapper class, `clients.Manager`, that
    # initialises this class using values from tempest CONF object. The wrapper
    # class should only be used by tests hosted in Tempest.

    def __init__(self, credentials, identity_uri, region=None, scope='project',
                 disable_ssl_certificate_validation=True, ca_certs=None,
                 trace_requests='', client_parameters=None):
        """Service Clients provider

        Instantiate a `ServiceClients` object, from a set of credentials and an
        identity URI. The identity version is inferred from the credentials
        object. Optionally auth scope can be provided.

        A few parameters can be given a value which is applied as default
        for all service clients: region, dscv, ca_certs, trace_requests.

        Parameters dscv, ca_certs and trace_requests all apply to the auth
        provider as well as any service clients provided by this manager.

        Any other client parameter must be set via client_parameters.
        The list of available parameters is defined in the service clients
        interfaces. For reference, most clients will accept 'region',
        'service', 'endpoint_type', 'build_timeout' and 'build_interval', which
        are all inherited from RestClient.

        The `config` module in Tempest exposes an helper function
        `service_client_config` that can be used to extract from configuration
        a dictionary ready to be injected in kwargs.

        Exceptions are:
        - Token clients for 'identity' have a very different interface
        - Volume client for 'volume' accepts 'default_volume_size'
        - Servers client from 'compute' accepts 'enable_instance_password'

        Examples:

            >>> identity_params = config.service_client_config('identity')
            >>> params = {
            >>>     'identity': identity_params,
            >>>     'compute': {'region': 'region2'}}
            >>> manager = lib_manager.Manager(
            >>>     my_creds, identity_uri, client_parameters=params)

        :param credentials: An instance of `auth.Credentials`
        :param identity_uri: URI of the identity API. This should be a
                             mandatory parameter, and it will so soon.
        :param region: Default value of region for service clients.
        :param scope: default scope for tokens produced by the auth provider
        :param disable_ssl_certificate_validation Applies to auth and to all
                                                  service clients.
        :param ca_certs Applies to auth and to all service clients.
        :param trace_requests Applies to auth and to all service clients.
        :param client_parameters Dictionary with parameters for service
            clients. Keys of the dictionary are the service client service
            name, as declared in `service_clients.available_modules()` except
            for the version. Values are dictionaries of parameters that are
            going to be passed to all clients in the service client module.

        Examples:

            >>> params_service_x = {'param_name': 'param_value'}
            >>> client_parameters = { 'service_x': params_service_x }

            >>> params_service_y = config.service_client_config('service_y')
            >>> client_parameters['service_y'] = params_service_y

        """
        self._registered_services = set([])
        self.credentials = credentials
        self.identity_uri = identity_uri
        if not identity_uri:
            raise exceptions.InvalidCredentials(
                'ServiceClients requires a non-empty identity_uri.')
        self.region = region
        # Check if passed or default credentials are valid
        if not self.credentials.is_valid():
            raise exceptions.InvalidCredentials()
        # Get the identity classes matching the provided credentials
        # TODO(andreaf) Define a new interface in Credentials to get
        # the API version from an instance
        identity = [(k, auth.IDENTITY_VERSION[k][1]) for k in
                    auth.IDENTITY_VERSION.keys() if
                    isinstance(self.credentials, auth.IDENTITY_VERSION[k][0])]
        # Zero matches or more than one are both not valid.
        if len(identity) != 1:
            raise exceptions.InvalidCredentials()
        self.auth_version, auth_provider_class = identity[0]
        self.dscv = disable_ssl_certificate_validation
        self.ca_certs = ca_certs
        self.trace_requests = trace_requests
        # Creates an auth provider for the credentials
        self.auth_provider = auth_provider_class(
            self.credentials, self.identity_uri, scope=scope,
            disable_ssl_certificate_validation=self.dscv,
            ca_certs=self.ca_certs, trace_requests=self.trace_requests)
        # Setup some defaults for client parameters of registered services
        client_parameters = client_parameters or {}
        self.parameters = {}
        # Parameters are provided for unversioned services
        unversioned_services = set(
            [x.split('.')[0] for x in available_modules()])
        for service in unversioned_services:
            self.parameters[service] = self._setup_parameters(
                client_parameters.pop(service, {}))
        # Check that no client parameters was supplied for unregistered clients
        if client_parameters:
            raise exceptions.UnknownServiceClient(
                services=list(client_parameters.keys()))

        # Register service clients owned by tempest
        for service in tempest_modules():
            if service in list(client_modules_by_service_name):
                attribute = service.replace('.', '_')
                configs = service.split('.')[0]
                module = client_modules_by_service_name[service]
                self.register_service_client_module(
                    attribute, service, module.__name__,
                    module.__all__, **self.parameters[configs])

        # Register service clients from plugins
        clients_registry = clients.ClientsRegistry()
        plugin_service_clients = clients_registry.get_service_clients()
        for plugin in plugin_service_clients:
            service_clients = plugin_service_clients[plugin]
            # Each plugin returns a list of service client parameters
            for service_client in service_clients:
                # NOTE(andreaf) If a plugin cannot register, stop the
                # registration process, log some details to help
                # troubleshooting, and re-raise
                try:
                    self.register_service_client_module(**service_client)
                except Exception:
                    LOG.exception(
                        'Failed to register service client from plugin %s '
                        'with parameters %s' % (plugin, service_client))
                    raise

    def register_service_client_module(self, name, service_version,
                                       module_path, client_names, **kwargs):
        """Register a service client module

        Initiates a client factory for the specified module, using this
        class auth_provider, and accessible via a `name` attribute in the
        service client.

        :param name: Name used to access the client
        :param service_version: Name of the service complete with version.
            Used to track registered services. When a plugin implements it,
            it can be used by other plugins to obtain their configuration.
        :param module_path: Path to module that includes all service clients.
            All service client classes must be exposed by a single module.
            If they are separated in different modules, defining __all__
            in the root module can help, similar to what is done by service
            clients in tempest.
        :param client_names: List or set of names of service client classes.
        :param kwargs: Extra optional parameters to be passed to all clients.
            ServiceClient provides defaults for region, dscv, ca_certs and
            trace_requests.
        :raise ServiceClientRegistrationException: if the provided name is
            already in use or if service_version is already registered.
        :raise ImportError: if module_path cannot be imported.
        """
        if hasattr(self, name):
            using_name = getattr(self, name)
            detailed_error = 'Module name already in use: %s' % using_name
            raise exceptions.ServiceClientRegistrationException(
                name=name, service_version=service_version,
                module_path=module_path, client_names=client_names,
                detailed_error=detailed_error)
        if service_version in self.registered_services:
            detailed_error = 'Service %s already registered.' % service_version
            raise exceptions.ServiceClientRegistrationException(
                name=name, service_version=service_version,
                module_path=module_path, client_names=client_names,
                detailed_error=detailed_error)
        params = dict(region=self.region,
                      disable_ssl_certificate_validation=self.dscv,
                      ca_certs=self.ca_certs,
                      trace_requests=self.trace_requests)
        params.update(kwargs)
        # Instantiate the client factory
        _factory = ClientsFactory(module_path=module_path,
                                  client_names=client_names,
                                  auth_provider=self.auth_provider,
                                  **params)
        # Adds the client factory to the service_client
        setattr(self, name, _factory)
        # Add the name of the new service in self.SERVICES for discovery
        self._registered_services.add(service_version)

    @property
    def registered_services(self):
        # TODO(andreaf) Temporary set needed until all services are migrated
        _non_migrated_services = tempest_modules() - set(
            client_modules_by_service_name)
        return self._registered_services | _non_migrated_services

    def _setup_parameters(self, parameters):
        """Setup default values for client parameters

        Region by default is the region passed as an __init__ parameter.
        Checks that no parameter for an unknown service is provided.
        """
        _parameters = {}
        # Use region from __init__
        if self.region:
            _parameters['region'] = self.region
        # Update defaults with specified parameters
        _parameters.update(parameters)
        # If any parameter is left, parameters for an unknown service were
        # provided as input. Fail rather than ignore silently.
        return _parameters
<commit_msg>Add : to docstring of service_clients<commit_after># Copyright 2012 OpenStack Foundation
# Copyright (c) 2016 Hewlett-Packard Enterprise Development Company, L.P.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import copy
import importlib
import inspect
import logging

from tempest.lib import auth
from tempest.lib import exceptions
from tempest.lib.services import clients
from tempest.lib.services import compute
from tempest.lib.services import image
from tempest.lib.services import network

LOG = logging.getLogger(__name__)

client_modules_by_service_name = {
    'compute': compute,
    'image.v1': image.v1,
    'image.v2': image.v2,
    'network': network
}

def tempest_modules():
    """List of service client modules available in Tempest.

    Provides a list of service modules available Tempest.
    """
    return set(['compute', 'identity.v2', 'identity.v3', 'image.v1',
                'image.v2', 'network', 'object-storage', 'volume.v1',
                'volume.v2', 'volume.v3'])

def available_modules():
    """List of service client modules available in Tempest and plugins

    The list of available modules can be used for automatic configuration.

    :raise PluginRegistrationException: if a plugin exposes a service_version
        already defined by Tempest or another plugin.

    Examples:

        >>> from tempest import config
        >>> params = {}
        >>> for service_version in available_modules():
        >>>     service = service_version.split('.')[0]
        >>>     params[service] = config.service_client_config(service)
        >>> service_clients = ServiceClients(creds, identity_uri,
        >>>                                  client_parameters=params)
    """
    extra_service_versions = set([])
    plugin_services = clients.ClientsRegistry().get_service_clients()
    for plugin_name in plugin_services:
        plug_service_versions = set([x['service_version'] for x in
                                     plugin_services[plugin_name]])
        # If a plugin exposes a duplicate service_version raise an exception
        if plug_service_versions:
            if not plug_service_versions.isdisjoint(extra_service_versions):
                detailed_error = (
                    'Plugin %s is trying to register a service %s already '
                    'claimed by another one' % (plugin_name,
                                                extra_service_versions &
                                                plug_service_versions))
                raise exceptions.PluginRegistrationException(
                    name=plugin_name, detailed_error=detailed_error)
            if not plug_service_versions.isdisjoint(tempest_modules()):
                detailed_error = (
                    'Plugin %s is trying to register a service %s already '
                    'claimed by a Tempest one' % (plugin_name,
                                                  tempest_modules() &
                                                  plug_service_versions))
                raise exceptions.PluginRegistrationException(
                    name=plugin_name, detailed_error=detailed_error)
        extra_service_versions |= plug_service_versions
    return tempest_modules() | extra_service_versions

class ClientsFactory(object):
    """Builds service clients for a service client module

    This class implements the logic of feeding service client parameters
    to service clients from a specific module. It allows setting the
    parameters once and obtaining new instances of the clients without the
    need of passing any parameter.

    ClientsFactory can be used directly, or consumed via the `ServiceClients`
    class, which manages the authorization part.
    """

    def __init__(self, module_path, client_names, auth_provider, **kwargs):
        """Initialises the client factory

        :param module_path: Path to module that includes all service clients.
            All service client classes must be exposed by a single module.
            If they are separated in different modules, defining __all__
            in the root module can help, similar to what is done by service
            clients in tempest.
        :param client_names: List or set of names of the service client
            classes.
        :param auth_provider: The auth provider used to initialise client.
        :param kwargs: Parameters to be passed to all clients. Parameters
            values can be overwritten when clients are initialised, but
            parameters cannot be deleted.
        :raise ImportError if the specified module_path cannot be imported

        Example:

            >>> # Get credentials and an auth_provider
            >>> clients = ClientsFactory(
            >>>     module_path='my_service.my_service_clients',
            >>>     client_names=['ServiceClient1', 'ServiceClient2'],
            >>>     auth_provider=auth_provider,
            >>>     service='my_service',
            >>>     region='region1')
            >>> my_api_client = clients.MyApiClient()
            >>> my_api_client_region2 = clients.MyApiClient(region='region2')

        """
        # Import the module. If it's not importable, the raised exception
        # provides good enough information about what happened
        _module = importlib.import_module(module_path)
        # If any of the classes is not in the module we fail
        for class_name in client_names:
            # TODO(andreaf) This always passes all parameters to all clients.
            # In future to allow clients to specify the list of parameters
            # that they accept based out of a list of standard ones.

            # Obtain the class
            klass = self._get_class(_module, class_name)
            final_kwargs = copy.copy(kwargs)

            # Set the function as an attribute of the factory
            setattr(self, class_name, self._get_partial_class(
                klass, auth_provider, final_kwargs))

    @classmethod
    def _get_partial_class(cls, klass, auth_provider, kwargs):

        # Define a function that returns a new class instance by
        # combining default kwargs with extra ones
        def partial_class(**later_kwargs):
            kwargs.update(later_kwargs)
            return klass(auth_provider=auth_provider, **kwargs)

        return partial_class

    @classmethod
    def _get_class(cls, module, class_name):
        klass = getattr(module, class_name, None)
        if not klass:
            msg = 'Invalid class name, %s is not found in %s'
            raise AttributeError(msg % (class_name, module))
        if not inspect.isclass(klass):
            msg = 'Expected a class, got %s of type %s instead'
            raise TypeError(msg % (klass, type(klass)))
        return klass

class ServiceClients(object):
    """Service client provider class

    The ServiceClients object provides a useful means for tests to access
    service clients configured for a specified set of credentials.
    It hides some of the complexity from the authorization and configuration
    layers.

    Examples:

        >>> from tempest import service_clients
        >>> johndoe = cred_provider.get_creds_by_role(['johndoe'])
        >>> johndoe_clients = service_clients.ServiceClients(johndoe,
        >>>                                                  identity_uri)
        >>> johndoe_servers = johndoe_clients.servers_client.list_servers()

    """
    # NOTE(andreaf) This class does not depend on tempest configuration
    # and its meant for direct consumption by external clients such as tempest
    # plugins. Tempest provides a wrapper class, `clients.Manager`, that
    # initialises this class using values from tempest CONF object. The wrapper
    # class should only be used by tests hosted in Tempest.

    def __init__(self, credentials, identity_uri, region=None, scope='project',
                 disable_ssl_certificate_validation=True, ca_certs=None,
                 trace_requests='', client_parameters=None):
        """Service Clients provider

        Instantiate a `ServiceClients` object, from a set of credentials and an
        identity URI. The identity version is inferred from the credentials
        object. Optionally auth scope can be provided.

        A few parameters can be given a value which is applied as default
        for all service clients: region, dscv, ca_certs, trace_requests.

        Parameters dscv, ca_certs and trace_requests all apply to the auth
        provider as well as any service clients provided by this manager.

        Any other client parameter must be set via client_parameters.
        The list of available parameters is defined in the service clients
        interfaces. For reference, most clients will accept 'region',
        'service', 'endpoint_type', 'build_timeout' and 'build_interval', which
        are all inherited from RestClient.

        The `config` module in Tempest exposes an helper function
        `service_client_config` that can be used to extract from configuration
        a dictionary ready to be injected in kwargs.

        Exceptions are:
        - Token clients for 'identity' have a very different interface
        - Volume client for 'volume' accepts 'default_volume_size'
        - Servers client from 'compute' accepts 'enable_instance_password'

        Examples:

            >>> identity_params = config.service_client_config('identity')
            >>> params = {
            >>>     'identity': identity_params,
            >>>     'compute': {'region': 'region2'}}
            >>> manager = lib_manager.Manager(
            >>>     my_creds, identity_uri, client_parameters=params)

        :param credentials: An instance of `auth.Credentials`
        :param identity_uri: URI of the identity API. This should be a
                             mandatory parameter, and it will so soon.
        :param region: Default value of region for service clients.
        :param scope: default scope for tokens produced by the auth provider
        :param disable_ssl_certificate_validation: Applies to auth and to all
                                                  service clients.
        :param ca_certs: Applies to auth and to all service clients.
        :param trace_requests: Applies to auth and to all service clients.
        :param client_parameters: Dictionary with parameters for service
            clients. Keys of the dictionary are the service client service
            name, as declared in `service_clients.available_modules()` except
            for the version. Values are dictionaries of parameters that are
            going to be passed to all clients in the service client module.

        Examples:

            >>> params_service_x = {'param_name': 'param_value'}
            >>> client_parameters = { 'service_x': params_service_x }

            >>> params_service_y = config.service_client_config('service_y')
            >>> client_parameters['service_y'] = params_service_y

        """
        self._registered_services = set([])
        self.credentials = credentials
        self.identity_uri = identity_uri
        if not identity_uri:
            raise exceptions.InvalidCredentials(
                'ServiceClients requires a non-empty identity_uri.')
        self.region = region
        # Check if passed or default credentials are valid
        if not self.credentials.is_valid():
            raise exceptions.InvalidCredentials()
        # Get the identity classes matching the provided credentials
        # TODO(andreaf) Define a new interface in Credentials to get
        # the API version from an instance
        identity = [(k, auth.IDENTITY_VERSION[k][1]) for k in
                    auth.IDENTITY_VERSION.keys() if
                    isinstance(self.credentials, auth.IDENTITY_VERSION[k][0])]
        # Zero matches or more than one are both not valid.
        if len(identity) != 1:
            raise exceptions.InvalidCredentials()
        self.auth_version, auth_provider_class = identity[0]
        self.dscv = disable_ssl_certificate_validation
        self.ca_certs = ca_certs
        self.trace_requests = trace_requests
        # Creates an auth provider for the credentials
        self.auth_provider = auth_provider_class(
            self.credentials, self.identity_uri, scope=scope,
            disable_ssl_certificate_validation=self.dscv,
            ca_certs=self.ca_certs, trace_requests=self.trace_requests)
        # Setup some defaults for client parameters of registered services
        client_parameters = client_parameters or {}
        self.parameters = {}
        # Parameters are provided for unversioned services
        unversioned_services = set(
            [x.split('.')[0] for x in available_modules()])
        for service in unversioned_services:
            self.parameters[service] = self._setup_parameters(
                client_parameters.pop(service, {}))
        # Check that no client parameters was supplied for unregistered clients
        if client_parameters:
            raise exceptions.UnknownServiceClient(
                services=list(client_parameters.keys()))

        # Register service clients owned by tempest
        for service in tempest_modules():
            if service in list(client_modules_by_service_name):
                attribute = service.replace('.', '_')
                configs = service.split('.')[0]
                module = client_modules_by_service_name[service]
                self.register_service_client_module(
                    attribute, service, module.__name__,
                    module.__all__, **self.parameters[configs])

        # Register service clients from plugins
        clients_registry = clients.ClientsRegistry()
        plugin_service_clients = clients_registry.get_service_clients()
        for plugin in plugin_service_clients:
            service_clients = plugin_service_clients[plugin]
            # Each plugin returns a list of service client parameters
            for service_client in service_clients:
                # NOTE(andreaf) If a plugin cannot register, stop the
                # registration process, log some details to help
                # troubleshooting, and re-raise
                try:
                    self.register_service_client_module(**service_client)
                except Exception:
                    LOG.exception(
                        'Failed to register service client from plugin %s '
                        'with parameters %s' % (plugin, service_client))
                    raise

    def register_service_client_module(self, name, service_version,
                                       module_path, client_names, **kwargs):
        """Register a service client module

        Initiates a client factory for the specified module, using this
        class auth_provider, and accessible via a `name` attribute in the
        service client.

        :param name: Name used to access the client
        :param service_version: Name of the service complete with version.
            Used to track registered services. When a plugin implements it,
            it can be used by other plugins to obtain their configuration.
        :param module_path: Path to module that includes all service clients.
            All service client classes must be exposed by a single module.
            If they are separated in different modules, defining __all__
            in the root module can help, similar to what is done by service
            clients in tempest.
        :param client_names: List or set of names of service client classes.
        :param kwargs: Extra optional parameters to be passed to all clients.
            ServiceClient provides defaults for region, dscv, ca_certs and
            trace_requests.
        :raise ServiceClientRegistrationException: if the provided name is
            already in use or if service_version is already registered.
        :raise ImportError: if module_path cannot be imported.
        """
        if hasattr(self, name):
            using_name = getattr(self, name)
            detailed_error = 'Module name already in use: %s' % using_name
            raise exceptions.ServiceClientRegistrationException(
                name=name, service_version=service_version,
                module_path=module_path, client_names=client_names,
                detailed_error=detailed_error)
        if service_version in self.registered_services:
            detailed_error = 'Service %s already registered.' % service_version
            raise exceptions.ServiceClientRegistrationException(
                name=name, service_version=service_version,
                module_path=module_path, client_names=client_names,
                detailed_error=detailed_error)
        params = dict(region=self.region,
                      disable_ssl_certificate_validation=self.dscv,
                      ca_certs=self.ca_certs,
                      trace_requests=self.trace_requests)
        params.update(kwargs)
        # Instantiate the client factory
        _factory = ClientsFactory(module_path=module_path,
                                  client_names=client_names,
                                  auth_provider=self.auth_provider,
                                  **params)
        # Adds the client factory to the service_client
        setattr(self, name, _factory)
        # Add the name of the new service in self.SERVICES for discovery
        self._registered_services.add(service_version)

    @property
    def registered_services(self):
        # TODO(andreaf) Temporary set needed until all services are migrated
        _non_migrated_services = tempest_modules() - set(
            client_modules_by_service_name)
        return self._registered_services | _non_migrated_services

    def _setup_parameters(self, parameters):
        """Setup default values for client parameters

        Region by default is the region passed as an __init__ parameter.
        Checks that no parameter for an unknown service is provided.
        """
        _parameters = {}
        # Use region from __init__
        if self.region:
            _parameters['region'] = self.region
        # Update defaults with specified parameters
        _parameters.update(parameters)
        # If any parameter is left, parameters for an unknown service were
        # provided as input. Fail rather than ignore silently.
        return _parameters
<|endoftext|>


<commit_before>import datetime
import errno
import os
import stat
import sys
import time
import beaver.transports as transports

class Worker(object):
    """Looks for changes in all files of a directory.
    This is useful for watching log file changes in real-time.
    It also supports files rotation.

    Example:

    >>> def callback(filename, lines):
    ...     print filename, lines
    ...
    >>> l = Worker(args, callback, ["log", "txt"], tail_lines=0)
    >>> l.loop()
    """

    def __init__(self, args, callback, extensions=["log"], tail_lines=0):
        """Arguments:

        (str) @args:
            set of arguments for the worker

        (callable) @callback:
            a function which is called every time a new line in a
            file being watched is found;
            this is called with "filename" and "lines" arguments.

        (list) @extensions:
            only watch files with these extensions

        (int) @tail_lines:
            read last N lines from files being watched before starting
        """
        self.files_map = {}
        self.callback = callback
        self.extensions = extensions
        self.config = args

        if self.config.path is not None:
            self.folder = os.path.realpath(args.path)
            assert os.path.isdir(self.folder), "%s does not exists" \
                                            % self.folder
        assert callable(callback)
        self.update_files()
        # The first time we run the script we move all file markers at EOF.
        # In case of files created afterwards we don't do this.
        for id, file in self.files_map.iteritems():
            file.seek(os.path.getsize(file.name))  # EOF
            if tail_lines:
                lines = self.tail(file.name, tail_lines)
                if lines:
                    self.callback(file.name, lines)

    def __del__(self):
        self.close()

    def loop(self, interval=0.1, async=False):
        """Start the loop.
        If async is True make one loop then return.
        """
        while 1:
            self.update_files()
            for fid, file in list(self.files_map.iteritems()):
                self.readfile(file)
            if async:
                return
            time.sleep(interval)

    def log(self, line):
        """Log when a file is un/watched"""
        print line

    def listdir(self):
        """List directory and filter files by extension.
        You may want to override this to add extra logic or
        globbling support.
        """
        ls = os.listdir(self.folder)
        if self.extensions:
            return [x for x in ls if os.path.splitext(x)[1][1:] \
                                           in self.extensions]
        else:
            return ls

    @staticmethod
    def tail(fname, window):
        """Read last N lines from file fname."""
        try:
            f = open(fname, 'r')
        except IOError, err:
            if err.errno == errno.ENOENT:
                return []
            else:
                raise
        else:
            BUFSIZ = 1024
            f.seek(0, os.SEEK_END)
            fsize = f.tell()
            block = -1
            data = ""
            exit = False
            while not exit:
                step = (block * BUFSIZ)
                if abs(step) >= fsize:
                    f.seek(0)
                    exit = True
                else:
                    f.seek(step, os.SEEK_END)
                data = f.read().strip()
                if data.count('\n') >= window:
                    break
                else:
                    block -= 1
            return data.splitlines()[-window:]

    def update_files(self):
        ls = []
        files = []
        if self.config.files is not None:
            for name in self.config.files:
                files.append(os.path.realpath(name))
        else:
            for name in self.listdir():
                files.append(os.path.realpath(os.path.join(self.folder, name)))

        for absname in files:
            try:
                st = os.stat(absname)
            except EnvironmentError, err:
                if err.errno != errno.ENOENT:
                    raise
            else:
                if not stat.S_ISREG(st.st_mode):
                    continue
                fid = self.get_file_id(st)
                ls.append((fid, absname))

        # check existent files
        for fid, file in list(self.files_map.iteritems()):
            try:
                st = os.stat(file.name)
            except EnvironmentError, err:
                if err.errno == errno.ENOENT:
                    self.unwatch(file, fid)
                else:
                    raise
            else:
                if fid != self.get_file_id(st):
                    # same name but different file (rotation); reload it.
                    self.unwatch(file, fid)
                    self.watch(file.name)

        # add new ones
        for fid, fname in ls:
            if fid not in self.files_map:
                self.watch(fname)

    def readfile(self, file):
        lines = file.readlines()
        if lines:
            self.callback(file.name, lines)

    def watch(self, fname):
        try:
            file = open(fname, "r")
            fid = self.get_file_id(os.stat(fname))
        except EnvironmentError, err:
            if err.errno != errno.ENOENT:
                raise
        else:
            self.log("[{0}] {1} - watching logfile {2}".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%i:%s'), fid, fname))
            self.files_map[fid] = file

    def unwatch(self, file, fid):
        # file no longer exists; if it has been renamed
        # try to read it for the last time in case the
        # log rotator has written something in it.
        lines = self.readfile(file)
        self.log("[{0}] {1} - un-watching logfile {2}".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%i:%s'), fid, file.name))
        del self.files_map[fid]
        if lines:
            self.callback(file.name, lines)

    @staticmethod
    def get_file_id(st):
        return "%xg%x" % (st.st_dev, st.st_ino)

    def close(self):
        for id, file in self.files_map.iteritems():
            file.close()
        self.files_map.clear()

def run_worker(options):
    if options.transport not in ['amqp', 'redis', 'stdout']:
        raise Exception('Invalid transport {0}'.format(options.transport))

    if options.transport == 'amqp':
        transport = transports.AmqpTransport()
    if options.transport == 'redis':
        transport = transports.RedisTransport()
    if options.transport == 'stdout':
        transport = transports.StdoutTransport()

    try:
        l = Worker(options, transport.callback)
        l.loop()
    except KeyboardInterrupt:
        print("\nShutting down. Please wait.")
        transport.interrupt()
        print("Shutdown complete.")
        sys.exit(0)
    except Exception, e:
        print("Unhandled Exception: %s" % str(e))
        transport.unhandled()
        sys.exit(1)
<commit_msg>Updated logging statements<commit_after>import datetime
import errno
import os
import stat
import sys
import time
import beaver.transports as transports

class Worker(object):
    """Looks for changes in all files of a directory.
    This is useful for watching log file changes in real-time.
    It also supports files rotation.

    Example:

    >>> def callback(filename, lines):
    ...     print filename, lines
    ...
    >>> l = Worker(args, callback, ["log", "txt"], tail_lines=0)
    >>> l.loop()
    """

    def __init__(self, args, callback, extensions=["log"], tail_lines=0):
        """Arguments:

        (str) @args:
            set of arguments for the worker

        (callable) @callback:
            a function which is called every time a new line in a
            file being watched is found;
            this is called with "filename" and "lines" arguments.

        (list) @extensions:
            only watch files with these extensions

        (int) @tail_lines:
            read last N lines from files being watched before starting
        """
        self.files_map = {}
        self.callback = callback
        self.extensions = extensions
        self.config = args

        if self.config.path is not None:
            self.folder = os.path.realpath(args.path)
            assert os.path.isdir(self.folder), "%s does not exists" \
                                            % self.folder
        assert callable(callback)
        self.update_files()
        # The first time we run the script we move all file markers at EOF.
        # In case of files created afterwards we don't do this.
        for id, file in self.files_map.iteritems():
            file.seek(os.path.getsize(file.name))  # EOF
            if tail_lines:
                lines = self.tail(file.name, tail_lines)
                if lines:
                    self.callback(file.name, lines)

    def __del__(self):
        self.close()

    def loop(self, interval=0.1, async=False):
        """Start the loop.
        If async is True make one loop then return.
        """
        while 1:
            self.update_files()
            for fid, file in list(self.files_map.iteritems()):
                self.readfile(file)
            if async:
                return
            time.sleep(interval)

    def log(self, line):
        """Log when a file is un/watched"""
        print "[{0}] {1}".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%i:%s'), line)

    def listdir(self):
        """List directory and filter files by extension.
        You may want to override this to add extra logic or
        globbling support.
        """
        ls = os.listdir(self.folder)
        if self.extensions:
            return [x for x in ls if os.path.splitext(x)[1][1:] \
                                           in self.extensions]
        else:
            return ls

    @staticmethod
    def tail(fname, window):
        """Read last N lines from file fname."""
        try:
            f = open(fname, 'r')
        except IOError, err:
            if err.errno == errno.ENOENT:
                return []
            else:
                raise
        else:
            BUFSIZ = 1024
            f.seek(0, os.SEEK_END)
            fsize = f.tell()
            block = -1
            data = ""
            exit = False
            while not exit:
                step = (block * BUFSIZ)
                if abs(step) >= fsize:
                    f.seek(0)
                    exit = True
                else:
                    f.seek(step, os.SEEK_END)
                data = f.read().strip()
                if data.count('\n') >= window:
                    break
                else:
                    block -= 1
            return data.splitlines()[-window:]

    def update_files(self):
        ls = []
        files = []
        if self.config.files is not None:
            for name in self.config.files:
                files.append(os.path.realpath(name))
        else:
            for name in self.listdir():
                files.append(os.path.realpath(os.path.join(self.folder, name)))

        for absname in files:
            try:
                st = os.stat(absname)
            except EnvironmentError, err:
                if err.errno != errno.ENOENT:
                    raise
            else:
                if not stat.S_ISREG(st.st_mode):
                    continue
                fid = self.get_file_id(st)
                ls.append((fid, absname))

        # check existent files
        for fid, file in list(self.files_map.iteritems()):
            try:
                st = os.stat(file.name)
            except EnvironmentError, err:
                if err.errno == errno.ENOENT:
                    self.unwatch(file, fid)
                else:
                    raise
            else:
                if fid != self.get_file_id(st):
                    # same name but different file (rotation); reload it.
                    self.unwatch(file, fid)
                    self.watch(file.name)

        # add new ones
        for fid, fname in ls:
            if fid not in self.files_map:
                self.watch(fname)

    def readfile(self, file):
        lines = file.readlines()
        if lines:
            self.callback(file.name, lines)

    def watch(self, fname):
        try:
            file = open(fname, "r")
            fid = self.get_file_id(os.stat(fname))
        except EnvironmentError, err:
            if err.errno != errno.ENOENT:
                raise
        else:
            self.log("[{0}] - watching logfile {1}".format(fid, fname))
            self.files_map[fid] = file

    def unwatch(self, file, fid):
        # file no longer exists; if it has been renamed
        # try to read it for the last time in case the
        # log rotator has written something in it.
        lines = self.readfile(file)
        self.log("[{0}] - un-watching logfile {1}".format(fid, file.name))
        del self.files_map[fid]
        if lines:
            self.callback(file.name, lines)

    @staticmethod
    def get_file_id(st):
        return "%xg%x" % (st.st_dev, st.st_ino)

    def close(self):
        for id, file in self.files_map.iteritems():
            file.close()
        self.files_map.clear()

def run_worker(options):
    if options.transport not in ['amqp', 'redis', 'stdout']:
        raise Exception('Invalid transport {0}'.format(options.transport))

    if options.transport == 'amqp':
        transport = transports.AmqpTransport()
    if options.transport == 'redis':
        transport = transports.RedisTransport()
    if options.transport == 'stdout':
        transport = transports.StdoutTransport()

    try:
        print "[{0}] Starting worker...".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%i:%s'))
        l = Worker(options, transport.callback)
        print "[{0}] Working...".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%i:%s'))
        l.loop()
    except KeyboardInterrupt:
        print "\n[{0}] Shutting down. Please wait.".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%i:%s'))
        transport.interrupt()
        print "[{0}] Shutdown complete.".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%i:%s'))
        sys.exit(0)
    except Exception, e:
        print "[{0}] Unhandled Exception: {1}".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%i:%s'), str(e))
        transport.unhandled()
        sys.exit(1)
<|endoftext|>


<commit_before>from legPct import legPct, runTime
import numpy as np
import os
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.formula.api as smf

def deadheadPct(busRun):
    '''
    busRun: a single bus run schedule
    	with columns [ETA, TotalPass]
    returns: a float percent
    '''
    busRun = legPct(busRun)
    # print 'this should be 1: ' + str(sum(busRun.PctOfRunTime)) # debug
    deadheads = busRun[(busRun.TotalPass == 0)]
    return sum(deadheads.PctOfRunTime)

def deadheadVsCost(schedule):
    '''
    schedule: a full schedule
    with columns [ServiceDate, Run, Activity, ETA, NumOn, TotalPass,]
    '''
    uniqueDR = schedule[['ServiceDate', 'Run']].drop_duplicates()
    toKeep = []
    print(uniqueDR)
    numOfRuns = len(uniqueDR)
    deadhead = []
    cost = []
    breakdownDate = []
    breakdownRun = []
    loopcount = 0
    numDropped = 0

    # get deadhead pct for each Date/Run pair
    for row in uniqueDR.iterrows():
        busRun = schedule[(schedule['ServiceDate'] == row[1].ServiceDate) &
                 (schedule['Run'] == row[1].Run)]

        totalPass = sum(busRun.NumOn)
        if 8 in busRun.Activity.unique():
            print 'warning! run ' + str(row[1].Run) + ' on ' + str(row[1].ServiceDate) + ' breaks down.'
            toKeep.append(False)
            breakdownRun.append(row[1].Run)
            breakdownDate.append(row[1].ServiceDate)
        elif totalPass > 0:
        # approximates average cost per boarding
            cost.append(float(runTime(busRun['ETA'])) / totalPass)
            deadhead.append(deadheadPct(busRun[['ETA', 'TotalPass']]))
            toKeep.append(True)
        else:
            print 'warning! run ' + str(row[1].Run) + ' on ' + str(row[1].ServiceDate) + ' has no passengers.'
            toKeep.append(False)
            numDropped = numDropped + 1

        loopcount = loopcount + 1
        os.system(['clear', 'cls'][os.name == 'nt'])
        print row[1].Run
        print row[1].ServiceDate
        print str(float(loopcount)/numOfRuns * 100) + '%' + ' done\n'

    print cost
    print deadhead
    print('')
    print('Number "dropped": ' + str(numDropped))
    uniqueDRLen = len(uniqueDR)
    print('Number needed: ' + str(uniqueDRLen - len(cost)))
    if False in toKeep:
        print('Drop in toKeep found.')

    # remove rows with bad data
    uniqueDR = uniqueDR[toKeep]
    print('Number dropped: ' + str(uniqueDRLen - len(uniqueDR)))

    # write breakdowns to file
    pd.DataFrame({'ServiceDate' : breakdownDate,
                 'Run' : breakdownRun}).to_csv('../../data/4mo_broken_buses.csv')

    # write results to file
    cost = np.asarray(cost)
    deadhead = np.asarray(deadhead)
    uniqueDR['CostProxy'] = cost
    uniqueDR['PctDeadhead'] = deadhead
    # IMPORTANT: change file name if not 4mo
    uniqueDR.to_csv('../../data/4mo_deadhead_results.csv', index=False)

    # regressions
    results = smf.ols('cost ~ deadhead', data=uniqueDR).fit()
    print results.summary()
    results = smf.ols('np.log(cost) ~ deadhead', data=uniqueDR).fit()
    print results.summary()

    # plots
    # plt.hist(deadhead)
    # plt.savefig('../output/deadheadHist.png')
    # plt.close()
    # plt.plot(deadhead, cost, 'ro')
    # plt.xlabel('Percent Deadhead')
    # plt.ylabel('Length of Trip / Number of passengers (seconds)')
    # plt.savefig('../output/figure.png')
    # plt.close()

def main():
    data = pd.read_csv('../../data/UW_Trip_Data_4mo_QC_capacity.csv')
    #data.columns.values[24] = 'TotalPass'
    busRun = data[(data.Run == data.Run[0]) & (data.ServiceDate == data.ServiceDate[0])]
    print str(deadheadPct(busRun)) + '\n'
    deadheadVsCost(data[['ServiceDate', 'Run', 'Activity', 'ETA', 'NumOn', 'TotalPass']])
    #[data.ServiceDate == '0015-04-13'] ^insert this before the [ for a single day

if __name__ == '__main__':
      main()<commit_msg>now actually final<commit_after>from legPct import legPct, runTime
import numpy as np
import os
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.formula.api as smf

def deadheadPct(busRun):
    '''
    busRun: a single bus run schedule
    	with columns [ETA, TotalPass]
    returns: a float percent
    '''
    busRun = legPct(busRun)
    # print 'this should be 1: ' + str(sum(busRun.PctOfRunTime)) # debug
    deadheads = busRun[(busRun.TotalPass == 0)]
    return sum(deadheads.PctOfRunTime)

def deadheadVsCost(schedule):
    '''
    schedule: a full schedule
    with columns [ServiceDate, Run, Activity, ETA, NumOn, TotalPass,]
    '''
    uniqueDR = schedule[['ServiceDate', 'Run']].drop_duplicates()
    toKeep = []
    print(uniqueDR)
    numOfRuns = len(uniqueDR)
    deadhead = []
    cost = []
    breakdownDate = []
    breakdownRun = []
    loopcount = 0
    numDropped = 0

    # get deadhead pct for each Date/Run pair
    for row in uniqueDR.iterrows():
        busRun = schedule[(schedule['ServiceDate'] == row[1].ServiceDate) &
                 (schedule['Run'] == row[1].Run)]

        totalPass = sum(busRun.NumOn)
        if 8 in busRun.Activity.unique():
            print 'warning! run ' + str(row[1].Run) + ' on ' + str(row[1].ServiceDate) + ' breaks down.'
            toKeep.append(False)
            breakdownRun.append(row[1].Run)
            breakdownDate.append(row[1].ServiceDate)
        elif totalPass > 0:
        # approximates average cost per boarding
            cost.append(float(runTime(busRun['ETA'])) / totalPass)
            deadhead.append(deadheadPct(busRun[['ETA', 'TotalPass']]))
            toKeep.append(True)
        else:
            print 'warning! run ' + str(row[1].Run) + ' on ' + str(row[1].ServiceDate) + ' has no passengers.'
            toKeep.append(False)
            numDropped = numDropped + 1

        loopcount = loopcount + 1
        os.system(['clear', 'cls'][os.name == 'nt'])
        print row[1].Run
        print row[1].ServiceDate
        print str(float(loopcount)/numOfRuns * 100) + '%' + ' done\n'

    print cost
    print deadhead
    print('')
    print('Number "dropped": ' + str(numDropped))
    uniqueDRLen = len(uniqueDR)
    print('Number needed: ' + str(uniqueDRLen - len(cost)))
    if False in toKeep:
        print('Drop in toKeep found.')

    # remove rows with bad data
    uniqueDR = uniqueDR[toKeep]
    print('Number dropped: ' + str(uniqueDRLen - len(uniqueDR)))

    # write breakdowns to file
    pd.DataFrame({'ServiceDate' : breakdownDate,
                 'Run' : breakdownRun}).to_csv('../../data/4mo_broken_buses.csv')

    # write results to file
    cost = np.asarray(cost)
    deadhead = np.asarray(deadhead)
    uniqueDR['CostProxy'] = cost
    uniqueDR['PctDeadhead'] = deadhead
    # IMPORTANT: change file name if not 4mo
    uniqueDR.to_csv('../../data/4mo_deadhead_results.csv', index=False)

    # regressions
    results = smf.ols('cost ~ deadhead', data=uniqueDR).fit()
    print results.summary()
    results = smf.ols('np.log(cost) ~ deadhead', data=uniqueDR).fit()
    print results.summary()

    # plots
    plt.hist(deadhead)
    plt.savefig('../output/deadheadHist.png')
    plt.close()
    plt.plot(deadhead, cost, 'ro')
    plt.xlabel('Percent Deadhead')
    plt.ylabel('Length of Trip / Number of passengers (seconds)')
    plt.savefig('../output/figure.png')
    plt.close()

def main():
    data = pd.read_csv('../../data/UW_Trip_Data_4mo_QC_capacity.csv')
    #data.columns.values[24] = 'TotalPass'
    busRun = data[(data.Run == data.Run[0]) & (data.ServiceDate == data.ServiceDate[0])]
    print str(deadheadPct(busRun)) + '\n'
    deadheadVsCost(data[['ServiceDate', 'Run', 'Activity', 'ETA', 'NumOn', 'TotalPass']])
    #[data.ServiceDate == '0015-04-13'] ^insert this before the [ for a single day

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