<commit_before>#!/usr/bin/env python
# coding=utf-8

import os
import cgi
import Cookie
import re
import sys
import httplib
import json

class Httprequest(object):

    def __init__(self, meth, uri, query_str, host, headers, cookies=""):
        self.meth = meth
        self.uri = uri
        self.cookies_str = cookies
        self.host = host
        self.headers = headers

        self.path = uri.split("?", 1)[0]
        self.args = {}
        self.files = {}

        form = cgi.FieldStorage()
        for key in form.keys():
            item = form[key]
            if item.file:
                self.files[key] = item

            self.args[key] = form.getlist(key)

    def write(self, text):
        sys.stdout.write(text)

    @property
    def get_cookies(self):
        if not hasattr(self, "_cookies"):
            self._cookies = Cookie.SimpleCookie()
            if self.cookies_str:
                self._cookies.load(self.cookies_str)
        return self._cookies

class TemplateWrapper(object):

    def __init__(self):
        pass

    @staticmethod
    def wrap_html(path, params):
        body = open(path, 'r').read()
        if params:
            body = body % params
        return body

class BaseHandler(object):

    def __init__(self, application, request, **kwargs):
        super(BaseHandler, self).__init__()
        self.app = application
        self.request = request

        self.clear()

    def clear(self):
        self._headers = {
            "Content-Type": "text/html; charset=UTF-8"
        }
        self._status_code = 200

    def set_status(self, status):
        assert status in httplib.responses
        self._status_code = status

    def set_header(self, name, value):
        self._headers[name] = str(value)

    def clear_header(self, name):
        if name in self._headers:
            del self._headers[name]

    def get_cookies(self):
        return self.request.get_cookies()

    def set_cookie(self, name, value, expires = None, expires_days = None, max_age = None, path = "/"):

        if not hasattr(self, "_new_cookie"):
            self._new_cookie = Cookie.SimpleCookie()

    def gen_headers(self):
        status_expr = httplib.responses[self._status_code]
        header_line = ["Status: %d %s" % (self._status_code, status_expr)]

        for name, value in self._headers.iteritems():
            header_line.append("%s: %s" % (name, value))

        #if hasattr(self, "_new_cookie"):
            #for cookie in self._new_cookie.values():
            #    header_line.append("Set-Cookie: " + cookie.OutputString(None))

        return "\r\n".join(header_line) + "\r\n\r\n"

    def write(self, text):
        if isinstance(text, dict):
            #text = json_encode(text)

            self.set_header("Content-Type", "application/json; charset=UTF-8")

        resp_body = text
        resp_header = self.gen_headers()
        self.request.write(resp_header)
        self.request.write(resp_body)

    def wrap_html(self, path, params=None):
        return TemplateWrapper.wrap_html(path, params)

class ErrorHandler(BaseHandler):

    def get(self):
        self.set_status(404)

        body = "Page Not Found"
        self.write(body)

class Application(object):

    """web framework for the application"""

    def __init__(self, vars, urls=(), config=()):
        self._urls = urls
        self._config = config
        self._vars = vars

    def get_request(self):
        env = os.environ

        headers = []

        request = Httprequest(
            unicode(env["REQUEST_METHOD"], encoding="utf-8"),
            unicode(env["REQUEST_URI"], encoding="utf-8"),
            unicode(env.get("QUERY_STRING"), encoding="utf-8"),
            unicode(env.get("HTTP_HOST"), encoding="utf-8"),
            headers,
            env.get("HTTP_COOKIE")

        )

        return request

    def delegate(self):
        path = self._request.path
        method = self._request.meth

        for pattern, name in self._urls:
            m = re.match('^' + pattern + '$', path)
            if m:
                args = m.groups()
                func = method.lower()
                cls = self._vars.get(name)

                if hasattr(cls, func):
                    handler = cls(self, self._request)
                    meth = getattr(cls, func)
                    return meth(handler, *args)

        handler = ErrorHandler(self, self._request)
        return handler.get()

    def handle(self):
        self._request = self.get_request()
        self.delegate()

    def run(self):
        self.handle()
<commit_msg>set cookie added, get args added<commit_after>#!/usr/bin/env python
# coding=utf-8

import os
import cgi
import Cookie
import re
import sys
import httplib
import datetime
import calendar
import email.utils

class Httprequest(object):

    def __init__(self, meth, uri, query_str, host, headers, cookies=""):
        self.meth = meth
        self.uri = uri
        self.cookies_str = cookies
        self.host = host
        self.headers = headers

        self.path = uri.split("?", 1)[0]
        self.args = {}
        self.files = {}

        form = cgi.FieldStorage()
        for key in form.keys():
            item = form[key]
            if item.file:
                self.files[key] = item

            self.args[key] = form.getlist(key)

    def write(self, text):
        sys.stdout.write(text)

    @property
    def get_cookies(self):
        if not hasattr(self, "_cookies"):
            self._cookies = Cookie.SimpleCookie()
            if self.cookies_str:
                self._cookies.load(self.cookies_str)
        return self._cookies

class TemplateWrapper(object):

    def __init__(self):
        pass

    @staticmethod
    def wrap_html(path, params):
        body = open(path, 'r').read()
        if params:
            body = body % params
        return body

class BaseHandler(object):

    def __init__(self, application, request, **kwargs):
        super(BaseHandler, self).__init__()
        self.app = application
        self.request = request

        self.clear()

    def clear(self):
        self._headers = {
            "Content-Type": "text/html; charset=UTF-8"
        }
        self._status_code = 200

    def set_status(self, status):
        assert status in httplib.responses
        self._status_code = status

    def set_header(self, name, value):
        self._headers[name] = str(value)

    def clear_header(self, name):
        if name in self._headers:
            del self._headers[name]

    def get_cookies(self):
        return self.request.get_cookies()

    def set_cookie(self, name, value, expires=None,
                   expires_days=None, max_age=None, path="/"):
        if not hasattr(self, "_new_cookie"):
            self._new_cookie = Cookie.SimpleCookie()
        self._new_cookie[name] = value
        if path:
            self._new_cookie[name][path] = path
        if max_age:
            self._new_cookie[name][max_age] = max_age
        if expires_days is not None and not expires:
            expires = datetime.datetime.utcnow() + datetime.timedelta(
                days=expires_days)
        if expires:
            timestamp = calendar.timegm(expires.utctimetuple)
            format_timestamp = email.utils.formatdate(
                timestamp, localtime=False, usegmt=True)
            self._new_cookie[name][expires] = format_timestamp

    def clear_cookie(self, name):
        # 100 days for expires
        expires = datetime.datetime.utcnow() - datetime.timedelta(days = 100)
        self.set_cookie(name, value = "", expires = expires)

    def clear_cookies(self):
        all_cookies = self.get_cookies()
        for name in all_cookies.iterkeys():
            self.clear_cookie(name)

    def gen_headers(self):
        status_expr = httplib.responses[self._status_code]
        header_line = ["Status: %d %s" % (self._status_code, status_expr)]

        for name, value in self._headers.iteritems():
            header_line.append("%s: %s" % (name, value))

        if hasattr(self, "_new_cookie"):
            for cookie in self._new_cookie.values():
                header_line.append("Set-Cookie: " + cookie.OutputString(None))

        return "\r\n".join(header_line) + "\r\n\r\n"

    def get_args(self, name, default = []):
        args = []
        for arg in self.request.args.get(name, []):
            args.append(arg)
        return args

    def write(self, text):
        if isinstance(text, dict):
            #text = json_encode(text)

            self.set_header("Content-Type", "application/json; charset=UTF-8")

        resp_body = text
        resp_header = self.gen_headers()
        self.request.write(resp_header)
        self.request.write(resp_body)

    def wrap_html(self, path, params=None):
        return TemplateWrapper.wrap_html(path, params)

class ErrorHandler(BaseHandler):

    def get(self):
        self.set_status(404)

        body = "Page Not Found"
        self.write(body)

class Application(object):

    """web framework for the application"""

    def __init__(self, vars, urls=(), config=()):
        self._urls = urls
        self._config = config
        self._vars = vars

    def get_request(self):
        env = os.environ

        headers = []

        request = Httprequest(
            unicode(env["REQUEST_METHOD"], encoding="utf-8"),
            unicode(env["REQUEST_URI"], encoding="utf-8"),
            unicode(env.get("QUERY_STRING"), encoding="utf-8"),
            unicode(env.get("HTTP_HOST"), encoding="utf-8"),
            headers,
            env.get("HTTP_COOKIE")

        )

        return request

    def delegate(self):
        path = self._request.path
        method = self._request.meth

        for pattern, name in self._urls:
            m = re.match('^' + pattern + '$', path)
            if m:
                args = m.groups()
                func = method.lower()
                cls = self._vars.get(name)

                if hasattr(cls, func):
                    handler = cls(self, self._request)
                    meth = getattr(cls, func)
                    return meth(handler, *args)

        handler = ErrorHandler(self, self._request)
        return handler.get()

    def handle(self):
        self._request = self.get_request()
        self.delegate()

    def run(self):
        self.handle()
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright INRIA
# Contributors: Nicolas P. Rougier (Nicolas.Rougier@inria.fr)
#
# DANA is a computing framework for the simulation of distributed,
# asynchronous, numerical and adaptive models.
#
# This software is governed by the CeCILL license under French law and abiding
# by the rules of distribution of free software. You can use, modify and/ or
# redistribute the software under the terms of the CeCILL license as circulated
# by CEA, CNRS and INRIA at the following URL
# http://www.cecill.info/index.en.html.
#
# As a counterpart to the access to the source code and rights to copy, modify
# and redistribute granted by the license, users are provided only with a
# limited warranty and the software's author, the holder of the economic
# rights, and the successive licensors have only limited liability.
#
# In this respect, the user's attention is drawn to the risks associated with
# loading, using, modifying and/or developing or reproducing the software by
# the user in light of its specific status of free software, that may mean that
# it is complicated to manipulate, and that also therefore means that it is
# reserved for developers and experienced professionals having in-depth
# computer knowledge. Users are therefore encouraged to load and test the
# software's suitability as regards their requirements in conditions enabling
# the security of their systems and/or data to be ensured and, more generally,
# to use and operate it in the same conditions as regards security.
#
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL license and that you accept its terms.
# -----------------------------------------------------------------------------
''' Management of time '''
import sys

second      = 1
millisecond = 0.001
ms          = millisecond
minute      = 60*second
hour        = 60*minute

class Timer(object):
    ''' Description of a timer function '''

    _func = None
    _dt = 0
    _next = 0
    _order = 0
    _clock = None
    _start = 0
    _stop =0

    def __init__(self, func, clock, dt, order=0, start=None, stop=None):
        ''' Create a new timer function to be called every dt.

        **Parameter**

        func : function(time)
            Function to be called every dt

        clock : Clock
            Clock that will trigger the timer

        dt : float
            Time interval between two calls

        order : int
            In case several timers share the same time interval, those with
            lower order are called first.

        start : float
            When to start this timer

        stop : float
            When to stop this timer
        '''
        self._func = func
        self._dt = dt
        self._order = order
        self._clock = clock
        self._start = start or self._clock._time
        self._stop = stop or self._clock._stop
        self._next = self._start

    def __call__(self):
        ''' Call the timer function and update local time '''
        self._func(self._next)
        self._next += self._dt
        if self._next > self._stop:
            #self._clock._timers.remove(self)
            self._next = self._clock.stop + 1

    def __cmp__(self, other):
        ''' Comparison function used to order timers '''
        return ( cmp(self._next, other._next)
                 or cmp(self._order,other._order) )

class Tick(object):
    ''' Clock decorator

    **Usage**

    clock = Clock()
    @clock.tick
    def timer(t):
        print 'called at time', t
    '''
    _func = None
    _clock = None

    def __init__(self, function):
        ''' Add function to the clock using default clock dt '''
        self._func = function
        self._clock.add(function)

class before(object):
    ''' Tick class decorator

    This is used to specify that a function is to be called just before the
    clock default tick. It must be used in conjunction with the Tick decorator.

    **Usage**

    clock = Clock()
    @before(clock.tick)
    def timer(t): print 'called at time', t
    '''

    def __init__(self, tick):
        ''' Register relevant clock tick.

        **Parameters**

        tick : Tick
            A tick decorator
        '''
        self._tick = tick

    def __call__(self, func):
        ''' Add function to the clock using default clock dt '''
        self._tick._clock.add(func, order=-1)

class after(object):
    ''' Tick class decorator

    This is used to specify that a function is to be called just after the
    clock default tick.

    **Usage**

    clock = Clock()
    @after(clock.tick)
    def timer(t): print 'called at time', t
    '''

    def __init__(self, tick):
        ''' Register relevant clock tick
        **Parameters**

        tick : Tick
            A tick decorator
        '''
        self._tick = tick

    def __call__(self, func):
        ''' Add function to the clock using default clock dt '''
        self._tick._clock.add(func, order=+1)

class Every(object):
    ''' Clock decorator

    This is used to specify that a function is to be called on a regular basis.

    **Usage**

    clock = Clock()
    @clock.every(0.1)
    def timer(t): print 'called at time', t
    '''

    _order = 0
    _dt = None
    _clock = None

    def __init__(self, dt, start=0, stop=sys.maxint, order=0):
        '''
        dt : float
             Time interval between two calls

        order : int
             In case several timers share the same time interval, those with
             lower order are called first.
        '''
        self._dt = dt
        self._order = order
        self._start = start
        self._stop = stop

    def __call__(self, func):
        ''' Add function to the clock using given dt and order. '''

        dt = self._dt
        #if self._start is None:
        #    start = self._clock.time
        #else:
        start = max(self._start, self._clock.time)
        #if self._stop is None:
        #    stop = self._clock.stop
        #else:
        # stop = min(self._stop, self._clock.stop)

        start = self._start
        stop = self._stop
        order = self._order
        self._clock.add(func, dt=dt, start=start, stop=stop, order=order)

class At(object):
    ''' Clock decorator

    This is used to specify that a function is to be called once.

    **Usage**

    clock = Clock()
    @clock.at(0.1)
    def timer(t): print 'called at time', t
    '''

    _order = 0
    _dt = None
    _clock = None

    def __init__(self, dt, order=0):
        '''
        dt : float
            Time before call

        order : int
             In case several timers share the same time interval, those with
             lower order are called first.

        '''
        self._dt = dt
        self._start = self._dt
        self._stop  = self._dt
        self._order = order

    def __call__(self, func):
        ''' Add function to the clock using given dt and order. '''
        self._clock.add(func, self._dt, self._order,
                        start = self._start, stop = self._stop)

class ClockException(Exception):
    ''' Clock Exception '''
    pass

class Clock(object):
    ''' Clock class

    **Examples:**

      >>> clock = Clock(start=0.0, stop=1.0, dt=0.1)
      >>> @clock.tick
      >>> def tick(time):
      ...    print 'timer tick at time %.3f' % time
      >>> clock.run()
    '''

    _start   = 0.0*second
    _time    = 0.0*second
    _stop    = 1.0*second
    _dt      = 1.0*millisecond
    _running = False
    _timers  = []

    def __init__(self, start=0.0, stop=1.0, dt=0.001):
        ''' Initialize clock

        **Parameters**

        start : float
            Start time

        stop : float
            Stop time

        dt : float
            Time step resolution
        '''
        self._start = start
        self._stop = stop
        self._dt = dt
        self._time = self._start
        self.every = Every
        self.every._clock = self
        self.at = At
        self.at._clock = self
        self.tick = Tick
        self.tick._clock = self

    def reset(self):
        ''' Reset clock '''

        self._time = self._start
        for timer in self._timers:
            timer._next = timer._start
        self._timers.sort()

    def clear(self):
        ''' Remove all timers '''

        self._timers = []

    def run(self, start=None, stop=None, dt=None):
        ''' Run the clock.

        **Parameters**

        start : float
            Start time

        stop : float
            Stop time

        dt : float
            Time step resolution
        '''
        self.start = start or self._start
        self.stop = stop or self._stop
        self._dt = dt or self._dt
        self.reset()
        self._running = True
        while self._time <= self._stop and self._running:
            # print 'Tick : %.3f' % self.time
            while (self._timers and
                   self._timers[0]._next < (self._time+self._dt)
                   and self._running):

                timer = self._timers[0]
                if timer._next <= self._stop and \
                        self._time + self._dt - timer._next > 1e-10:
                    timer()
                else:
                    break
                self._timers.sort()
            self._time += self._dt
        self._running = False

    def stop(self):
        ''' Stop the clock. '''

        self._running = False

    def add(self, func, dt=None, order=0, start=None, stop=None):
        ''' Add a new timer to the timer list

        **Parameters**

        func : function(time)
            Function to be added

        dt : float or None
            Time interval between each function call. If not timestep is given,
            clock resolution (clock.dt) is used.

        order : int
            In case several timers share the same time interval, those with
            lower order are called first.
        '''

        if not dt:
            dt = self._dt
        timer = Timer(func, clock=self, dt=dt, order=order, start=start, stop=stop)
        self._timers.append(timer)
        self._timers.sort()

    def remove(self, func, dt=None):
        ''' Remove a given timer from the timer list

        **Parameters**

        func : function(time)
            Function to be removed

        dt : float or None
            Function timestep (as it was given when this function has been
            added to the timer list). If not timestep is given, clock
            resolution (clock.dt) is used.

        **Notes**

        A same function can be added with several different timesteps. It is
        this necessary to specify which timer (using timestep) is to be
        removed.
        '''

        if dt is None:
            for i in range(len(self._timers)):
                timer = self._timers[i]
                if timer._func == func:
                    self._timers.pop(i)
                    break
        else:
            for i in range(len(self._timers)):
                timer = self._timers[i]
                if timer._func == func and timer._dt == dt:
                    self._timers.pop(i)
                    break

    def _get_time(self):
        ''' Return current time '''
        return self._time
    time = property(_get_time,
                    doc = '''Current time''')

    def _get_start(self):
        ''' Return start time '''
        return self._start
    def _set_start(self, time):
        ''' Set start time '''
        if self._running:
            raise ClockException('Cannot set start time while running')
        if self._stop < self._start:
            raise ClockException('Start time must be inferor to stop time')
        self._start = time
        self.reset()
    start = property(_get_start, _set_start,
                     doc = '''Clock start time''')

    def _get_stop(self):
        ''' Return stop time '''
        return self._stop
    def _set_stop(self, time):
        ''' Set stop time '''
        if self._running:
            raise ClockException('Cannot set stop time while running.')
        if self._stop < self._start:
            raise ClockException('Stop time must be superior to start time.')
        self._stop = time
        self.reset()
    stop = property(_get_stop, _set_stop,
                     doc = '''Clock stop time.''')

    def _get_dt(self):
        ''' Return clock resolution. '''
        return self._dt
    def _set_dt(self, dt):
        ''' Set clock resolution. '''
        if self._running:
            raise ClockException('Cannot set resolution while running.')
        previous_dt = self._dt
        self._dt = dt
        self.reset()
        for timer in self._timers:
            if timer._dt == previous_dt:
                timer._dt = dt
    dt = property(_get_dt, _set_dt,
                  doc = '''Clock resolution.''')

# -----------------------------------------------------------------------------
if __name__ == '__main__':

    clock = Clock(start=0.0, stop=1.0, dt=0.1)

    @clock.tick
    def timer_2(time):
        print 'timer 2 called at time %.3f' % time

    @before(clock.tick)
    def timer_1(time):
        print 'timer 1 called at time %.3f' % time

    @after(clock.tick)
    def timer_3(time):
        print 'timer 3 called at time %.3f' % time

    @clock.every(100*millisecond,order=-1)
    def timer_4(time): print 'timer 4 called at time %.3f' % time

    @clock.every(100*millisecond,order=+1)
    def timer_5(time): print 'timer 5 called at time %.3f' % time

    @clock.at(50*millisecond)
    def timer_6(time): print 'timer 6 called at time %.3f' % time

    @clock.at(500*millisecond)
    def timer_7(time): print 'timer 7 called at time %.3f' % time

    @clock.every(dt=100*millisecond, order=-2,
                 start=100*millisecond, stop=200*millisecond)
    def timer_8(time): print 'timer 8 called at time %.3f' % time

    print "First run"
    clock.run()
    print
    print "Second run"
    clock.run()
<commit_msg>Fix a bug with the after decorator stop time (that was implicitely set to 1.0 second)<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright INRIA
# Contributors: Nicolas P. Rougier (Nicolas.Rougier@inria.fr)
#
# DANA is a computing framework for the simulation of distributed,
# asynchronous, numerical and adaptive models.
#
# This software is governed by the CeCILL license under French law and abiding
# by the rules of distribution of free software. You can use, modify and/ or
# redistribute the software under the terms of the CeCILL license as circulated
# by CEA, CNRS and INRIA at the following URL
# http://www.cecill.info/index.en.html.
#
# As a counterpart to the access to the source code and rights to copy, modify
# and redistribute granted by the license, users are provided only with a
# limited warranty and the software's author, the holder of the economic
# rights, and the successive licensors have only limited liability.
#
# In this respect, the user's attention is drawn to the risks associated with
# loading, using, modifying and/or developing or reproducing the software by
# the user in light of its specific status of free software, that may mean that
# it is complicated to manipulate, and that also therefore means that it is
# reserved for developers and experienced professionals having in-depth
# computer knowledge. Users are therefore encouraged to load and test the
# software's suitability as regards their requirements in conditions enabling
# the security of their systems and/or data to be ensured and, more generally,
# to use and operate it in the same conditions as regards security.
#
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL license and that you accept its terms.
# -----------------------------------------------------------------------------
''' Management of time '''
import sys

second      = 1
millisecond = 0.001
ms          = millisecond
minute      = 60*second
hour        = 60*minute

class Timer(object):
    ''' Description of a timer function '''

    _func = None
    _dt = 0
    _next = 0
    _order = 0
    _clock = None
    _start = 0
    _stop =0

    def __init__(self, func, clock, dt, order=0, start=None, stop=None):
        ''' Create a new timer function to be called every dt.

        **Parameter**

        func : function(time)
            Function to be called every dt

        clock : Clock
            Clock that will trigger the timer

        dt : float
            Time interval between two calls

        order : int
            In case several timers share the same time interval, those with
            lower order are called first.

        start : float
            When to start this timer

        stop : float
            When to stop this timer
        '''
        self._func = func
        self._dt = dt
        self._order = order
        self._clock = clock
        self._start = start or self._clock._time
        self._stop = stop #or self._clock._stop
        self._next = self._start

    def __call__(self):
        ''' Call the timer function and update local time '''
        self._func(self._next)
        self._next += self._dt
        if self._stop and self._next > self._stop:
            #self._clock._timers.remove(self)
            self._next = self._clock.stop + 1

    def __cmp__(self, other):
        ''' Comparison function used to order timers '''
        return ( cmp(self._next, other._next)
                 or cmp(self._order,other._order) )

class Tick(object):
    ''' Clock decorator

    **Usage**

    clock = Clock()
    @clock.tick
    def timer(t):
        print 'called at time', t
    '''
    _func = None
    _clock = None

    def __init__(self, function):
        ''' Add function to the clock using default clock dt '''
        self._func = function
        self._clock.add(function)

class before(object):
    ''' Tick class decorator

    This is used to specify that a function is to be called just before the
    clock default tick. It must be used in conjunction with the Tick decorator.

    **Usage**

    clock = Clock()
    @before(clock.tick)
    def timer(t): print 'called at time', t
    '''

    def __init__(self, tick):
        ''' Register relevant clock tick.

        **Parameters**

        tick : Tick
            A tick decorator
        '''
        self._tick = tick

    def __call__(self, func):
        ''' Add function to the clock using default clock dt '''
        self._tick._clock.add(func, order=-1)

class after(object):
    ''' Tick class decorator

    This is used to specify that a function is to be called just after the
    clock default tick.

    **Usage**

    clock = Clock()
    @after(clock.tick)
    def timer(t): print 'called at time', t
    '''

    def __init__(self, tick):
        ''' Register relevant clock tick
        **Parameters**

        tick : Tick
            A tick decorator
        '''
        self._tick = tick

    def __call__(self, func):
        ''' Add function to the clock using default clock dt '''
        self._tick._clock.add(func, order=+1)

class Every(object):
    ''' Clock decorator

    This is used to specify that a function is to be called on a regular basis.

    **Usage**

    clock = Clock()
    @clock.every(0.1)
    def timer(t): print 'called at time', t
    '''

    _order = 0
    _dt = None
    _clock = None

    def __init__(self, dt, start=0, stop=sys.maxint, order=0):
        '''
        dt : float
             Time interval between two calls

        order : int
             In case several timers share the same time interval, those with
             lower order are called first.
        '''
        self._dt = dt
        self._order = order
        self._start = start
        self._stop = stop

    def __call__(self, func):
        ''' Add function to the clock using given dt and order. '''

        dt = self._dt
        #if self._start is None:
        #    start = self._clock.time
        #else:
        start = max(self._start, self._clock.time)
        #if self._stop is None:
        #    stop = self._clock.stop
        #else:
        # stop = min(self._stop, self._clock.stop)

        start = self._start
        stop = self._stop
        order = self._order
        self._clock.add(func, dt=dt, start=start, stop=stop, order=order)

class At(object):
    ''' Clock decorator

    This is used to specify that a function is to be called once.

    **Usage**

    clock = Clock()
    @clock.at(0.1)
    def timer(t): print 'called at time', t
    '''

    _order = 0
    _dt = None
    _clock = None

    def __init__(self, dt, order=0):
        '''
        dt : float
            Time before call

        order : int
             In case several timers share the same time interval, those with
             lower order are called first.

        '''
        self._dt = dt
        self._start = self._dt
        self._stop  = self._dt
        self._order = order

    def __call__(self, func):
        ''' Add function to the clock using given dt and order. '''
        self._clock.add(func, self._dt, self._order,
                        start = self._start, stop = self._stop)

class ClockException(Exception):
    ''' Clock Exception '''
    pass

class Clock(object):
    ''' Clock class

    **Examples:**

      >>> clock = Clock(start=0.0, stop=1.0, dt=0.1)
      >>> @clock.tick
      >>> def tick(time):
      ...    print 'timer tick at time %.3f' % time
      >>> clock.run()
    '''

    _start   = 0.0*second
    _time    = 0.0*second
    _stop    = 1.0*second
    _dt      = 1.0*millisecond
    _running = False
    _timers  = []

    def __init__(self, start=0.0, stop=1.0, dt=0.001):
        ''' Initialize clock

        **Parameters**

        start : float
            Start time

        stop : float
            Stop time

        dt : float
            Time step resolution
        '''
        self._start = start
        self._stop = stop
        self._dt = dt
        self._time = self._start
        self.every = Every
        self.every._clock = self
        self.at = At
        self.at._clock = self
        self.tick = Tick
        self.tick._clock = self

    def reset(self):
        ''' Reset clock '''

        self._time = self._start
        for timer in self._timers:
            timer._next = timer._start
        self._timers.sort()

    def clear(self):
        ''' Remove all timers '''

        self._timers = []

    def run(self, start=None, stop=None, dt=None):
        ''' Run the clock.

        **Parameters**

        start : float
            Start time

        stop : float
            Stop time

        dt : float
            Time step resolution
        '''
        self.start = start or self._start
        self.stop = stop or self._stop
        self._dt = dt or self._dt
        self.reset()
        self._running = True
        while self._time <= self._stop and self._running:
            # print 'Tick : %.3f' % self.time
            while (self._timers and self._running
                   and self._timers[0]._next < (self._time+self._dt)):
                timer = self._timers[0]
                if timer._next <= self._stop and \
                        self._time + self._dt - timer._next > 1e-10:
                    timer()
                else:
                    break
                self._timers.sort()
            self._time += self._dt
        self._running = False

    def stop(self):
        ''' Stop the clock. '''

        self._running = False

    def add(self, func, dt=None, order=0, start=None, stop=None):
        ''' Add a new timer to the timer list

        **Parameters**

        func : function(time)
            Function to be added

        dt : float or None
            Time interval between each function call. If not timestep is given,
            clock resolution (clock.dt) is used.

        order : int
            In case several timers share the same time interval, those with
            lower order are called first.
        '''

        if not dt:
            dt = self._dt
        timer = Timer(func, clock=self, dt=dt, order=order, start=start, stop=stop)
        self._timers.append(timer)
        self._timers.sort()

    def remove(self, func, dt=None):
        ''' Remove a given timer from the timer list

        **Parameters**

        func : function(time)
            Function to be removed

        dt : float or None
            Function timestep (as it was given when this function has been
            added to the timer list). If not timestep is given, clock
            resolution (clock.dt) is used.

        **Notes**

        A same function can be added with several different timesteps. It is
        this necessary to specify which timer (using timestep) is to be
        removed.
        '''

        if dt is None:
            for i in range(len(self._timers)):
                timer = self._timers[i]
                if timer._func == func:
                    self._timers.pop(i)
                    break
        else:
            for i in range(len(self._timers)):
                timer = self._timers[i]
                if timer._func == func and timer._dt == dt:
                    self._timers.pop(i)
                    break

    def _get_time(self):
        ''' Return current time '''
        return self._time
    time = property(_get_time,
                    doc = '''Current time''')

    def _get_start(self):
        ''' Return start time '''
        return self._start
    def _set_start(self, time):
        ''' Set start time '''
        if self._running:
            raise ClockException('Cannot set start time while running')
        if self._stop < self._start:
            raise ClockException('Start time must be inferor to stop time')
        self._start = time
        self.reset()
    start = property(_get_start, _set_start,
                     doc = '''Clock start time''')

    def _get_stop(self):
        ''' Return stop time '''
        return self._stop
    def _set_stop(self, time):
        ''' Set stop time '''
        if self._running:
            raise ClockException('Cannot set stop time while running.')
        if self._stop < self._start:
            raise ClockException('Stop time must be superior to start time.')
        self._stop = time
        self.reset()
    stop = property(_get_stop, _set_stop,
                     doc = '''Clock stop time.''')

    def _get_dt(self):
        ''' Return clock resolution. '''
        return self._dt
    def _set_dt(self, dt):
        ''' Set clock resolution. '''
        if self._running:
            raise ClockException('Cannot set resolution while running.')
        previous_dt = self._dt
        self._dt = dt
        self.reset()
        for timer in self._timers:
            if timer._dt == previous_dt:
                timer._dt = dt
    dt = property(_get_dt, _set_dt,
                  doc = '''Clock resolution.''')

# -----------------------------------------------------------------------------
if __name__ == '__main__':

    clock = Clock(start=0.0, stop=1.0, dt=0.1)

    @clock.tick
    def timer_2(time):
        print 'timer 2 called at time %.3f' % time

    @before(clock.tick)
    def timer_1(time):
        print 'timer 1 called at time %.3f' % time

    @after(clock.tick)
    def timer_3(time):
        print 'timer 3 called at time %.3f' % time

    @clock.every(100*millisecond,order=-1)
    def timer_4(time): print 'timer 4 called at time %.3f' % time

    @clock.every(100*millisecond,order=+1)
    def timer_5(time): print 'timer 5 called at time %.3f' % time

    @clock.at(50*millisecond)
    def timer_6(time): print 'timer 6 called at time %.3f' % time

    @clock.at(500*millisecond)
    def timer_7(time): print 'timer 7 called at time %.3f' % time

    @clock.every(dt=100*millisecond, order=-2,
                 start=100*millisecond, stop=200*millisecond)
    def timer_8(time): print 'timer 8 called at time %.3f' % time

    print "First run"
    clock.run()
    print
    print "Second run"
    clock.run()
<|endoftext|>


<commit_before>#  todo:
#  use dictwriter to write data
#  check for year folder and create it if not exists
#  inconsistent quotes usage

import arrow
import time
import requests
import geocoder
import logging
import csv
import pdb

logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True

#  debugging vars
bill = []

def get_data(start_date, end_date):
    start = start_date.format('MM/DD/YYYY')
    end = end_date.format('MM/DD/YYYY')
    print('Getting data from {} to {}'.format(start, end))
    data = {'sDate': start, 'eDate': end, 'Submit': 'Submit'}
    res = requests.post('http://www.austintexas.gov/oss_permits/permit_report.cfm', data=data)
    print(res.status_code, res.request.url)

    return res.content

def parse_table_html(data):
    data = str(data)
    data = data.replace("\\n","")
    data = data.replace("\\t","")
    data = data.replace("b'","")
    data = data.replace("
","")
    data = data.replace("
","")
    data = data.replace("","")
    data = data.replace("	","|")
    data = data.replace("","")
    data = data.replace("	",delim)
    data = data.replace("
","")
    data = data.replace("
","\n")
    return data

def geocode_data(data):
    reader = csv.DictReader(data.split('\n'),  delimiter='|')
    counter = 0
    #  create list of unique addresses
    for row in reader:
        address = row['permit_location']

        if type(address) == str: #  normalize addresses and skip empty address fields
                address = address.upper().strip()
        else:
            continue #  data with invalid address is skipped

        if address not in address_dict:
            if counter < 2: #  only geocode a few records (dev only)
                print("hey!")
                counter =  counter + 1
                time.sleep(.5) #  delay for .5 seconds between lookup requests. the api limit is 5 requests per second
                found_address = geocoder.google(address +', Austin, TX')
                address_dict[address] = found_address

        if address in address_dict:
            if address_dict[address].lat:
                row['lat'] = address_dict[address].lat
                row['lng'] = address_dict[address].lng
                row['accuracy'] = address_dict[address].accuracy
                row["city"] = address_dict[address].city
                row["county"] = address_dict[address].county
                row["state"] = address_dict[address].state
                row["postal_code"] = address_dict[address].postal

        pdb.set_trace()
        return data

def write_data(start_date, end_date, data):
    fname = 'data/{}/permit_report_{}_{}.xls'.format(start_date.format('YYYY'), start_date.format('MM-DD-YY'), end_date.format('MM-DD-YY'))
    print('Writing data from {} to {}'.format(start_date.format('MM/DD/YYYY'), end_date.format('MM/DD/YYYY')))
    with open(fname, 'w+') as fh:
        fh.write(data)

def main(start, end):
    delta = end - start
    days = delta.days + 1
    print('Fetching permit reports for {} days'.format(days))
    for day_number in range(0, days, interval):
        start_date = start.replace(days=day_number)
        end_date = start.replace(days=day_number+interval-1)
        data = get_data(start_date, end_date)
        data = parse_table_html(data)
        data = geocode_data(data)
        write_data(start_date, end_date, data)

delim = "|"
start = arrow.get(2015,12,7) #  (YYYY,M,D)
end = arrow.get(2015,12,7)
interval = 1 #  download, geocode, and write one day at a time
address_dict = dict()
main(start, end)
<commit_msg>built-in geocoding!<commit_after>#  todo:
#  inconsistent quotes usage
#  interval must always be one day

import arrow
import os
import time
import requests
import geocoder
import logging
import csv

logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True

#  debugging vars
bill = []

def get_data(start_date, end_date):
    start = start_date.format('MM/DD/YYYY')
    end = end_date.format('MM/DD/YYYY')
    print('Getting data from {} to {}'.format(start, end))
    data = {'sDate': start, 'eDate': end, 'Submit': 'Submit'}
    res = requests.post('http://www.austintexas.gov/oss_permits/permit_report.cfm', data=data)
    print(res.status_code, res.request.url)

    return res.content

def parse_table_html(data):
    data = str(data)
    data = data.replace("\\n","")
    data = data.replace("\\t","")
    data = data.replace("b'","")
    data = data.replace("
","")
    data = data.replace("
","")
    data = data.replace("","")
    data = data.replace("	","|")
    data = data.replace("","")
    data = data.replace("	",delim)
    data = data.replace("
","")
    data = data.replace("
","\n")
    return data

def geocode_data(data):
    geocoded_data = []
    reader = csv.DictReader(data.split('\n'),  delimiter='|')
    fieldnames = reader.fieldnames + ['lat'] + ['lng'] + ['accuracy'] + ['city'] + ['postal_code'] + ['state'] + ['county']
    counter = 0

    #  create list of unique addresses
    for row in reader:
        address = row['permit_location']

        if type(address) == str: #  normalize addresses and skip empty address fields
                address = address.upper().strip()
        else:
            continue #  data with invalid address is skipped

        if address not in address_dict:
            if counter < 2: #  only geocode a few records (dev only)
                print("hey!")
                counter =  counter + 1
                time.sleep(.5) #  delay for .5 seconds between lookup requests. the api limit is 5 requests per second
                found_address = geocoder.google(address +', Austin, TX')
                address_dict[address] = found_address

        if address in address_dict:
            if address_dict[address].lat:
                row['lat'] = address_dict[address].lat
                row['lng'] = address_dict[address].lng
                row['accuracy'] = address_dict[address].accuracy
                row["city"] = address_dict[address].city
                row["county"] = address_dict[address].county
                row["state"] = address_dict[address].state
                row["postal_code"] = address_dict[address].postal

        geocoded_data.append(row)

    return (geocoded_data, fieldnames)

def write_data(start_date, end_date, data, fieldnames):
    fname = 'data/{}/permit_report_{}_{}.xls'.format(start_date.format('YYYY'), start_date.format('MM-DD-YY'), end_date.format('MM-DD-YY'))
    folder = start_date.format('YYYY')
    if not os.path.exists("data/" + folder):
        os.makedirs("data/" + folder)

    print('Writing data from {} to {}'.format(start_date.format('MM/DD/YYYY'), end_date.format('MM/DD/YYYY')))
    with open(fname, 'w+') as fh:
        writer = csv.DictWriter(fh, fieldnames, delimiter = '|', lineterminator='\n')
        writer.writeheader()
        writer.writerows(data)

def main(start, end):
    delta = end - start
    days = delta.days + 1
    print('Fetching permit reports for {} days'.format(days))
    for day_number in range(0, days, interval):
        start_date = start.replace(days=day_number)
        end_date = start.replace(days=day_number+interval-1)
        data = get_data(start_date, end_date)
        data = parse_table_html(data)
        data = geocode_data(data)
        write_data(start_date, end_date, data[0], data[1])

delim = "|"
start = arrow.get(2015,12,7) #  (YYYY,M,D)
end = arrow.get(2015,12,7)
interval = 1 #  download, geocode, and write one day at a time
address_dict = dict()
main(start, end)
<|endoftext|>


<commit_before># Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class ActsCore(CMakePackage):
    """
    A Common Tracking Software (ACTS)

    This project contains an experiment-independent set of track reconstruction
    tools. The main philosophy is to provide high-level track reconstruction
    modules that can be used for any tracking detector. The description of the
    tracking detector's geometry is optimized for efficient navigation and
    quick extrapolation of tracks. Converters for several common geometry
    description languages exist. Having a highly performant, yet largely
    customizable implementation of track reconstruction algorithms was a
    primary objective for the design of this toolset. Additionally, the
    applicability to real-life HEP experiments plays major role in the
    development process. Apart from algorithmic code, this project also
    provides an event data model for the description of track parameters and
    measurements.

    Key features of this project include: tracking geometry description which
    can be constructed from TGeo, DD4Hep, or GDML input, simple and efficient
    event data model, performant and highly flexible algorithms for track
    propagation and fitting, basic seed finding algorithms.
    """

    homepage = "http://acts.web.cern.ch/ACTS/"
    git      = "https://gitlab.cern.ch/acts/acts-core.git"
    maintainers = ['HadrienG2']

    version('develop', branch='master')
    version('0.15.0', commit='267c28f69c561e64369661a6235b03b5a610d6da')
    version('0.14.0', commit='38d678fcb205b77d60326eae913fbb1b054acea1')
    version('0.13.0', commit='b33f7270ddbbb33050b7ec60b4fa255dc2bfdc88')
    version('0.12.1', commit='a8b3d36e7c6cb86487637589e0eff7bbe626054a')
    version('0.12.0', commit='f9cda77299606d78c889fb1db2576c1971a271c4')
    version('0.11.1', commit='c21196cd6c3ecc6da0f14d0a9ef227a274be584b')
    version('0.11.0', commit='22bcea1f19adb0021ca61b843b95cfd2462dd31d')
    version('0.10.5', commit='b6f7234ca8f18ee11e57709d019c14bf41cf9b19')
    version('0.10.4', commit='42cbc359c209f5cf386e620b5a497192c024655e')
    version('0.10.3', commit='a3bb86b79a65b3d2ceb962b60411fd0df4cf274c')
    version('0.10.2', commit='64cbf28c862d8b0f95232b00c0e8c38949d5015d')
    version('0.10.1', commit='0692dcf7824efbc504fb16f7aa00a50df395adbc')
    version('0.10.0', commit='30ef843cb00427f9959b7de4d1b9843413a13f02')
    version('0.09.5', commit='12b11fe8b0d428ccb8e92dda7dc809198f828672')
    version('0.09.4', commit='e5dd9fbe179201e70347d1a3b9fa1899c226798f')
    version('0.09.3', commit='a8f31303ee8720ed2946bfe2d59e81d0f70e307e')
    version('0.09.2', commit='4e1f7fa73ffe07457080d787e206bf6466fe1680')
    version('0.09.1', commit='69c451035516cb683b8f7bc0bab1a25893e9113d')
    version('0.09.0', commit='004888b0a412f5bbaeef2ffaaeaf2aa182511494')
    version('0.08.2', commit='c5d7568714e69e7344582b93b8d24e45d6b81bf9')
    version('0.08.1', commit='289bdcc320f0b3ff1d792e29e462ec2d3ea15df6')
    version('0.08.0', commit='99eedb38f305e3a1cd99d9b4473241b7cd641fa9')

    # Variants that affect the core ACTS library
    variant('legacy', default=False, description='Build the Legacy package')
    variant('examples', default=False, description='Build the examples')
    variant('tests', default=False, description='Build the unit tests')
    variant('integration_tests', default=False, description='Build the integration tests')

    # Variants the enable / disable ACTS plugins
    variant('digitization', default=False, description='Build the geometric digitization plugin')
    variant('dd4hep', default=False, description='Build the DD4hep plugin')
    variant('identification', default=False, description='Build the Identification plugin')
    variant('json', default=False, description='Build the Json plugin')
    variant('tgeo', default=False, description='Build the TGeo plugin')

    depends_on('cmake @3.11:', type='build')
    depends_on('boost @1.62:1.69.99 +program_options +test', when='@:0.10.3')
    depends_on('boost @1.62: +program_options +test', when='@0.10.4:')
    depends_on('eigen @3.2.9:', type='build')
    depends_on('nlohmann-json @3.2.0:', when='@0.14.0: +json')
    depends_on('root @6.10: cxxstd=14', when='+tgeo @:0.8.0')
    depends_on('root @6.10: cxxstd=17', when='+tgeo @0.8.1:')
    depends_on('dd4hep @1.2:', when='+dd4hep')

    def cmake_args(self):
        spec = self.spec

        def cmake_variant(cmake_label, spack_variant):
            enabled = spec.satisfies('+' + spack_variant)
            return "-DACTS_BUILD_{0}={1}".format(cmake_label, enabled)

        args = [
            cmake_variant("LEGACY", "legacy"),
            cmake_variant("EXAMPLES", "examples"),
            cmake_variant("TESTS", "tests"),
            cmake_variant("INTEGRATION_TESTS", "integration_tests"),
            cmake_variant("DIGITIZATION_PLUGIN", "digitization"),
            cmake_variant("DD4HEP_PLUGIN", "dd4hep"),
            cmake_variant("IDENTIFICATION_PLUGIN", "identification"),
            cmake_variant("JSON_PLUGIN", "json"),
            cmake_variant("TGEO_PLUGIN", "tgeo")
        ]

        if 'root' in spec:
            cxxstd = spec['root'].variants['cxxstd'].value
            args.append("-DCMAKE_CXX_STANDARD={0}".format(cxxstd))

        if spec.satisfies('@0.14.0: +json'):
            args.append("-DACTS_USE_BUNDLED_NLOHMANN_JSON=OFF")

        return args
<commit_msg>acts-core: added v0.16.0 (#14839)<commit_after># Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class ActsCore(CMakePackage):
    """
    A Common Tracking Software (ACTS)

    This project contains an experiment-independent set of track reconstruction
    tools. The main philosophy is to provide high-level track reconstruction
    modules that can be used for any tracking detector. The description of the
    tracking detector's geometry is optimized for efficient navigation and
    quick extrapolation of tracks. Converters for several common geometry
    description languages exist. Having a highly performant, yet largely
    customizable implementation of track reconstruction algorithms was a
    primary objective for the design of this toolset. Additionally, the
    applicability to real-life HEP experiments plays major role in the
    development process. Apart from algorithmic code, this project also
    provides an event data model for the description of track parameters and
    measurements.

    Key features of this project include: tracking geometry description which
    can be constructed from TGeo, DD4Hep, or GDML input, simple and efficient
    event data model, performant and highly flexible algorithms for track
    propagation and fitting, basic seed finding algorithms.
    """

    homepage = "http://acts.web.cern.ch/ACTS/"
    git      = "https://gitlab.cern.ch/acts/acts-core.git"
    maintainers = ['HadrienG2']

    version('develop', branch='master')
    version('0.16.0', commit='b3d965fe0b8ae335909d79114ef261c6b996773a')
    version('0.15.0', commit='267c28f69c561e64369661a6235b03b5a610d6da')
    version('0.14.0', commit='38d678fcb205b77d60326eae913fbb1b054acea1')
    version('0.13.0', commit='b33f7270ddbbb33050b7ec60b4fa255dc2bfdc88')
    version('0.12.1', commit='a8b3d36e7c6cb86487637589e0eff7bbe626054a')
    version('0.12.0', commit='f9cda77299606d78c889fb1db2576c1971a271c4')
    version('0.11.1', commit='c21196cd6c3ecc6da0f14d0a9ef227a274be584b')
    version('0.11.0', commit='22bcea1f19adb0021ca61b843b95cfd2462dd31d')
    version('0.10.5', commit='b6f7234ca8f18ee11e57709d019c14bf41cf9b19')
    version('0.10.4', commit='42cbc359c209f5cf386e620b5a497192c024655e')
    version('0.10.3', commit='a3bb86b79a65b3d2ceb962b60411fd0df4cf274c')
    version('0.10.2', commit='64cbf28c862d8b0f95232b00c0e8c38949d5015d')
    version('0.10.1', commit='0692dcf7824efbc504fb16f7aa00a50df395adbc')
    version('0.10.0', commit='30ef843cb00427f9959b7de4d1b9843413a13f02')
    version('0.09.5', commit='12b11fe8b0d428ccb8e92dda7dc809198f828672')
    version('0.09.4', commit='e5dd9fbe179201e70347d1a3b9fa1899c226798f')
    version('0.09.3', commit='a8f31303ee8720ed2946bfe2d59e81d0f70e307e')
    version('0.09.2', commit='4e1f7fa73ffe07457080d787e206bf6466fe1680')
    version('0.09.1', commit='69c451035516cb683b8f7bc0bab1a25893e9113d')
    version('0.09.0', commit='004888b0a412f5bbaeef2ffaaeaf2aa182511494')
    version('0.08.2', commit='c5d7568714e69e7344582b93b8d24e45d6b81bf9')
    version('0.08.1', commit='289bdcc320f0b3ff1d792e29e462ec2d3ea15df6')
    version('0.08.0', commit='99eedb38f305e3a1cd99d9b4473241b7cd641fa9')

    # Variants that affect the core ACTS library
    variant('benchmarks', default=False, description='Build the performance benchmarks')
    variant('examples', default=False, description='Build the examples')
    variant('tests', default=False, description='Build the unit tests')
    variant('integration_tests', default=False, description='Build the integration tests')

    # Variants the enable / disable ACTS plugins
    variant('dd4hep', default=False, description='Build the DD4hep plugin')
    variant('digitization', default=False, description='Build the geometric digitization plugin')
    variant('fatras', default=False, description='Build the FAst TRAcking Simulation package')
    variant('identification', default=False, description='Build the Identification plugin')
    variant('json', default=False, description='Build the Json plugin')
    variant('legacy', default=False, description='Build the Legacy package')
    variant('tgeo', default=False, description='Build the TGeo plugin')

    depends_on('cmake @3.11:', type='build')
    depends_on('boost @1.62:1.69.99 +program_options +test', when='@:0.10.3')
    depends_on('boost @1.62: +program_options +test', when='@0.10.4:')
    depends_on('eigen @3.2.9:', type='build')
    depends_on('nlohmann-json @3.2.0:', when='@0.14.0: +json')
    depends_on('root @6.10: cxxstd=14', when='+tgeo @:0.8.0')
    depends_on('root @6.10: cxxstd=17', when='+tgeo @0.8.1:')
    depends_on('dd4hep @1.2: +xercesc', when='+dd4hep')

    def cmake_args(self):
        spec = self.spec

        def cmake_variant(cmake_label, spack_variant):
            enabled = spec.satisfies('+' + spack_variant)
            return "-DACTS_BUILD_{0}={1}".format(cmake_label, enabled)

        integration_tests_label = "INTEGRATIONTESTS"
        tests_label = "UNITTESTS"
        if spec.satisfies('@:0.15.99'):
            integration_tests_label = "INTEGRATION_TESTS"
            tests_label = "TESTS"

        args = [
            cmake_variant("BENCHMARKS", "benchmarks"),
            cmake_variant("EXAMPLES", "examples"),
            cmake_variant(tests_label, "tests"),
            cmake_variant(integration_tests_label, "integration_tests"),
            cmake_variant("DIGITIZATION_PLUGIN", "digitization"),
            cmake_variant("DD4HEP_PLUGIN", "dd4hep"),
            cmake_variant("FATRAS", "fatras"),
            cmake_variant("IDENTIFICATION_PLUGIN", "identification"),
            cmake_variant("JSON_PLUGIN", "json"),
            cmake_variant("LEGACY", "legacy"),
            cmake_variant("TGEO_PLUGIN", "tgeo")
        ]

        if 'root' in spec:
            cxxstd = spec['root'].variants['cxxstd'].value
            args.append("-DCMAKE_CXX_STANDARD={0}".format(cxxstd))

        if spec.satisfies('@0.14.0: +json'):
            args.append("-DACTS_USE_BUNDLED_NLOHMANN_JSON=OFF")

        return args
<|endoftext|>


<commit_before># Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *
import platform

# The viewer and trace viewer tar files and sha256sum depend on the
# version and machine type.
def viewer_url(ver, mach):
    return (
        'http://hpctoolkit.org/download/hpcviewer/{0}/'
        'hpcviewer-linux.gtk.{1}.tgz'
    ).format(ver, mach)

def trace_url(ver, mach):
    return (
        'http://hpctoolkit.org/download/hpcviewer/{0}/'
        'hpctraceviewer-linux.gtk.{1}.tgz'
    ).format(ver, mach)

class Hpcviewer(Package):
    """Binary distribution of hpcviewer and hpctraceviewer for the Rice
    HPCToolkit (Linux x86_64, ppc64 and ppc64le).  Note: hpctoolkit
    databases are platform independent, so you don't need to install
    hpctoolkit to run the viewers and it's common to run hpcrun and
    hpcviewer on different machines."""

    homepage = "http://hpctoolkit.org"

    viewer_sha = {
        ('2019.02', 'x86_64'):  'e24368a3ec27b82736a781971a8371abfe7744b2a4f68b7b41d76f84af306b83',
        ('2019.02', 'ppc64'):   '72c1ef1a5682c3273e900bb248f126428a02dfe728af0c49c7ee8381938d1e18',
        ('2019.02', 'ppc64le'): '02aaf27bb5b0f72d5b5738289bce60f6ef0ef7327ca96a890892509a09adc946',
    }

    trace_sha = {
        ('2019.02', 'x86_64'):  '5ff11317a638318295821204ffcb1276e9da1684cd5f298410ae2bf78ce88b6b',
        ('2019.02', 'ppc64'):   '95b2a7d848ecb924591c248f5e47c641646ef90a071db48237ddb96c4b71a8fb',
        ('2019.02', 'ppc64le'): '01a159306e7810efe07157ec823ac6ca7570ec2014c95db599a3f90eee33355c',
    }

    for ver in ['2019.02']:
        key = (ver, platform.machine())
        if key in viewer_sha and key in trace_sha:
            version(ver, url=viewer_url(*key), sha256=viewer_sha[key])

            resource(name='hpctraceviewer', url=trace_url(*key),
                     sha256=trace_sha[key], destination='TRACE')

    depends_on('java@8', type=('build', 'run'))

    # Both hpcviewer and trace viewer have an install script.
    def install(self, spec, prefix):
        args = [
            '--java', spec['java'].home,
            prefix
        ]

        inst = Executable(join_path('.', 'install'))
        inst(*args)

        cd(join_path('TRACE', 'hpctraceviewer'))

        inst = Executable(join_path('.', 'install'))
        inst(*args)
<commit_msg>hpcviewer: add version 2019.04 (#11380)<commit_after># Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *
import platform

# The viewer and trace viewer tar files and sha256sum depend on the
# version and machine type.
def viewer_url(ver, mach):
    return (
        'http://hpctoolkit.org/download/hpcviewer/{0}/'
        'hpcviewer-linux.gtk.{1}.tgz'
    ).format(ver, mach)

def trace_url(ver, mach):
    return (
        'http://hpctoolkit.org/download/hpcviewer/{0}/'
        'hpctraceviewer-linux.gtk.{1}.tgz'
    ).format(ver, mach)

class Hpcviewer(Package):
    """Binary distribution of hpcviewer and hpctraceviewer for the Rice
    HPCToolkit (Linux x86_64, ppc64 and ppc64le).  Note: hpctoolkit
    databases are platform independent, so you don't need to install
    hpctoolkit to run the viewers and it's common to run hpcrun and
    hpcviewer on different machines."""

    homepage = "http://hpctoolkit.org"

    viewer_sha = {
        ('2019.04', 'x86_64'):  'c524498ef235171e298c8142b7e73b0a1f7c433f9c471fb692d31f0685e53aa4',
        ('2019.04', 'ppc64'):   'dc9daee886ba72c0615db909860ee1aed0979f12c0d113efbe721ddabdf55199',
        ('2019.04', 'ppc64le'): 'dddabccef156996d390653639096ad3e27b7384a5754f42084f50c4a50a9009b',
        ('2019.02', 'x86_64'):  'e24368a3ec27b82736a781971a8371abfe7744b2a4f68b7b41d76f84af306b83',
        ('2019.02', 'ppc64'):   '72c1ef1a5682c3273e900bb248f126428a02dfe728af0c49c7ee8381938d1e18',
        ('2019.02', 'ppc64le'): '02aaf27bb5b0f72d5b5738289bce60f6ef0ef7327ca96a890892509a09adc946',
    }

    trace_sha = {
        ('2019.04', 'x86_64'):  'f5f908c0e52c97a72af1af8519f4b191298fe52bd811dd06a051b68cd7bcce27',
        ('2019.04', 'ppc64'):   '221683c992e4fe2cd9079ad2ebb531d99d04a3cbb3a8860f795b276b1eaeab19',
        ('2019.04', 'ppc64le'): 'fe539c6a165a72bba6ea7bdb34a90d862d427c4d55095c97794d54e6dd9d3075',
        ('2019.02', 'x86_64'):  '5ff11317a638318295821204ffcb1276e9da1684cd5f298410ae2bf78ce88b6b',
        ('2019.02', 'ppc64'):   '95b2a7d848ecb924591c248f5e47c641646ef90a071db48237ddb96c4b71a8fb',
        ('2019.02', 'ppc64le'): '01a159306e7810efe07157ec823ac6ca7570ec2014c95db599a3f90eee33355c',
    }

    version_list = ['2019.04', '2019.02']

    for ver in version_list:
        key = (ver, platform.machine())
        if key in viewer_sha and key in trace_sha:
            version(ver, url=viewer_url(*key), sha256=viewer_sha[key])

            resource(name='hpctraceviewer', url=trace_url(*key),
                     sha256=trace_sha[key], destination='TRACE',
                     when='@{0}'.format(ver))

    depends_on('java@8', type=('build', 'run'))

    # Both hpcviewer and trace viewer have an install script.
    def install(self, spec, prefix):
        args = [
            '--java', spec['java'].home,
            prefix
        ]

        inst = Executable(join_path('.', 'install'))
        inst(*args)

        cd(join_path('TRACE', 'hpctraceviewer'))

        inst = Executable(join_path('.', 'install'))
        inst(*args)
<|endoftext|>


<commit_before>from Bio.Seq import translate
from Bio.Data.IUPACData import (
    ambiguous_dna_complement, ambiguous_rna_complement)

from dark.aa import PROPERTIES, NONE

def _makeComplementTable(complementData):
    """
    Make a sequence complement table.

    @param complementData: A C{dict} whose keys and values are strings of
        length one. A key, value pair indicates a substitution that should
        be performed during complementation.
    @return: A 256 character string that can be used as a translation table
        by the C{translate} method of a Python string.
    """
    table = range(256)
    for _from, to in complementData.iteritems():
        table[ord(_from[0])] = ord(to[0])
    return ''.join(map(chr, table))

class Read(object):
    """
    Hold information about a single read.

    @param id: A C{str} describing the read.
    @param sequence: A C{str} of sequence information (might be
        nucleotides or proteins).
    @param quality: An optional C{str} of phred quality scores. If not C{None},
        it must be the same length as C{sequence}.
    @raise ValueError: if the length of the quality string (if any) does not
        match the length of the sequence.
    """
    def __init__(self, id, sequence, quality=None, translation_table=None):
        if quality is not None and len(quality) != len(sequence):
            raise ValueError(
                'Invalid read: sequence length (%d) != quality length (%d)' %
                (len(sequence), len(quality)))

        self.id = id
        try:
            self.sequence = sequence.upper()
        except AttributeError:
            self.sequence = sequence
        self.quality = quality
        self.TRANSLATION_TABLE = translation_table

    def __eq__(self, other):
        return (self.id == other.id and
                self.sequence == other.sequence and
                self.quality == other.quality)

    def __ne__(self, other):
        return not self == other

    def __len__(self):
        return len(self.sequence)

    def toString(self, format_):
        """
        Convert the read to a string format.

        @param format_: Either 'fasta' or 'fastq'.
        @raise ValueError: if C{format_} is 'fastq' and the read has no quality
            information, or if an unknown format is requested.
        @return: A C{str} representing the read in the requested format.
        """
        if format_ == 'fasta':
            return '>%s\n%s\n' % (self.id, self.sequence)
        elif format_ == 'fastq':
            if self.quality is None:
                raise ValueError('Read %r has no quality information' %
                                 self.id)
            else:
                return '@%s\n%s\n+%s\n%s\n' % (
                    self.id, self.sequence, self.id, self.quality)
        else:
            raise ValueError("Format must be either 'fasta' or 'fastq'.")

class _NucleotideRead(Read):
    """
    Holds methods to work with nucleotide (DNA and RNA) sequences.
    """
    def translations(self):
        """
        Yield all six translations of a nucleotide sequence.

        @return: A generator that produces six L{TranslatedRead} instances.
        """
        rc = self.reverseComplement().sequence
        for reverseComplemented in False, True:
            for frame in 0, 1, 2:
                seq = rc if reverseComplemented else self.sequence
                # Get the suffix of the sequence for translation. I.e.,
                # skip 0, 1, or 2 initial bases, depending on the frame.
                # Note that this makes a copy of the sequence, which we can
                # then safely append 'N' bases to to adjust its length to
                # be zero mod 3.
                suffix = seq[frame:]
                lengthMod3 = len(suffix) % 3
                if lengthMod3:
                    suffix += ('NN' if lengthMod3 == 1 else 'N')
                yield TranslatedRead(self, translate(suffix), frame,
                                     reverseComplemented)

    def reverseComplement(self):
        """
        Reverse complement a nucleotide sequence.

        @return: The reverse complemented sequence as a C{Read} instance.
        """
        quality = None if self.quality is None else self.quality[::-1]
        sequence = self.sequence.translate(self.TRANSLATION_TABLE)[::-1]
        return Read(self.id, sequence, quality)

class DNARead(_NucleotideRead):
    """
    Hold information and methods to work with DNA reads.
    """
    TRANSLATION_TABLE = _makeComplementTable(ambiguous_dna_complement)

class RNARead(_NucleotideRead):
    """
    Hold information and methods to work with RNA reads.
    """
    TRANSLATION_TABLE = _makeComplementTable(ambiguous_rna_complement)

class AARead(Read):
    """
    Hold information and methods to work with AA reads.
    """
    def properties(self):
        """
        Translate an amino acid sequence to properties.

        @return: A generator that produces an L{PropertiesRead} instance.
        """
        aaSeq = self.sequence
        properties = [PROPERTIES[base] if base in PROPERTIES.keys() else NONE
                      for base in aaSeq]
        return properties

class TranslatedRead(AARead):
    """
    Hold information about one DNA->AA translation of a Read.

    @param originalRead: The original DNA or RNA L{Read} instance from which
        this translation was obtained.
    @param sequence: The C{str} AA translated sequence.
    @param frame: The C{int} frame, either 0, 1, or 2.
    @param reverseComplemented: A C{bool}, C{True} if the original sequence
        must be reverse complemented to obtain this AA sequence.
    """
    def __init__(self, originalRead, sequence, frame,
                 reverseComplemented=False):
        if frame not in (0, 1, 2):
            raise ValueError('Frame must be 0, 1, or 2')
        newId = '%s-frame%d%s' % (originalRead.id, frame,
                                  'rc' if reverseComplemented else '')
        Read.__init__(self, newId, sequence)
        self.originalRead = originalRead
        self.frame = frame
        self.reverseComplemented = reverseComplemented

    def __eq__(self, other):
        return (Read.__eq__(self, other) and
                self.frame == other.frame and
                self.reverseComplemented == other.reverseComplemented and
                self.originalRead == other.originalRead)

    def __ne__(self, other):
        return not self == other

    def maximumORFLength(self):
        """
        Return the length of the longest (possibly partial) ORF in a translated
        read. The ORF may originate or terminate outside the sequence, which is
        why the length is just a lower bound.
        """
        return max(len(orf) for orf in self.sequence.split('*'))

class Reads(object):
    """
    Maintain a collection of sequence reads.
    """

    def __init__(self):
        self.additionalReads = []
        self._length = 0

    def add(self, read):
        """
        Add a read to this collection of reads.

        @param read: A C{Read} instance.
        """
        self.additionalReads.append(read)
        self._length += 1

    def __iter__(self):
        # Reset self._length because __iter__ may be called more than once
        # and we don't want to increment _length each time we iterate.
        self._length = len(self.additionalReads)

        # Look for an 'iter' method in a possible subclass.
        try:
            iter = self.iter()
        except AttributeError:
            pass
        else:
            for read in iter:
                self._length += 1
                yield read

        for read in self.additionalReads:
            yield read

    def __len__(self):
        # Note that len reflects the number of reads that are currently known.
        # If self.__iter__ has not been exhausted, we will not know the true
        # number of reads.
        return self._length

    def save(self, filename, format_='fasta'):
        """
        Write the reads to C{filename} in the requested format.

        @param filename: Either a C{str} file name to save into (the file will
            be overwritten) or an open file descriptor (e.g., sys.stdout).
        @param format_: A C{str} format to save as, either 'fasta' or 'fastq'.
        @raise ValueError: if C{format_} is 'fastq' and a read with no quality
            is present, or if an unknown format is requested.
        """
        format_ = format_.lower()

        if isinstance(filename, basestring):
            with open(filename, 'w') as fp:
                for read in self:
                    fp.write(read.toString(format_))
        else:
            # We have a file-like object.
            for read in self:
                filename.write(read.toString(format_))

    def filter(self, minLength=None, maxLength=None):
        """
        Filter a set of reads to produce a matching subset.

        Note: there are many additional filtering options that could be added,
        e.g., filtering on read id (whitelist, blacklist, regex, etc), GC %,
        and quality.

        @param minLength: The minimum acceptable length.
        @param maxLength: The maximum acceptable length.
        """
        result = Reads()
        for read in self:
            readLen = len(read)
            if ((minLength is None or readLen >= minLength) and
                    (maxLength is None or readLen <= maxLength)):
                result.add(read)
        return result
<commit_msg>I need a whisky<commit_after>from Bio.Seq import translate
from Bio.Data.IUPACData import (
    ambiguous_dna_complement, ambiguous_rna_complement)

from dark.aa import PROPERTIES, NONE

def _makeComplementTable(complementData):
    """
    Make a sequence complement table.

    @param complementData: A C{dict} whose keys and values are strings of
        length one. A key, value pair indicates a substitution that should
        be performed during complementation.
    @return: A 256 character string that can be used as a translation table
        by the C{translate} method of a Python string.
    """
    table = range(256)
    for _from, to in complementData.iteritems():
        table[ord(_from[0])] = ord(to[0])
    return ''.join(map(chr, table)), complementData

class Read(object):
    """
    Hold information about a single read.

    @param id: A C{str} describing the read.
    @param sequence: A C{str} of sequence information (might be
        nucleotides or proteins).
    @param quality: An optional C{str} of phred quality scores. If not C{None},
        it must be the same length as C{sequence}.
    @raise ValueError: if the length of the quality string (if any) does not
        match the length of the sequence.
    """
    def __init__(self, id, sequence, quality=None, translation_table=None):
        if quality is not None and len(quality) != len(sequence):
            raise ValueError(
                'Invalid read: sequence length (%d) != quality length (%d)' %
                (len(sequence), len(quality)))

        self.id = id
        try:
            self.sequence = sequence.upper()
        except AttributeError:
            self.sequence = sequence
        self.quality = quality
        self.TRANSLATION_TABLE = translation_table

    def __eq__(self, other):
        return (self.id == other.id and
                self.sequence == other.sequence and
                self.quality == other.quality)

    def __ne__(self, other):
        return not self == other

    def __len__(self):
        return len(self.sequence)

    def toString(self, format_):
        """
        Convert the read to a string format.

        @param format_: Either 'fasta' or 'fastq'.
        @raise ValueError: if C{format_} is 'fastq' and the read has no quality
            information, or if an unknown format is requested.
        @return: A C{str} representing the read in the requested format.
        """
        if format_ == 'fasta':
            return '>%s\n%s\n' % (self.id, self.sequence)
        elif format_ == 'fastq':
            if self.quality is None:
                raise ValueError('Read %r has no quality information' %
                                 self.id)
            else:
                return '@%s\n%s\n+%s\n%s\n' % (
                    self.id, self.sequence, self.id, self.quality)
        else:
            raise ValueError("Format must be either 'fasta' or 'fastq'.")

class _NucleotideRead(Read):
    """
    Holds methods to work with nucleotide (DNA and RNA) sequences.
    """
    def translations(self):
        """
        Yield all six translations of a nucleotide sequence.

        @return: A generator that produces six L{TranslatedRead} instances.
        """
        rc = self.reverseComplement().sequence
        for reverseComplemented in False, True:
            for frame in 0, 1, 2:
                seq = rc if reverseComplemented else self.sequence
                # Get the suffix of the sequence for translation. I.e.,
                # skip 0, 1, or 2 initial bases, depending on the frame.
                # Note that this makes a copy of the sequence, which we can
                # then safely append 'N' bases to to adjust its length to
                # be zero mod 3.
                suffix = seq[frame:]
                lengthMod3 = len(suffix) % 3
                if lengthMod3:
                    suffix += ('NN' if lengthMod3 == 1 else 'N')
                yield TranslatedRead(self, translate(suffix), frame,
                                     reverseComplemented)

    def reverseComplement(self):
        """
        Reverse complement a nucleotide sequence.

        @return: The reverse complemented sequence as a C{Read} instance.
        """
        quality = None if self.quality is None else self.quality[::-1]
        translationTable = self.getTranslationTable()
        sequence = self.sequence.translate(translationTable[0])[::-1]
        return (DNARead(self.id, sequence, quality) if (
                translationTable[1] == ambiguous_dna_complement)
                else RNARead(self.id, sequence, quality))

class DNARead(_NucleotideRead):
    """
    Hold information and methods to work with DNA reads.
    """
    def getTranslationTable(self):
        return _makeComplementTable(ambiguous_dna_complement)

class RNARead(_NucleotideRead):
    """
    Hold information and methods to work with RNA reads.
    """
    def getTranslationTable(self):
        return _makeComplementTable(ambiguous_rna_complement)

class AARead(Read):
    """
    Hold information and methods to work with AA reads.
    """
    def properties(self):
        """
        Translate an amino acid sequence to properties.

        @return: A generator that produces an L{PropertiesRead} instance.
        """
        aaSeq = self.sequence
        properties = [PROPERTIES[base] if base in PROPERTIES.keys() else NONE
                      for base in aaSeq]
        return properties

class TranslatedRead(AARead):
    """
    Hold information about one DNA->AA translation of a Read.

    @param originalRead: The original DNA or RNA L{Read} instance from which
        this translation was obtained.
    @param sequence: The C{str} AA translated sequence.
    @param frame: The C{int} frame, either 0, 1, or 2.
    @param reverseComplemented: A C{bool}, C{True} if the original sequence
        must be reverse complemented to obtain this AA sequence.
    """
    def __init__(self, originalRead, sequence, frame,
                 reverseComplemented=False):
        if frame not in (0, 1, 2):
            raise ValueError('Frame must be 0, 1, or 2')
        newId = '%s-frame%d%s' % (originalRead.id, frame,
                                  'rc' if reverseComplemented else '')
        Read.__init__(self, newId, sequence)
        self.originalRead = originalRead
        self.frame = frame
        self.reverseComplemented = reverseComplemented

    def __eq__(self, other):
        return (Read.__eq__(self, other) and
                self.frame == other.frame and
                self.reverseComplemented == other.reverseComplemented and
                self.originalRead == other.originalRead)

    def __ne__(self, other):
        return not self == other

    def maximumORFLength(self):
        """
        Return the length of the longest (possibly partial) ORF in a translated
        read. The ORF may originate or terminate outside the sequence, which is
        why the length is just a lower bound.
        """
        return max(len(orf) for orf in self.sequence.split('*'))

class Reads(object):
    """
    Maintain a collection of sequence reads.
    """

    def __init__(self):
        self.additionalReads = []
        self._length = 0

    def add(self, read):
        """
        Add a read to this collection of reads.

        @param read: A C{Read} instance.
        """
        self.additionalReads.append(read)
        self._length += 1

    def __iter__(self):
        # Reset self._length because __iter__ may be called more than once
        # and we don't want to increment _length each time we iterate.
        self._length = len(self.additionalReads)

        # Look for an 'iter' method in a possible subclass.
        try:
            iter = self.iter()
        except AttributeError:
            pass
        else:
            for read in iter:
                self._length += 1
                yield read

        for read in self.additionalReads:
            yield read

    def __len__(self):
        # Note that len reflects the number of reads that are currently known.
        # If self.__iter__ has not been exhausted, we will not know the true
        # number of reads.
        return self._length

    def save(self, filename, format_='fasta'):
        """
        Write the reads to C{filename} in the requested format.

        @param filename: Either a C{str} file name to save into (the file will
            be overwritten) or an open file descriptor (e.g., sys.stdout).
        @param format_: A C{str} format to save as, either 'fasta' or 'fastq'.
        @raise ValueError: if C{format_} is 'fastq' and a read with no quality
            is present, or if an unknown format is requested.
        """
        format_ = format_.lower()

        if isinstance(filename, basestring):
            with open(filename, 'w') as fp:
                for read in self:
                    fp.write(read.toString(format_))
        else:
            # We have a file-like object.
            for read in self:
                filename.write(read.toString(format_))

    def filter(self, minLength=None, maxLength=None):
        """
        Filter a set of reads to produce a matching subset.

        Note: there are many additional filtering options that could be added,
        e.g., filtering on read id (whitelist, blacklist, regex, etc), GC %,
        and quality.

        @param minLength: The minimum acceptable length.
        @param maxLength: The maximum acceptable length.
        """
        result = Reads()
        for read in self:
            readLen = len(read)
            if ((minLength is None or readLen >= minLength) and
                    (maxLength is None or readLen <= maxLength)):
                result.add(read)
        return result
<|endoftext|>


<commit_before>##############################################################################
# Copyright (c) 2013-2017, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://github.com/llnl/spack
# Please also see the NOTICE and LICENSE files for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (as
# published by the Free Software Foundation) version 2.1, February 1999.
#
# 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 terms and
# conditions of the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
from spack import *
import glob

class IntelTbb(Package):
    """Widely used C++ template library for task parallelism.
    Intel Threading Building Blocks (Intel TBB) lets you easily write parallel
    C++ programs that take full advantage of multicore performance, that are
    portable and composable, and that have future-proof scalability.
    """
    homepage = "http://www.threadingbuildingblocks.org/"

    # Only version-specific URL's work for TBB
    version('2018.0', 'e54de69981905ad69eb9cf0226b9bf5f9a4ba065',
            url='https://github.com/01org/tbb/archive/2018.tar.gz')
    version('2017.6', 'c0a722fd1ae66b40aeab25da6049086ef5f02f17',
            url='https://github.com/01org/tbb/archive/2017_U6.tar.gz')
    version('2017.5', '26f720729d322913912e99d1e4a36bd10625d3ca',
            url='https://github.com/01org/tbb/archive/2017_U5.tar.gz')
    version('2017.3', '2c451a5bcf6fc31487b98b4b29651c369874277c',
            url='https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb2017_20161128oss_src.tgz')
    version('4.4.4', 'd4cee5e4ca75cab5181834877738619c56afeb71',
            url='https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb44_20160413oss_src.tgz')
    version('4.4.3', '80707e277f69d9b20eeebdd7a5f5331137868ce1',
            url='https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb44_20160128oss_src_0.tgz')

    provides('tbb')

    def coerce_to_spack(self, tbb_build_subdir):
        for compiler in ["icc", "gcc", "clang"]:
            fs = glob.glob(join_path(tbb_build_subdir,
                                     "*.%s.inc" % compiler))
            for f in fs:
                lines = open(f).readlines()
                of = open(f, "w")
                for l in lines:
                    if l.strip().startswith("CPLUS ="):
                        of.write("# coerced to spack\n")
                        of.write("CPLUS = $(CXX)\n")
                    elif l.strip().startswith("CPLUS ="):
                        of.write("# coerced to spack\n")
                        of.write("CONLY = $(CC)\n")
                    else:
                        of.write(l)

    def install(self, spec, prefix):
        if spec.satisfies('%gcc@6.1:') and spec.satisfies('@:4.4.3'):
            raise InstallError('Only TBB 4.4.4 and above build with GCC 6.1!')

        # We need to follow TBB's compiler selection logic to get the proper
        # build + link flags but we still need to use spack's compiler wrappers
        # to accomplish this, we do two things:
        #
        # * Look at the spack spec to determine which compiler we should pass
        #   to tbb's Makefile;
        #
        # * patch tbb's build system to use the compiler wrappers (CC, CXX) for
        #   icc, gcc, clang (see coerce_to_spack());
        #
        self.coerce_to_spack("build")

        if spec.satisfies('%clang'):
            tbb_compiler = "clang"
        elif spec.satisfies('%intel'):
            tbb_compiler = "icc"
        else:
            tbb_compiler = "gcc"

        mkdirp(prefix)
        mkdirp(prefix.lib)

        #
        # tbb does not have a configure script or make install target
        # we simply call make, and try to put the pieces together
        #
        make("compiler=%s"  % (tbb_compiler))

        # install headers to {prefix}/include
        install_tree('include', prefix.include)

        # install libs to {prefix}/lib
        tbb_lib_names = ["libtbb",
                         "libtbbmalloc",
                         "libtbbmalloc_proxy"]

        for lib_name in tbb_lib_names:
            # install release libs
            fs = glob.glob(join_path("build", "*release", lib_name + ".*"))
            for f in fs:
                install(f, prefix.lib)
            # install debug libs if they exist
            fs = glob.glob(join_path("build", "*debug", lib_name + "_debug.*"))
            for f in fs:
                install(f, prefix.lib)
<commit_msg>intel-tbb: add 2018.1 (#5769)<commit_after>##############################################################################
# Copyright (c) 2013-2017, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://github.com/llnl/spack
# Please also see the NOTICE and LICENSE files for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (as
# published by the Free Software Foundation) version 2.1, February 1999.
#
# 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 terms and
# conditions of the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
from spack import *
import glob

class IntelTbb(Package):
    """Widely used C++ template library for task parallelism.
    Intel Threading Building Blocks (Intel TBB) lets you easily write parallel
    C++ programs that take full advantage of multicore performance, that are
    portable and composable, and that have future-proof scalability.
    """
    homepage = "http://www.threadingbuildingblocks.org/"

    # Only version-specific URL's work for TBB
    version('2018.1', 'b2f2fa09adf44a22f4024049907f774b',
            url='https://github.com/01org/tbb/archive/2018_U1.tar.gz')
    version('2018.0', 'e54de69981905ad69eb9cf0226b9bf5f9a4ba065',
            url='https://github.com/01org/tbb/archive/2018.tar.gz')
    version('2017.6', 'c0a722fd1ae66b40aeab25da6049086ef5f02f17',
            url='https://github.com/01org/tbb/archive/2017_U6.tar.gz')
    version('2017.5', '26f720729d322913912e99d1e4a36bd10625d3ca',
            url='https://github.com/01org/tbb/archive/2017_U5.tar.gz')
    version('2017.3', '2c451a5bcf6fc31487b98b4b29651c369874277c',
            url='https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb2017_20161128oss_src.tgz')
    version('4.4.4', 'd4cee5e4ca75cab5181834877738619c56afeb71',
            url='https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb44_20160413oss_src.tgz')
    version('4.4.3', '80707e277f69d9b20eeebdd7a5f5331137868ce1',
            url='https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb44_20160128oss_src_0.tgz')

    provides('tbb')

    def coerce_to_spack(self, tbb_build_subdir):
        for compiler in ["icc", "gcc", "clang"]:
            fs = glob.glob(join_path(tbb_build_subdir,
                                     "*.%s.inc" % compiler))
            for f in fs:
                lines = open(f).readlines()
                of = open(f, "w")
                for l in lines:
                    if l.strip().startswith("CPLUS ="):
                        of.write("# coerced to spack\n")
                        of.write("CPLUS = $(CXX)\n")
                    elif l.strip().startswith("CPLUS ="):
                        of.write("# coerced to spack\n")
                        of.write("CONLY = $(CC)\n")
                    else:
                        of.write(l)

    def install(self, spec, prefix):
        if spec.satisfies('%gcc@6.1:') and spec.satisfies('@:4.4.3'):
            raise InstallError('Only TBB 4.4.4 and above build with GCC 6.1!')

        # We need to follow TBB's compiler selection logic to get the proper
        # build + link flags but we still need to use spack's compiler wrappers
        # to accomplish this, we do two things:
        #
        # * Look at the spack spec to determine which compiler we should pass
        #   to tbb's Makefile;
        #
        # * patch tbb's build system to use the compiler wrappers (CC, CXX) for
        #   icc, gcc, clang (see coerce_to_spack());
        #
        self.coerce_to_spack("build")

        if spec.satisfies('%clang'):
            tbb_compiler = "clang"
        elif spec.satisfies('%intel'):
            tbb_compiler = "icc"
        else:
            tbb_compiler = "gcc"

        mkdirp(prefix)
        mkdirp(prefix.lib)

        #
        # tbb does not have a configure script or make install target
        # we simply call make, and try to put the pieces together
        #
        make("compiler=%s"  % (tbb_compiler))

        # install headers to {prefix}/include
        install_tree('include', prefix.include)

        # install libs to {prefix}/lib
        tbb_lib_names = ["libtbb",
                         "libtbbmalloc",
                         "libtbbmalloc_proxy"]

        for lib_name in tbb_lib_names:
            # install release libs
            fs = glob.glob(join_path("build", "*release", lib_name + ".*"))
            for f in fs:
                install(f, prefix.lib)
            # install debug libs if they exist
            fs = glob.glob(join_path("build", "*debug", lib_name + "_debug.*"))
            for f in fs:
                install(f, prefix.lib)
<|endoftext|>


<commit_before># Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class Libbeagle(AutotoolsPackage, CudaPackage):
    """Beagle performs genotype calling, genotype phasing, imputation of
       ungenotyped markers, and identity-by-descent segment detection."""

    homepage = "https://github.com/beagle-dev/beagle-lib"
    url      = "https://github.com/beagle-dev/beagle-lib/archive/v3.1.2.tar.gz"

    version('3.1.2', sha256='dd872b484a3a9f0bce369465e60ccf4e4c0cd7bd5ce41499415366019f236275')
    version('2.1.2', sha256='82ff13f4e7d7bffab6352e4551dfa13afabf82bff54ea5761d1fc1e78341d7de',
            url='https://github.com/beagle-dev/beagle-lib/archive/beagle_release_2_1_2.tar.gz')

    depends_on('autoconf', type='build')
    depends_on('automake', type='build')
    depends_on('libtool',  type='build')
    depends_on('m4',       type='build')

    depends_on('subversion', type='build')
    depends_on('pkgconfig', type='build')
    depends_on('java', type='build')

    cuda_arch_values = CudaPackage.cuda_arch_values
    variant(
        'cuda_arch',
        description='CUDA architecture',
        default='none',
        values=('none',) + cuda_arch_values,
        multi=False
    )
    conflicts('cuda_arch=none', when='+cuda',
              msg='must select a CUDA architecture')

    def patch(self):
        # update cuda architecture if necessary
        if '+cuda' in self.spec:
            cuda_arch = self.spec.variants['cuda_arch'].value
            archflag = '-arch=compute_{0}'.format(cuda_arch)

            filter_file('-arch compute_13', '',
                        'libhmsbeagle/GPU/kernels/Makefile.am',
                        string=True)

            filter_file(r'(NVCCFLAGS="-O3).*(")',
                        r'\1 {0}\2'.format(archflag), 'configure.ac')

            # point CUDA_LIBS to libcuda.so
            filter_file('-L$with_cuda/lib', '-L$with_cuda/lib64/stubs',
                        'configure.ac', string=True)

    def configure_args(self):
        args = [
            # Since spack will inject architecture flags turn off -march=native
            # when building libbeagle.
            '--disable-march-native',
        ]

        if '+cuda' in self.spec:
            args.append('--with-cuda=%s' % self.spec['cuda'].prefix)
        else:
            args.append('--without-cuda')

        return args
<commit_msg>libbeagle: add opencl variant (#27424)<commit_after># Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class Libbeagle(AutotoolsPackage, CudaPackage):
    """Beagle performs genotype calling, genotype phasing, imputation of
       ungenotyped markers, and identity-by-descent segment detection."""

    homepage = "https://github.com/beagle-dev/beagle-lib"
    url      = "https://github.com/beagle-dev/beagle-lib/archive/v3.1.2.tar.gz"

    version('3.1.2', sha256='dd872b484a3a9f0bce369465e60ccf4e4c0cd7bd5ce41499415366019f236275')
    version('2.1.2', sha256='82ff13f4e7d7bffab6352e4551dfa13afabf82bff54ea5761d1fc1e78341d7de',
            url='https://github.com/beagle-dev/beagle-lib/archive/beagle_release_2_1_2.tar.gz')

    depends_on('autoconf', type='build')
    depends_on('automake', type='build')
    depends_on('libtool',  type='build')
    depends_on('m4',       type='build')

    depends_on('subversion', type='build')
    depends_on('pkgconfig', type='build')
    depends_on('java', type='build')
    depends_on('opencl', when='+opencl')

    cuda_arch_values = CudaPackage.cuda_arch_values
    variant('opencl', default=False, description='Include OpenCL (GPU) support')
    variant(
        'cuda_arch',
        description='CUDA architecture',
        default='none',
        values=('none',) + cuda_arch_values,
        multi=False
    )
    conflicts('cuda_arch=none', when='+cuda',
              msg='must select a CUDA architecture')

    def patch(self):
        # update cuda architecture if necessary
        if '+cuda' in self.spec:
            cuda_arch = self.spec.variants['cuda_arch'].value
            archflag = '-arch=compute_{0}'.format(cuda_arch)

            filter_file('-arch compute_13', '',
                        'libhmsbeagle/GPU/kernels/Makefile.am',
                        string=True)

            filter_file(r'(NVCCFLAGS="-O3).*(")',
                        r'\1 {0}\2'.format(archflag), 'configure.ac')

            # point CUDA_LIBS to libcuda.so
            filter_file('-L$with_cuda/lib', '-L$with_cuda/lib64/stubs',
                        'configure.ac', string=True)

    def autoreconf(self, spec, prefix):
        which('bash')('autogen.sh')

    def configure_args(self):
        args = [
            # Since spack will inject architecture flags turn off -march=native
            # when building libbeagle.
            '--disable-march-native',
        ]

        if '+cuda' in self.spec:
            args.append('--with-cuda={0}'.format(self.spec['cuda'].prefix))
        else:
            args.append('--without-cuda')

        if '+opencl' in self.spec:
            args.append('--with-opencl={0}'.format(self.spec['opencl'].prefix))
        else:
            args.append('--without-opencl')

        return args
<|endoftext|>