<commit_before>import os, sys

in_file=sys.argv[1]
out_file=sys.argv[2]

#data needed to construct an egg
#geometry
group=[]
vertex=[]
tangent=[]
binormal=[]
normal=[]
polygon=[]
uv=[]
uv_index=[]
texture=[]
weight=[]
joint=[]

isVertex=False
isTangent=False
isBinormal=False
isNormal=False
isPolygon=False
isUV=False
isUVIndex=False

#read the fbx file
with open(in_file,'r') as fbx:
    for line in fbx:
        if isVertex:
            vertex.append(line.strip('a: ').strip('\n').split(','))
            isVertex=False
        elif isPolygon:
            polygon.append(line.strip('a: ').strip('\n').split(','))
            isPolygon=False
        elif isNormal:
            normal.append(line.strip('a: ').strip('\n').split(','))
            isNormal=False
        elif isBinormal:
            binormal.append(line.strip('a: ').strip('\n').split(','))
            isBinormal=False
        elif isTangent:
            tangent.append(line.strip('a: ').strip('\n').split(','))
            isTangent=False
        elif isUV:
            uv.append(line.strip('a: ').strip('\n').split(','))
            isUV=False
        elif isUVIndex:
            uv_index.append(line.strip('a: ').strip('\n').split(','))
            isUVIndex=False

        if line.strip().startswith('Model:') and line.strip().endswith('"Mesh" {'):
            temp=line.strip().split(',')
            #should be ['Model/Geometry: {some_number}', '"Model::{some_name}"', '"Mesh" {']
            group.append((temp[0].strip('Model: '), temp[1].strip('"Model:: "')))
        elif line.strip().startswith('Vertices'):
            isVertex=True
        elif line.strip().startswith('PolygonVertexIndex'):
            isPolygon=True
        elif line.strip().startswith('Normals'):
            isNormal=True
        elif line.strip().startswith('Binormals'):
            isBinormal=True
        elif line.strip().startswith('Tangents'):
            isTangent=True
        elif line.strip().startswith('UV:'):
            isUV=True
        elif line.strip().startswith('UVIndex:'):
            isUVIndex=True

#convert the fbx data to egg data
egg_data={}
index=0
for gr in group:
    egg_vertex=[]
    egg_poly=[]
    temp_poly=[]
    temp_uv=[]
    poly=[]
    #build a list of polygons
    #the verts are wrong for now - or right if there are no normals and uv :(
    for v in polygon[index]:
        if int(v)>-1:
            poly.append(v)
        else:
            poly.append(int(v)*(-1)-1)
            temp_poly.append(poly)
            poly=[]
    #we need uv for each vert not some funky index
    for i in uv_index[index]:
        temp_uv.append((uv[index][int(i)*2],uv[index][int(i)*2+1]))

    # I was thinking I'd need to remove duplicated verts
    # but I don't - if I do all is mixed up
    #TODO: rewrite this part of the code to be more sane
    id=0
    for polygon in temp_poly:
        new_poly=[]
        for vertId in polygon:
            vert=(vertex[index][int(vertId)*3],vertex[index][int(vertId)*3+1],vertex[index][int(vertId)*3+2])
            norm=(normal[index][id],normal[index][id+1],normal[index][id+2])
            #TODO: check if there are any tbn!!
            tang=(tangent[index][id],tangent[index][id+1],tangent[index][id+2])
            bino=(binormal[index][id],binormal[index][id+1],binormal[index][id+2])
            uv=temp_uv[int(vertId)]
            egg_vertex.append((vert, norm, tang, bino, uv))
            new_poly.append(egg_vertex.index((vert, norm, tang, bino,uv)))
            id+=3
        egg_poly.append(new_poly)

    egg_data[gr[1]]={'vertex':egg_vertex,
                    'poly':egg_poly
                    }
    index+=1
#write the egg file
with open(out_file,'w') as egg:
    egg.write('<CoordinateSystem> { Z-Up }\n\n')
    for group in egg_data:
        egg.write('<Group> '+group+' {\n')
        egg.write('    <VertexPool> '+group+'.verts {\n')
        i=0
        for v in egg_data[group]['vertex']:
            egg.write('        <Vertex> '+str(i)+' {\n')
            egg.write('        '+'{0} {1} {2}'.format(*v[0])+'\n')
            egg.write('            <Normal> {'+'{0} {1} {2}'.format(*egg_data[group]['vertex'][i][1])+'}\n')
            egg.write('            <UV> {\n')
            egg.write('                {0} {1}\n'.format(*egg_data[group]['vertex'][i][4]))
            if tangent:
                egg.write('                <Tangent> {'+'{0} {1} {2}'.format(*egg_data[group]['vertex'][i][2])+'}\n')
                egg.write('                <Binormal> {'+'{0} {1} {2}'.format(*egg_data[group]['vertex'][i][3])+'}\n')
            egg.write('            }\n')
            egg.write('        }\n')
            i+=1
        egg.write('    }\n')
        for v in egg_data[group]['poly']:
            egg.write('    <Polygon> {\n')
            egg.write('    <VertexRef> { ')
            for n in v:
                egg.write(str(n)+" ")
            egg.write(' <Ref> { '+group+'.verts } }\n')
            egg.write('    }\n')
        egg.write('}')

    <commit_msg>Still buged for non triangulated mesh :(<commit_after>import os, sys

def buildVertexData(fbx_data, vertId, rgba, uv, tbnId=None):
    i=3
    if tbnId==None:
        tbnId=vertId
        i=1
    xyz=(fbx_data['Vertices'][index][int(vertId)*i],
         fbx_data['Vertices'][index][int(vertId)*i+1],
         fbx_data['Vertices'][index][int(vertId)*i+2])
    try:
        n=(fbx_data['Normals'][index][int(tbnId)*i],
           fbx_data['Normals'][index][int(tbnId)*i+1],
           fbx_data['Normals'][index][int(tbnId)*i+2])
    except:
        n=None
    try:
        t=(fbx_data['Tangents'][index][int(tbnId)*i],
           fbx_data['Tangents'][index][int(tbnId)*i+1],
           fbx_data['Tangents'][index][int(tbnId)*i+2])
    except:
        t=None
    try:
        b=(fbx_data['Binormals'][index][int(tbnId)*i],
           fbx_data['Binormals'][index][int(tbnId)*i+1],
           fbx_data['Binormals'][index][int(tbnId)*i+2])
    except:
        b=None
    if rgba:
        rgba=rgba[tbnId]
    else:
        rgba=(1,1,1,1)
    if uv:
         uv=temp_uv[tbnId]
    else:
        uv=(0,0)
    vert_dict={'xyz':xyz, 'n':n, 't':t, 'b':b, 'rgba':rgba, 'uv':uv}
    return vert_dict

in_file=sys.argv[1]
out_file=sys.argv[2]

#what are we looking for in the fbx?
fbx_data={'Vertices':[],
        'PolygonVertexIndex':[],
        'Normals':[],
        'Tangents':[],
        'Binormals':[],
        'UV':[],
        'UVIndex':[],
        'Colors':[],
        'ColorIndex':[],
        'Model:':[], #can be Mesh or LimbNode
        'Node':[],#will point to a UI of the matrix that should come next
        'Matrix':[],
        'Deformer':[],# can be "Skin"(useless) or "Cluster" (needed!)
        'Indexes':[],# these should be indexes for weights
        'Weights':[],#membership
        'Transform':[], #not sure yet, looks important
        'TransformLink':[], #not sure yet, looks important
        'Texture:':[],
        'RelativeFilename':[], #texture path, duplicated :|
        'C: ':[], #Connections
        'AnimationCurve':[], #animations (probably only tht UId is of use)
        'KeyValueFloat':[], #animations
        'Material:':[],
        'P: "DiffuseColor"':[], #material diffuse
        'P: "AmbientColor"':[], #material ambient
        'P: "SpecularColor"':[], #material specular
        'P: "Shininess"':[], #material shininess != <Scalar> shininess { number } ???
        'P: "EmissiveColor"':[] #material emissive
        }
#how to format the data?
fbx_format={'Vertices':        lambda x: x.strip('a: ').split(','),
        'PolygonVertexIndex':  lambda x: x.strip('a: ').split(','),
        'Normals':             lambda x: x.strip('a: ').split(','),
        'Tangents':            lambda x: x.strip('a: ').split(','),
        'Binormals':           lambda x: x.strip('a: ').split(','),
        'UV':                  lambda x: x.strip('a: ').split(','),
        'UVIndex':             lambda x: x.strip('a: ').split(','),
        'Colors':              lambda x: x.strip('a: ').split(','),
        'ColorIndex':          lambda x: x.strip('a: ').split(','),
        'Model:':               lambda x: (last_line.split(',')[0].strip('Model: '), last_line.split(',')[1].strip('"Model:: "'),last_line.split(',')[2].strip(' {')),
        'Node':                lambda x: last_line.split(' ')[1],
        'Matrix':              lambda x: x.strip('a: ').split(','),
        'Deformer':            lambda x: None,
        'Indexes':             lambda x: None,
        'Weights':             lambda x: None,
        'Transform':           lambda x: None,
        'TransformLink':       lambda x: None,
        'Texture:':            lambda x: None,
        'RelativeFilename':    lambda x: None,
        'C: ':                 lambda x: None,
        'AnimationCurve':      lambda x: None,
        'KeyValueFloat':       lambda x: None,
        'Material:':           lambda x: None,
        'P: "DiffuseColor"':   lambda x: None,
        'P: "AmbientColor"':   lambda x: None,
        'P: "SpecularColor"':  lambda x: None,
        'P: "Shininess"':      lambda x: None,
        'P: "EmissiveColor"':  lambda x: None
        }

line_type=None
last_line=""
last_line_type=None
#read the fbx file
with open(in_file,'r') as fbx:
    for line in fbx:
        line=line.strip().strip('\n')
        if line_type in fbx_data:
            data=fbx_format[line_type](line)
            if data:
                fbx_data[line_type].append(data)
            line_type=None
            last_line_type=line_type
        for key in fbx_data:
            if line.startswith(key):
                line_type=key
        last_line=line

#data needed to build an egg file
egg_data={'Group':[],#{'name':'', id:''}
          'Vertex':{},#{'xyz':[], 'n':[], 'b':[], 't':[], 'uv':[], 'rgba':[]}
          'Polygon':{},#{'TRef':[],'VertexRef':[], 'id':''}???
          'Joint':[]#{'name:'', 'id':'', 'Transform':[], 'VertexRef':[(vertId,weight)]}???
          }
#find groups and joints
for group in fbx_data['Model:']:
    if group[2]=='"Mesh"':
        egg_data['Group'].append({'name':group[1], 'id':group[0]})
        egg_data['Vertex'][group[1]]=[]
        egg_data['Polygon'][group[1]]=[]
    elif group[2]=='"LimbNode"':
        egg_data['Joint'].append({'name':group[1], 'id':group[0]})
    else:
        print "Unsupported Model type {0}".format(group[2])

#build the data
for index, group in enumerate(egg_data['Group']):
    temp_poly=[]
    poly=[]
    temp_uv=[]
    temp_color=[]
    temp_normal=[]
    temp_vert=[]
    temp_binormal=[]
    temp_tangent=[]
    for vert in fbx_data['PolygonVertexIndex'][index]:
        #if the index is negative it's the 'last' vertex in a poly
        if int(vert)>-1:
            poly.append(vert)
        else:
            poly.append(int(vert)*(-1)-1)
            temp_poly.append(poly)
            poly=[]
    #UV and colors should always be "IndexToDirect",
    #UV are 2 element, colors are 4 element, verts are 3 element so they can't be "Direct"
    try:
        for i in fbx_data['UVIndex'][index]:
            temp_uv.append( (fbx_data['UV'][index][int(i)*2],
                             fbx_data['UV'][index][int(i)*2+1])
                             )
    except:
        pass
    #RGBA
    try:
        for i in fbx_data['ColorIndex'][index]:
            temp_color.append( (fbx_data['Colors'][index][int(i)*4],
                                fbx_data['Colors'][index][int(i)*4+1],
                                fbx_data['Colors'][index][int(i)*4+2],
                                fbx_data['Colors'][index][int(i)*4+3])
                             )
    except:
        pass
    #normals (and tbn) can be "Direct" or "IndexToDirect"
    #in "IndexToDirect" mode there will be 1 normal per vert
    #in "Direct" some verts are implicit and we need to rebuild the vert and poly table
    if len(fbx_data['Normals'][index])==len(fbx_data['Vertices'][index]):
        for vertId, data in enumerate(fbx_data['Vertices'][index]):
            if vertId+2<len(fbx_data['Vertices'][index]):
                vert_dict=buildVertexData(fbx_data, vertId, temp_color, temp_uv)
                egg_data['Vertex'][group['name']].append(vert_dict)
        for polygon in temp_poly:
            new_poly=[]
            for vertId in polygon:
                new_poly.append(vertId)
            egg_data['Polygon'][group['name']].append(new_poly)
    else:
        id=0
        for polygon in temp_poly:
            new_poly=[]
            for vertId in polygon:
                vert_dict=buildVertexData(fbx_data, vertId, temp_color, temp_uv, id)
                egg_data['Vertex'][group['name']].append(vert_dict)
                new_poly.append(id)
                id+=1
            egg_data['Polygon'][group['name']].append(new_poly)

#write the egg file
with open(out_file,'w') as egg:
    #TODO: get "UpAxis" from FBX
    egg.write('<CoordinateSystem> { Z-Up }\n\n')
    #TODO: Textures go here
    for index, group in enumerate(egg_data['Group']):
        egg.write('<Group> {name} {{\n'.format(**group))
        egg.write('    <VertexPool> {name}.verts {{\n'.format(**group))
        for id, vertex in enumerate(egg_data['Vertex'][group['name']]):
            egg.write('        <Vertex> {0} {{\n'.format(id))
            egg.write('        {xyz[0]} {xyz[1]} {xyz[2]}\n'.format(**egg_data['Vertex'][group['name']][id]))
            egg.write('            <Normal> {{ {n[0]} {n[1]} {n[2]} }}\n'.format(**egg_data['Vertex'][group['name']][id]))
            egg.write('            <UV> {\n')
            egg.write('                {uv[0]} {uv[1]}\n'.format(**egg_data['Vertex'][group['name']][id]))
            if egg_data['Vertex'][group['name']][id]['t']:
                egg.write('                <Tangent> {{ {t[0]} {t[1]} {t[2]} }}\n'.format(**egg_data['Vertex'][group['name']][id]))
            if egg_data['Vertex'][group['name']][id]['b']:
                egg.write('                <Binormal> {{ {b[0]} {b[1]} {b[2]} }}\n'.format(**egg_data['Vertex'][group['name']][id]))
            egg.write('            }\n')
            egg.write('        }\n')
        egg.write('    }\n')
        for poly in egg_data['Polygon'][group['name']]:
            egg.write('    <Polygon> {\n')
            egg.write('    <VertexRef> {  ')
            for v in poly:
                egg.write(str(v)+" ")
            egg.write(' <Ref> {{ {name}.verts }} }}\n'.format(**group))
            egg.write('    }\n')
        egg.write('}')
  <|endoftext|>


<commit_before># Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The SFC licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

import pytest

@pytest.mark.xfail_safari
@pytest.mark.xfail_firefox(reason="This is not in release firefox yet")
@pytest.mark.xfail_remote
async def test_check_console_messages(driver, pages):
    pages.load("javascriptPage.html")
    from selenium.webdriver.common.bidi.console import Console
    async with driver.add_listener(Console.ALL) as messages:
        driver.execute_script("console.log('I love cheese')")
    assert messages["message"] == "I love cheese"

@pytest.mark.xfail_safari
@pytest.mark.xfail_firefox(reason="This is not in release firefox yet")
@pytest.mark.xfail_remote
async def test_check_error_console_messages(driver, pages):
    pages.load("javascriptPage.html")
    from selenium.webdriver.common.bidi.console import Console
    async with driver.add_listener(Console.ERROR) as messages:
        driver.execute_script("console.error(\"I don't cheese\")")
        driver.execute_script("console.log('I love cheese')")
    assert messages["message"] == "I don't cheese"

@pytest.mark.xfail_firefox
@pytest.mark.xfail_safari
@pytest.mark.xfail_remote
async def test_collect_js_exceptions(driver, pages):
    pages.load("javascriptPage.html")
    async with driver.add_js_error_listener() as exceptions:
        driver.find_element(By.ID, "throwing-mouseover").click()
    assert exceptions is not None
    assert exceptions.exception_details.stack_trace.call_frames[0].function_name == "onmouseover"

@pytest.mark.xfail_firefox
@pytest.mark.xfail_safari
@pytest.mark.xfail_remote
async def test_collect_log_mutations(driver, pages):
    async with driver.log_mutation_events() as event:
        pages.load("dynamic.html")
        driver.find_element(By.ID, "reveal").click()
        WebDriverWait(driver, 5).until(EC.visibility_of(driver.find_element(By.ID, "revealed")))

    assert event["attribute_name"] == "style"
    assert event["current_value"] == ""
    assert event["old_value"] == "display:none;"
<commit_msg>[py] Add Ignored Exception to wait in Bidi Tests<commit_after># Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The SFC licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
from selenium.common.exceptions import InvalidSelectorException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

import pytest

@pytest.mark.xfail_safari
@pytest.mark.xfail_firefox(reason="This is not in release firefox yet")
@pytest.mark.xfail_remote
async def test_check_console_messages(driver, pages):
    pages.load("javascriptPage.html")
    from selenium.webdriver.common.bidi.console import Console
    async with driver.add_listener(Console.ALL) as messages:
        driver.execute_script("console.log('I love cheese')")
    assert messages["message"] == "I love cheese"

@pytest.mark.xfail_safari
@pytest.mark.xfail_firefox(reason="This is not in release firefox yet")
@pytest.mark.xfail_remote
async def test_check_error_console_messages(driver, pages):
    pages.load("javascriptPage.html")
    from selenium.webdriver.common.bidi.console import Console
    async with driver.add_listener(Console.ERROR) as messages:
        driver.execute_script("console.error(\"I don't cheese\")")
        driver.execute_script("console.log('I love cheese')")
    assert messages["message"] == "I don't cheese"

@pytest.mark.xfail_firefox
@pytest.mark.xfail_safari
@pytest.mark.xfail_remote
async def test_collect_js_exceptions(driver, pages):
    pages.load("javascriptPage.html")
    async with driver.add_js_error_listener() as exceptions:
        driver.find_element(By.ID, "throwing-mouseover").click()
    assert exceptions is not None
    assert exceptions.exception_details.stack_trace.call_frames[0].function_name == "onmouseover"

@pytest.mark.xfail_firefox
@pytest.mark.xfail_safari
@pytest.mark.xfail_remote
async def test_collect_log_mutations(driver, pages):
    async with driver.log_mutation_events() as event:
        pages.load("dynamic.html")
        driver.find_element(By.ID, "reveal").click()
        WebDriverWait(driver, 5, ignored_exceptions=InvalidSelectorException)\
            .until(EC.visibility_of(driver.find_element(By.ID, "revealed")))

    assert event["attribute_name"] == "style"
    assert event["current_value"] == ""
    assert event["old_value"] == "display:none;"
<|endoftext|>


<commit_before>#!/usr/bin/env python
# encoding: utf-8

# The MIT License (MIT)

# Copyright (c) 2018 CNRS

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# AUTHORS
# Hervé BREDIN - http://herve.niderb.fr

"""Resegmentation"""

import collections
import numpy as np
from .base import LabelingTask
from .base import LabelingTaskGenerator
from pyannote.database.protocol import SpeakerDiarizationProtocol
from pyannote.audio.labeling.models import StackedRNN
from pyannote.audio.util import from_numpy
from pyannote.database import get_unique_identifier
from pyannote.database import get_annotated
from pyannote.audio.labeling.extraction import SequenceLabeling

class ResegmentationGenerator(LabelingTaskGenerator):

    def __init__(self, precomputed, **kwargs):
        super(ResegmentationGenerator, self).__init__(
            precomputed, exhaustive=True, shuffle=True, **kwargs)

    def postprocess_y(self, Y):
        """Generate labels for resegmentation

        Parameters
        ----------
        Y : (n_samples, n_speakers) numpy.ndarray
            Discretized annotation returned by `pyannote.audio.util.to_numpy`.

        Returns
        -------
        y : (n_samples, 1) numpy.ndarray

        See also
        --------
        `pyannote.audio.util.to_numpy`
        """

        # +1 because...
        y = np.argmax(Y, axis=1) + 1

        # ... 0 is for non-speech
        non_speech = np.sum(Y, axis=1) == 0
        y[non_speech] = 0

        return np.int64(y)[:, np.newaxis]

class Resegmentation(LabelingTask):
    """

    Parameters
    ----------
    epochs : int, optional
        (Self-)train for that many epochs. Defaults to 10.
    ensemble : int, optional

    """

    # TODO -- ensemble of last K epochs

    def __init__(self, precomputed, epochs=10, ensemble=1, rnn='LSTM',
                 recurrent=[16, ], bidirectional=True, linear=[16, ], **kwargs):
        super(Resegmentation, self).__init__(**kwargs)
        self.precomputed = precomputed
        self.epochs = epochs
        self.ensemble = ensemble

        self.rnn = rnn
        self.recurrent = recurrent
        self.bidirectional = bidirectional
        self.linear = linear

    def get_batch_generator(self, precomputed):
        return ResegmentationGenerator(
            precomputed, duration=self.duration, per_epoch=self.per_epoch,
            batch_size=self.batch_size, parallel=self.parallel)

    @property
    def n_classes(self):
        if not hasattr(self, 'n_classes_'):
            raise AttributeError('Call .apply() to set `n_classes` attribute')
        return self.n_classes_

    def get_dummy_protocol(self, current_file):

        class DummyProtocol(SpeakerDiarizationProtocol):

            def trn_iter(self):
                yield current_file

            def dev_iter(self):
                yield current_file

            def tst_iter(self):
                yield current_file

        return DummyProtocol()

    def get_hypothesis(self, model, current_file, gpu=False):

        sequence_labeling = SequenceLabeling(
            model, self.precomputed, self.duration,
            step=.25*self.duration, batch_size=self.batch_size,
            source='audio', gpu=gpu)

        # add scores of current epoch to ensemble
        self.scores_.append(sequence_labeling.apply(current_file))

        # get ensemble scores (average of last self.ensemble epochs)
        scores = sum(s.data for s in self.scores_) / len(self.scores_)

        # TODO. replace argmax by Viterbi decoding
        self.y_ = np.argmax(scores, axis=1)
        return from_numpy(self.y_, self.precomputed,
                          labels=self.batch_generator_.labels)

    def apply_iter(self, current_file, hypothesis,
                   partial=True, gpu=False,
                   log_dir=None):

        current_file = dict(current_file)
        current_file['annotation'] = hypothesis

        # set `per_epoch` attribute to current file annotated duration
        self.per_epoch = get_annotated(current_file).duration()

        # number of speakers + 1 for non-speech
        self.n_classes_ = len(hypothesis.labels()) + 1

        model = StackedRNN(self.precomputed.dimension(), self.n_classes,
                           rnn=self.rnn, recurrent=self.recurrent,
                           linear=self.linear,
                           bidirectional=self.bidirectional,
                           logsoftmax=True)

        # initialize dummy protocol that has only one file
        protocol = self.get_dummy_protocol(current_file)

        if log_dir is not None:
            uri = get_unique_identifier(current_file)
            log_dir = 'f{log_dir}/{uri}'

        self.scores_ = collections.deque([], maxlen=self.ensemble)

        for iteration in self.fit_iter(model, self.precomputed, protocol,
                                       log_dir=log_dir, epochs=self.epochs,
                                       gpu=gpu):

            if partial:
                hypothesis = self.get_hypothesis(iteration['model'],
                                                 current_file, gpu=gpu)
                yield hypothesis

        if not partial:
            hypothesis = self.get_hypothesis(iteration['model'], current_file,
                                             gpu=gpu)

        yield hypothesis

    def apply(self, current_file, hypothesis, gpu=False, log_dir=None):
        for hypothesis in self.apply_iter(current_file, hypothesis,
                                          partial=False, gpu=gpu):
            pass

        return hypothesis

<commit_msg>chore: make code a bit more modular (+ docstrings)<commit_after>#!/usr/bin/env python
# encoding: utf-8

# The MIT License (MIT)

# Copyright (c) 2018 CNRS

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# AUTHORS
# Hervé BREDIN - http://herve.niderb.fr

"""Resegmentation"""

import collections
import numpy as np
from .base import LabelingTask
from .base import LabelingTaskGenerator
from pyannote.database.protocol import SpeakerDiarizationProtocol
from pyannote.audio.labeling.models import StackedRNN
from pyannote.audio.util import from_numpy
from pyannote.database import get_unique_identifier
from pyannote.database import get_annotated
from pyannote.audio.labeling.extraction import SequenceLabeling

class ResegmentationGenerator(LabelingTaskGenerator):

    def __init__(self, precomputed, **kwargs):
        super(ResegmentationGenerator, self).__init__(
            precomputed, exhaustive=True, shuffle=True, **kwargs)

    def postprocess_y(self, Y):
        """Generate labels for resegmentation

        Parameters
        ----------
        Y : (n_samples, n_speakers) numpy.ndarray
            Discretized annotation returned by `pyannote.audio.util.to_numpy`.

        Returns
        -------
        y : (n_samples, 1) numpy.ndarray

        See also
        --------
        `pyannote.audio.util.to_numpy`
        """

        # +1 because...
        y = np.argmax(Y, axis=1) + 1

        # ... 0 is for non-speech
        non_speech = np.sum(Y, axis=1) == 0
        y[non_speech] = 0

        return np.int64(y)[:, np.newaxis]

class Resegmentation(LabelingTask):
    """

    Parameters
    ----------
    epochs : int, optional
        (Self-)train for that many epochs. Defaults to 10.
    ensemble : int, optional

    """

    # TODO -- ensemble of last K epochs

    def __init__(self, precomputed, epochs=10, ensemble=1, rnn='LSTM',
                 recurrent=[16, ], bidirectional=True, linear=[16, ], **kwargs):
        super(Resegmentation, self).__init__(**kwargs)
        self.precomputed = precomputed
        self.epochs = epochs
        self.ensemble = ensemble

        self.rnn = rnn
        self.recurrent = recurrent
        self.bidirectional = bidirectional
        self.linear = linear

    def get_batch_generator(self, precomputed):
        return ResegmentationGenerator(
            precomputed, duration=self.duration, per_epoch=self.per_epoch,
            batch_size=self.batch_size, parallel=self.parallel)

    @property
    def n_classes(self):
        if not hasattr(self, 'n_classes_'):
            raise AttributeError('Call .apply() to set `n_classes` attribute')
        return self.n_classes_

    def get_dummy_protocol(self, current_file):
        """Get dummy protocol containing only `current_file`

        Parameters
        ----------
        current_file : pyannote.database dict

        Returns
        -------
        protocol : SpeakerDiarizationProtocol instance
            Dummy protocol containing only `current_file` in both train,
            dev., and test sets.

        """

        class DummyProtocol(SpeakerDiarizationProtocol):

            def trn_iter(self):
                yield current_file

            def dev_iter(self):
                yield current_file

            def tst_iter(self):
                yield current_file

        return DummyProtocol()

    def _score(self, model, current_file, gpu=False):
        """Apply current model on current file

        Parameters
        ----------
        model : nn.Module
            Current state of the model.
        current_file : pyannote.database dict
            Current file.
        gpu : bool, optional
            Process on GPU. Defaults to False.

        Returns
        -------
        scores : SlidingWindowFeature
            Sequence labeling scores.
        """

        # initialize sequence labeling with model and features
        sequence_labeling = SequenceLabeling(
            model, self.precomputed, self.duration,
            step=.25*self.duration, batch_size=self.batch_size,
            source='audio', gpu=gpu)

        return sequence_labeling.apply(current_file)

    def _decode(self, scores):
        """Decoding

        Parameters
        ----------
        scores : iterable of SlidingWindowFeature instances
            Raw scores.

        Returns
        -------
        hypothesis : pyannote.core.Annotation
            Decoded scores.
        """

        # get ensemble scores (average of last self.ensemble epochs)
        avg_scores = sum(s.data for s in scores) / len(scores)

        # TODO. replace argmax by Viterbi decoding
        self.y_ = np.argmax(avg_scores, axis=1)
        return from_numpy(self.y_, self.precomputed,
                          labels=self.batch_generator_.labels)

    def apply_iter(self, current_file, hypothesis,
                   partial=True, gpu=False,
                   log_dir=None):
        """Yield re-segmentation results for each epoch

        Parameters
        ----------
        current_file : pyannote.database dict
            Currently processed file
        hypothesis : pyannote.core.Annotation
            Input segmentation
        partial : bool, optional
            Set to False to only yield final re-segmentation.
            Set to True to yield re-segmentation after each epoch.
        gpu : bool, optional
            Process on GPU.
        log_dir : str, optional
            Path to log directory.

        Yields
        ------
        resegmented : pyannote.core.Annotation
            Resegmentation results after each epoch.
        """

        current_file = dict(current_file)
        current_file['annotation'] = hypothesis

        # set `per_epoch` attribute to current file annotated duration
        self.per_epoch = get_annotated(current_file).duration()

        # number of speakers + 1 for non-speech
        self.n_classes_ = len(hypothesis.labels()) + 1

        model = StackedRNN(self.precomputed.dimension(), self.n_classes,
                           rnn=self.rnn, recurrent=self.recurrent,
                           linear=self.linear,
                           bidirectional=self.bidirectional,
                           logsoftmax=True)

        # initialize dummy protocol that has only one file
        protocol = self.get_dummy_protocol(current_file)

        if log_dir is not None:
            uri = get_unique_identifier(current_file)
            log_dir = 'f{log_dir}/{uri}'

        scores = collections.deque([], maxlen=self.ensemble)

        iterations = self.fit_iter(model, self.precomputed, protocol,
                                   log_dir=log_dir, epochs=self.epochs,
                                   gpu=gpu)

        for i, iteration in enumerate(iterations):

            # if 'partial', compute scores for every iteration
            # if not, compute scores for last 'ensemble' iterations only
            if partial or (i + 1 > self.epochs - self.ensemble):
                iteration_score = self._score(iteration['model'],
                                              current_file, gpu=gpu)
                scores.append(iteration_score)

            # if 'partial', generate (and yield) hypothesis
            if partial:
                hypothesis = self._decode(scores)
                yield hypothesis

        # generate (and yield) hypothesis in case it's not already
        if not partial:
            hypothesis = self._decode(scores)
            yield hypothesis

    def apply(self, current_file, hypothesis, gpu=False, log_dir=None):
        for hypothesis in self.apply_iter(current_file, hypothesis,
                                          partial=False, gpu=gpu):
            pass

        return hypothesis

<|endoftext|>


<commit_before>from servable import Servable
from graphserver.graphdb import GraphDatabase
import cgi
from graphserver.core import State, WalkOptions
import time
import sys
import graphserver
from graphserver.util import TimeHelpers
from graphserver.ext.gtfs.gtfsdb import GTFSDatabase
try:
    import json
except ImportError:
    import simplejson as json
import yaml
import os
from fcgi import WSGIServer

from events import BoardEvent, AlightEvent, HeadwayBoardEvent, HeadwayAlightEvent, StreetEvent, StreetTurnEvent

class SelfEncoderHelper(json.JSONEncoder):
    def default(self, obj):
        if hasattr(obj, "to_jsonable"):
            return obj.to_jsonable()
        return json.JSONEncoder.default(self, obj)

def postprocess_path_raw(vertices, edges):
    retbuilder = []

    retbuilder.append("vertices")
    for i, vertex in enumerate(vertices):
        retbuilder.append( "%d %s"%(i, str(vertex)) )

    retbuilder.append("")
    retbuilder.append("states")
    for i, vertex in enumerate(vertices):
        retbuilder.append( "%d %s"%(i, str(vertex.payload)) )

    retbuilder.append("")
    retbuilder.append("edges")
    for i, edge in enumerate(edges):
        retbuilder.append( "%d %s"%(i, str(edge.payload)) )

    return "\n".join(retbuilder)

def postprocess_path(vertices, edges, vertex_events, edge_events):
    context = {}

    for edge1,vertex1,edge2,vertex2 in zip( [None]+edges, vertices, edges+[None], vertices[1:]+[None,None] ):
        #fire vertex events
        for handler in vertex_events:
            if handler.applies_to( edge1, vertex1, edge2 ):
                yield handler( edge1, vertex1, edge2, context=context )

        #fire edge events
        for handler in edge_events:
            if handler.applies_to( vertex1, edge2, vertex2 ):
                yield handler( vertex1, edge2, vertex2, context=context )

class RouteServer(Servable):
    def __init__(self, graphdb_filename, vertex_events, edge_events, vertex_reverse_geocoders):
        graphdb = GraphDatabase( graphdb_filename )
        self.graph = graphdb.incarnate()
        self.vertex_events = vertex_events
        self.edge_events = edge_events
        self.vertex_reverse_geocoders = vertex_reverse_geocoders

    def bounds(self, jsoncallback=None):
        """returns bounding box that encompases the bounding box from all member reverse geocoders"""

        l, b, r, t = None, None, None, None

        for reverse_geocoder in self.vertex_reverse_geocoders:
            gl, gb, gr, gt = reverse_geocoder.bounds()
            l = min(l,gl) if l else gl
            b = min(b,gb) if b else gb
            r = max(r,gr) if r else gr
            t = max(t,gt) if t else gt

        if jsoncallback is None:
            return json.dumps([l,b,r,t])
        else:
            return "%s(%s)"%(jsoncallback,json.dumps([l,b,r,t]))

    def vertices(self):
        return "\n".join( [vv.label for vv in self.graph.vertices] )
    vertices.mime = "text/plain"

    def get_vertex_id_raw( self, lat, lon ):
        for reverse_geocoder in self.vertex_reverse_geocoders:
            ret = reverse_geocoder( lat, lon )
            if ret is not None:
                return ret

        return None

    def get_vertex_id( self, lat, lon ):
        return json.dumps( self.get_vertex_id_raw( lat, lon ) )

    def path(self,
             origin,
             dest,
             currtime=None,
             time_offset=None,
             transfer_penalty=0,
             walking_speed=1.0,
             hill_reluctance=1.5,
             turn_penalty=None,
             walking_reluctance=None,
             max_walk=None,
             jsoncallback=None):

        performance = {}

        if currtime is None:
            currtime = int(time.time())

        if time_offset is not None:
            currtime += time_offset

        # time path query
        t0 = time.time()
        wo = WalkOptions()
        wo.transfer_penalty=transfer_penalty
        wo.walking_speed=walking_speed
        wo.hill_reluctance=hill_reluctance
        if turn_penalty is not None:
            wo.turn_penalty = turn_penalty
        if walking_reluctance is not None:
            wo.walking_reluctance = walking_reluctance
        if max_walk is not None:
            wo.max_walk = max_walk
        spt = self.graph.shortest_path_tree( origin, dest, State(1,currtime), wo )

        vertices, edges = spt.path( dest )
        performance['path_query_time'] = time.time()-t0

        t0 = time.time()
        narrative = list(postprocess_path(vertices, edges, self.vertex_events, self.edge_events))
        performance['narrative_postprocess_time'] = time.time()-t0

        t0 = time.time()
        wo.destroy()
        spt.destroy()
        performance['cleanup_time'] = time.time()-t0

        ret = {'narrative':narrative, 'performance':performance}

        if jsoncallback is None:
            return json.dumps(ret, indent=2, cls=SelfEncoderHelper)
        else:
            return "%s(%s)"%(jsoncallback,json.dumps(ret, indent=2, cls=SelfEncoderHelper))

    def geompath(self, lat1,lon1,lat2,lon2,
                 currtime=None,
                 time_offset=None,
                 transfer_penalty=0,
                 walking_speed=1.0,
                 hill_reluctance=1.5,
                 turn_penalty=None,
                 walking_reluctance=None,
                 max_walk=None,
                 jsoncallback=None):
        origin_vertex_label = self.get_vertex_id_raw( lat1, lon1 )
        dest_vertex_label = self.get_vertex_id_raw( lat2, lon2 )

        if origin_vertex_label is None:
            raise Exception( "could not find a vertex near (%s,%s)"%(lat1,lon1) )
        if dest_vertex_label is None:
            raise Exception( "could not find a vertex near (%s,%s)"%(lat2,lon2) )

        return self.path( origin_vertex_label,
                     dest_vertex_label,
                     currtime,
                     time_offset,
                     transfer_penalty,
                     walking_speed,
                     hill_reluctance,
                     turn_penalty,
                     walking_reluctance,
                     max_walk,
                     jsoncallback )

    def path_retro(self, origin, dest, currtime=None, time_offset=None, transfer_penalty=0, walking_speed=1.0):
        if currtime is None:
            currtime = int(time.time())

        if time_offset is not None:
            currtime += time_offset

        wo = WalkOptions()
        wo.transfer_penalty = transfer_penalty
        wo.walking_speed = walking_speed
        spt = self.graph.shortest_path_tree_retro( origin, dest, State(1,currtime), wo )
        wo.destroy()

        vertices, edges = spt.path_retro( origin )

        ret = list(postprocess_path(vertices, edges, self.vertex_events, self.edge_events))

        spt.destroy()

        return json.dumps(ret, indent=2, cls=SelfEncoderHelper)

    def path_raw(self, origin, dest, currtime=None):
        if currtime is None:
            currtime = int(time.time())

        wo = WalkOptions()
        spt = self.graph.shortest_path_tree( origin, dest, State(1,currtime), wo )
        wo.destroy()

        vertices, edges = spt.path( dest )

        ret = postprocess_path_raw(vertices, edges)

        spt.destroy()

        return ret

    def path_raw_retro(self, origin, dest, currtime):

        wo = WalkOptions()
        spt = self.graph.shortest_path_tree_retro( origin, dest, State(1,currtime), wo )
        wo.destroy()

        vertices, edges = spt.path_retro( origin )

        ret = postprocess_path_raw(vertices, edges)

        spt.destroy()

        return ret

def import_class(handler_class_path_string):
    sys.path.append( os.getcwd() )

    handler_class_path = handler_class_path_string.split(".")

    class_name = handler_class_path[-1]
    package_name = ".".join(handler_class_path[:-1])

    package = __import__(package_name, fromlist=[class_name])

    try:
        handler_class = getattr( package, class_name )
    except AttributeError:
        raise AttributeError( "Can't find %s. Only %s"%(class_name, dir(package)) )

    return handler_class

def get_handler_instances( handler_definitions, handler_type ):
    if handler_definitions is None:
        return

    if handler_type not in handler_definitions:
        return

    for handler in handler_definitions[handler_type]:
        handler_class = import_class( handler['name'] )
        handler_instance = handler_class(**handler.get("args", {}))

        yield handler_instance

from optparse import OptionParser
def main():

    # get command line input
    usage = """python routeserver.py graphdb_filename config_filename"""
    parser = OptionParser(usage=usage)
    parser.add_option("-p", "--port", dest="port", default="8080",
                      help="Port to serve HTTP, if serving as a standalone server")
    parser.add_option("-s", "--socket", dest="socket", default=None,
                      help="Socket on which serve fastCGI. If both port and socket are specified, serves as an fastCGI backend.")

    (options, args) = parser.parse_args()

    if len(args) != 2:
        parser.print_help()
        exit(-1)

    graphdb_filename, config_filename = args

    # get narrative handler classes
    handler_definitions = yaml.load( open(config_filename).read() )

    edge_events = list(get_handler_instances( handler_definitions, 'edge_handlers' ) )
    vertex_events = list(get_handler_instances( handler_definitions, 'vertex_handlers' ) )
    vertex_reverse_geocoders = list(get_handler_instances( handler_definitions, 'vertex_reverse_geocoders' ) )

    # explain to the nice people which handlers were loaded
    print "edge event handlers:"
    for edge_event in edge_events:
        print "   %s"%edge_event
    print "vertex event handlers:"
    for vertex_event in vertex_events:
        print "   %s"%vertex_event
    print "vertex reverse geocoders:"
    for vertex_reverse_geocoder in vertex_reverse_geocoders:
        print "   %s"%vertex_reverse_geocoder

    # start up the routeserver
    gc = RouteServer(graphdb_filename, vertex_events, edge_events, vertex_reverse_geocoders)

    # serve as either an HTTP server or an fastCGI backend
    if options.socket:
        print "Starting fastCGI backend serving at %s"%options.socket
        WSGIServer(gc.wsgi_app(), bindAddress = options.socket).run()
    else:
        gc.run_test_server(port=int(options.port))

if __name__ == '__main__':
    main()<commit_msg>routeplanner returns name of handler with each event<commit_after>from servable import Servable
from graphserver.graphdb import GraphDatabase
import cgi
from graphserver.core import State, WalkOptions
import time
import sys
import graphserver
from graphserver.util import TimeHelpers
from graphserver.ext.gtfs.gtfsdb import GTFSDatabase
try:
    import json
except ImportError:
    import simplejson as json
import yaml
import os
from fcgi import WSGIServer

from events import BoardEvent, AlightEvent, HeadwayBoardEvent, HeadwayAlightEvent, StreetEvent, StreetTurnEvent

class SelfEncoderHelper(json.JSONEncoder):
    def default(self, obj):
        if hasattr(obj, "to_jsonable"):
            return obj.to_jsonable()
        return json.JSONEncoder.default(self, obj)

def postprocess_path_raw(vertices, edges):
    retbuilder = []

    retbuilder.append("vertices")
    for i, vertex in enumerate(vertices):
        retbuilder.append( "%d %s"%(i, str(vertex)) )

    retbuilder.append("")
    retbuilder.append("states")
    for i, vertex in enumerate(vertices):
        retbuilder.append( "%d %s"%(i, str(vertex.payload)) )

    retbuilder.append("")
    retbuilder.append("edges")
    for i, edge in enumerate(edges):
        retbuilder.append( "%d %s"%(i, str(edge.payload)) )

    return "\n".join(retbuilder)

def postprocess_path(vertices, edges, vertex_events, edge_events):
    context = {}

    for edge1,vertex1,edge2,vertex2 in zip( [None]+edges, vertices, edges+[None], vertices[1:]+[None,None] ):
        #fire vertex events
        for handler in vertex_events:
            if handler.applies_to( edge1, vertex1, edge2 ):
                yield handler.__class__.__name__, handler( edge1, vertex1, edge2, context=context )

        #fire edge events
        for handler in edge_events:
            if handler.applies_to( vertex1, edge2, vertex2 ):
                yield handler.__class__.__name__, handler( vertex1, edge2, vertex2, context=context )

class RouteServer(Servable):
    def __init__(self, graphdb_filename, vertex_events, edge_events, vertex_reverse_geocoders):
        graphdb = GraphDatabase( graphdb_filename )
        self.graph = graphdb.incarnate()
        self.vertex_events = vertex_events
        self.edge_events = edge_events
        self.vertex_reverse_geocoders = vertex_reverse_geocoders

    def bounds(self, jsoncallback=None):
        """returns bounding box that encompases the bounding box from all member reverse geocoders"""

        l, b, r, t = None, None, None, None

        for reverse_geocoder in self.vertex_reverse_geocoders:
            gl, gb, gr, gt = reverse_geocoder.bounds()
            l = min(l,gl) if l else gl
            b = min(b,gb) if b else gb
            r = max(r,gr) if r else gr
            t = max(t,gt) if t else gt

        if jsoncallback is None:
            return json.dumps([l,b,r,t])
        else:
            return "%s(%s)"%(jsoncallback,json.dumps([l,b,r,t]))

    def vertices(self):
        return "\n".join( [vv.label for vv in self.graph.vertices] )
    vertices.mime = "text/plain"

    def get_vertex_id_raw( self, lat, lon ):
        for reverse_geocoder in self.vertex_reverse_geocoders:
            ret = reverse_geocoder( lat, lon )
            if ret is not None:
                return ret

        return None

    def get_vertex_id( self, lat, lon ):
        return json.dumps( self.get_vertex_id_raw( lat, lon ) )

    def path(self,
             origin,
             dest,
             currtime=None,
             time_offset=None,
             transfer_penalty=0,
             walking_speed=1.0,
             hill_reluctance=1.5,
             turn_penalty=None,
             walking_reluctance=None,
             max_walk=None,
             jsoncallback=None):

        performance = {}

        if currtime is None:
            currtime = int(time.time())

        if time_offset is not None:
            currtime += time_offset

        # time path query
        t0 = time.time()
        wo = WalkOptions()
        wo.transfer_penalty=transfer_penalty
        wo.walking_speed=walking_speed
        wo.hill_reluctance=hill_reluctance
        if turn_penalty is not None:
            wo.turn_penalty = turn_penalty
        if walking_reluctance is not None:
            wo.walking_reluctance = walking_reluctance
        if max_walk is not None:
            wo.max_walk = max_walk
        spt = self.graph.shortest_path_tree( origin, dest, State(1,currtime), wo )

        vertices, edges = spt.path( dest )
        performance['path_query_time'] = time.time()-t0

        t0 = time.time()
        narrative = list(postprocess_path(vertices, edges, self.vertex_events, self.edge_events))
        performance['narrative_postprocess_time'] = time.time()-t0

        t0 = time.time()
        wo.destroy()
        spt.destroy()
        performance['cleanup_time'] = time.time()-t0

        ret = {'narrative':narrative, 'performance':performance}

        if jsoncallback is None:
            return json.dumps(ret, indent=2, cls=SelfEncoderHelper)
        else:
            return "%s(%s)"%(jsoncallback,json.dumps(ret, indent=2, cls=SelfEncoderHelper))

    def geompath(self, lat1,lon1,lat2,lon2,
                 currtime=None,
                 time_offset=None,
                 transfer_penalty=0,
                 walking_speed=1.0,
                 hill_reluctance=1.5,
                 turn_penalty=None,
                 walking_reluctance=None,
                 max_walk=None,
                 jsoncallback=None):
        origin_vertex_label = self.get_vertex_id_raw( lat1, lon1 )
        dest_vertex_label = self.get_vertex_id_raw( lat2, lon2 )

        if origin_vertex_label is None:
            raise Exception( "could not find a vertex near (%s,%s)"%(lat1,lon1) )
        if dest_vertex_label is None:
            raise Exception( "could not find a vertex near (%s,%s)"%(lat2,lon2) )

        return self.path( origin_vertex_label,
                     dest_vertex_label,
                     currtime,
                     time_offset,
                     transfer_penalty,
                     walking_speed,
                     hill_reluctance,
                     turn_penalty,
                     walking_reluctance,
                     max_walk,
                     jsoncallback )

    def path_retro(self, origin, dest, currtime=None, time_offset=None, transfer_penalty=0, walking_speed=1.0):
        if currtime is None:
            currtime = int(time.time())

        if time_offset is not None:
            currtime += time_offset

        wo = WalkOptions()
        wo.transfer_penalty = transfer_penalty
        wo.walking_speed = walking_speed
        spt = self.graph.shortest_path_tree_retro( origin, dest, State(1,currtime), wo )
        wo.destroy()

        vertices, edges = spt.path_retro( origin )

        ret = list(postprocess_path(vertices, edges, self.vertex_events, self.edge_events))

        spt.destroy()

        return json.dumps(ret, indent=2, cls=SelfEncoderHelper)

    def path_raw(self, origin, dest, currtime=None):
        if currtime is None:
            currtime = int(time.time())

        wo = WalkOptions()
        spt = self.graph.shortest_path_tree( origin, dest, State(1,currtime), wo )
        wo.destroy()

        vertices, edges = spt.path( dest )

        ret = postprocess_path_raw(vertices, edges)

        spt.destroy()

        return ret

    def path_raw_retro(self, origin, dest, currtime):

        wo = WalkOptions()
        spt = self.graph.shortest_path_tree_retro( origin, dest, State(1,currtime), wo )
        wo.destroy()

        vertices, edges = spt.path_retro( origin )

        ret = postprocess_path_raw(vertices, edges)

        spt.destroy()

        return ret

def import_class(handler_class_path_string):
    sys.path.append( os.getcwd() )

    handler_class_path = handler_class_path_string.split(".")

    class_name = handler_class_path[-1]
    package_name = ".".join(handler_class_path[:-1])

    package = __import__(package_name, fromlist=[class_name])

    try:
        handler_class = getattr( package, class_name )
    except AttributeError:
        raise AttributeError( "Can't find %s. Only %s"%(class_name, dir(package)) )

    return handler_class

def get_handler_instances( handler_definitions, handler_type ):
    if handler_definitions is None:
        return

    if handler_type not in handler_definitions:
        return

    for handler in handler_definitions[handler_type]:
        handler_class = import_class( handler['name'] )
        handler_instance = handler_class(**handler.get("args", {}))

        yield handler_instance

from optparse import OptionParser
def main():

    # get command line input
    usage = """python routeserver.py graphdb_filename config_filename"""
    parser = OptionParser(usage=usage)
    parser.add_option("-p", "--port", dest="port", default="8080",
                      help="Port to serve HTTP, if serving as a standalone server")
    parser.add_option("-s", "--socket", dest="socket", default=None,
                      help="Socket on which serve fastCGI. If both port and socket are specified, serves as an fastCGI backend.")

    (options, args) = parser.parse_args()

    if len(args) != 2:
        parser.print_help()
        exit(-1)

    graphdb_filename, config_filename = args

    # get narrative handler classes
    handler_definitions = yaml.load( open(config_filename).read() )

    edge_events = list(get_handler_instances( handler_definitions, 'edge_handlers' ) )
    vertex_events = list(get_handler_instances( handler_definitions, 'vertex_handlers' ) )
    vertex_reverse_geocoders = list(get_handler_instances( handler_definitions, 'vertex_reverse_geocoders' ) )

    # explain to the nice people which handlers were loaded
    print "edge event handlers:"
    for edge_event in edge_events:
        print "   %s"%edge_event
    print "vertex event handlers:"
    for vertex_event in vertex_events:
        print "   %s"%vertex_event
    print "vertex reverse geocoders:"
    for vertex_reverse_geocoder in vertex_reverse_geocoders:
        print "   %s"%vertex_reverse_geocoder

    # start up the routeserver
    gc = RouteServer(graphdb_filename, vertex_events, edge_events, vertex_reverse_geocoders)

    # serve as either an HTTP server or an fastCGI backend
    if options.socket:
        print "Starting fastCGI backend serving at %s"%options.socket
        WSGIServer(gc.wsgi_app(), bindAddress = options.socket).run()
    else:
        gc.run_test_server(port=int(options.port))

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


<commit_before>#
# This file is part of the PyMeasure package.
#
# Copyright (c) 2013-2020 PyMeasure Developers
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#

import logging
import time
import re

import numpy as np

from pymeasure.instruments import Instrument
from pymeasure.instruments.validators import truncated_range
from .buffer import KeithleyBuffer

log = logging.getLogger(__name__)
log.addHandler(logging.NullHandler())

class Keithley6517B(Instrument, KeithleyBuffer):
    """ Represents the Keithely 6517B ElectroMeter and provides a
    high-level interface for interacting with the instrument.

    .. code-block:: python

        keithley = Keithley6517B("GPIB::1")

        keithley.apply_voltage()              # Sets up to source current
        keithley.source_voltage_range = 200   # Sets the source voltage
                                              # range to 200 V
        keithley.source_voltage = 20          # Sets the source voltage to 20 V
        keithley.enable_source()              # Enables the source output

        keithley.measure_resistance()         # Sets up to measure resistance

        keithley.ramp_to_voltage(50)          # Ramps the voltage to 50 V
        print(keithley.resistance)            # Prints the resistance in Ohms

        keithley.shutdown()                   # Ramps the voltage to 0 V
                                              # and disables output

    """

    source_enabled = Instrument.measurement(
        "OUTPUT?",
        """ Reads a boolean value that is True if the source is enabled. """,
        cast=bool
    )

    def extract_value(self, result):
        """ extracts the physical value from a result object returned
            by the instrument """
        m = re.fullmatch('([+\-0-9E\.]+)[A-Z]{4}', result[0])
        if m:
            return float(m.group(1))
        return None

    ###############
    # Current (A) #
    ###############

    current = Instrument.measurement(
        ":MEAS?",
        """ Reads the current in Amps, if configured for this reading.
        """, get_process=extract_value
    )

    current_range = Instrument.control(
        ":SENS:CURR:RANG?", ":SENS:CURR:RANG:AUTO 0;:SENS:CURR:RANG %g",
        """ A floating point property that controls the measurement current
        range in Amps, which can take values between -20 and +20 mA.
        Auto-range is disabled when this property is set. """,
        validator=truncated_range,
        values=[-20e-3, 20e-3]
    )

    current_nplc = Instrument.control(
        ":SENS:CURR:NPLC?", ":SENS:CURR:NPLC %g",
        """ A floating point property that controls the number of power
        line cycles (NPLC) for the DC current measurements, which sets the
        integration period and measurement speed. Takes values from 0.01 to
        10, where 0.1, 1, and 10 are Fast, Medium, and Slow respectively. """,
        values=[0.01, 10]
    )

    source_current_resistance_limit = Instrument.control(
        ":SOUR:CURR:RLIM?", ":SOUR:CURR:RLIM %g",
        """ Boolean property which enables or disables resistance
        current limit """,
        cast=bool
    )

    ###############
    # Voltage (V) #
    ###############

    voltage = Instrument.measurement(
        ":MEAS:VOLT?",
        """ Reads the voltage in Volts, if configured for this reading.
        """, get_process=extract_value
    )

    voltage_range = Instrument.control(
        ":SENS:VOLT:RANG?", ":SENS:VOLT:RANG:AUTO 0;:SENS:VOLT:RANG %g",
        """ A floating point property that controls the measurement voltage
        range in Volts, which can take values from -1000 to 1000 V.
        Auto-range is disabled when this property is set. """,
        validator=truncated_range,
        values=[-1000, 1000]
    )

    voltage_nplc = Instrument.control(
        ":SENS:VOLT:NPLC?", ":SENS:VOLT:NPLC %g",
        """ A floating point property that controls the number of power
        line cycles (NPLC) for the DC voltage measurements, which sets the
        integration period and measurement speed. Takes values from 0.01 to
        10, where 0.1, 1, and 10 are Fast, Medium, and Slow respectively. """
    )

    source_voltage = Instrument.control(
        ":SOUR:VOLT?", ":SOUR:VOLT:LEV %g",
        """ A floating point property that controls the source voltage
        in Volts. """
    )

    source_voltage_range = Instrument.control(
        ":SOUR:VOLT:RANG?", ":SOUR:VOLT:RANG:AUTO 0;:SOUR:VOLT:RANG %g",
        """ A floating point property that controls the source voltage
        range in Volts, which can take values from -1000 to 1000 V.
        Auto-range is disabled when this property is set. """,
        validator=truncated_range,
        values=[-1000, 1000]
    )

    ####################
    # Resistance (Ohm) #
    ####################

    resistance = Instrument.measurement(
        ":READ?",
        """ Reads the resistance in Ohms, if configured for this reading.
        """, get_process=extract_value
    )
    resistance_range = Instrument.control(
        ":SENS:RES:RANG?", ":SENS:RES:RANG:AUTO 0;:SENS:RES:RANG %g",
        """ A floating point property that controls the resistance range
        in Ohms, which can take values from 0 to 100e18 Ohms.
        Auto-range is disabled when this property is set. """,
        validator=truncated_range,
        values=[0, 100e18]
    )
    resistance_nplc = Instrument.control(
        ":SENS:RES:NPLC?", ":SENS:RES:NPLC %g",
        """ A floating point property that controls the number of power line cycles
        (NPLC) for the 2-wire resistance measurements, which sets the
        integration period and measurement speed. Takes values from 0.01
        to 10, where 0.1, 1, and 10 are Fast, Medium, and Slow respectively.
        """
    )

    buffer_points = Instrument.control(
        ":TRAC:POIN?", ":TRAC:POIN %d",
        """ An integer property that controls the number of buffer points. This
        does not represent actual points in the buffer, but the configuration
        value instead. """,
        validator=truncated_range,
        values=[1, 6875000],
        cast=int
    )

    ####################
    # Methods        #
    ####################

    def __init__(self, adapter, **kwargs):
        super(Keithley6517B, self).__init__(
            adapter, "Keithley 6517B Electrometer/High Resistance Meter",
            **kwargs
        )

    def enable_source(self):
        """ Enables the source of current or voltage depending on the
        configuration of the instrument. """
        self.write("OUTPUT ON")

    def disable_source(self):
        """ Disables the source of current or voltage depending on the
        configuration of the instrument. """
        self.write("OUTPUT OFF")

    def measure_resistance(self, nplc=1, resistance=2.1e5, auto_range=True):
        """ Configures the measurement of resistance.

        :param nplc: Number of power line cycles (NPLC) from 0.01 to 10
        :param resistance: Upper limit of resistance in Ohms,
                           from -210 POhms to 210 POhms
        :param auto_range: Enables auto_range if True, else uses the
                           resistance_range attribut
        """
        log.info("%s is measuring resistance.", self.name)
        self.write(":SENS:FUNC 'RES';"
                   ":SENS:RES:NPLC %f;" % nplc)
        if auto_range:
            self.write(":SENS:RES:RANG:AUTO 1;")
        else:
            self.resistance_range = resistance
        self.check_errors()

    def measure_voltage(self, nplc=1, voltage=21.0, auto_range=True):
        """ Configures the measurement of voltage.

        :param nplc: Number of power line cycles (NPLC) from 0.01 to 10
        :param voltage: Upper limit of voltage in Volts, from -1000 V to 1000 V
        :param auto_range: Enables auto_range if True, else uses the
                           voltage_range attribut
        """
        log.info("%s is measuring voltage.", self.name)
        self.write(":SENS:FUNC 'VOLT';"
                   ":SENS:VOLT:NPLC %f;" % nplc)
        if auto_range:
            self.write(":SENS:VOLT:RANG:AUTO 1;")
        else:
            self.voltage_range = voltage
        self.check_errors()

    def measure_current(self, nplc=1, current=1.05e-4, auto_range=True):
        """ Configures the measurement of current.

        :param nplc: Number of power line cycles (NPLC) from 0.01 to 10
        :param current: Upper limit of current in Amps, from -21 mA to 21 mA
        :param auto_range: Enables auto_range if True, else uses the
                           current_range attribut
        """
        log.info("%s is measuring current.", self.name)
        self.write(":SENS:FUNC 'CURR';"
                   ":SENS:CURR:NPLC %f;" % nplc)
        if auto_range:
            self.write(":SENS:CURR:RANG:AUTO 1;")
        else:
            self.current_range = current
        self.check_errors()

    def auto_range_source(self):
        """ Configures the source to use an automatic range.
        """
        self.write(":SOUR:VOLT:RANG:AUTO 1")

    def apply_voltage(self, voltage_range=None):
        """ Configures the instrument to apply a source voltage, and
        uses an auto range unless a voltage range is specified.

        :param voltage_range: A :attr:`~.Keithley6517B.voltage_range` value
                              or None (activates auto range)
        """
        log.info("%s is sourcing voltage.", self.name)
        if voltage_range is None:
            self.auto_range_source()
        else:
            self.source_voltage_range = voltage_range
        self.check_errors()

    @property
    def error(self):
        """ Returns a tuple of an error code and message from a
        single error. """
        err = self.values(":system:error?")
        if len(err) < 2:
            err = self.read()  # Try reading again
        code = err[0]
        message = err[1].replace('"', '')
        return (code, message)

    def check_errors(self):
        """ Logs any system errors reported by the instrument.
        """
        code, message = self.error
        while code != 0:
            t = time.time()
            log.info("Keithley 6517B reported error: %d, %s", code, message)
            code, message = self.error
            if (time.time()-t) > 10:
                log.warning("Timed out for Keithley 6517B error retrieval.")

    def reset(self):
        """ Resets the instrument and clears the queue.  """
        self.write("*RST;:stat:pres;:*CLS;")

    def ramp_to_voltage(self, target_voltage, steps=30, pause=20e-3):
        """ Ramps to a target voltage from the set voltage value over
        a certain number of linear steps, each separated by a pause duration.

        :param target_voltage: A voltage in Volts
        :param steps: An integer number of steps
        :param pause: A pause duration in seconds to wait between steps
        """
        voltages = np.linspace(
            self.source_voltage,
            target_voltage,
            steps
        )
        for voltage in voltages:
            self.source_voltage = voltage
            time.sleep(pause)

    def trigger(self):
        """ Executes a bus trigger, which can be used when
        :meth:`~.trigger_on_bus` is configured.
        """
        return self.write("*TRG")

    def shutdown(self):
        """ Ensures that the current or voltage is turned to zero
        and disables the output. """
        log.info("Shutting down %s.", self.name)
        self.ramp_to_voltage(0.0)
        self.stop_buffer()
        self.disable_source()
<commit_msg>Fix DeprecationWarning in regex string.<commit_after>#
# This file is part of the PyMeasure package.
#
# Copyright (c) 2013-2020 PyMeasure Developers
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#

import logging
import time
import re

import numpy as np

from pymeasure.instruments import Instrument
from pymeasure.instruments.validators import truncated_range
from .buffer import KeithleyBuffer

log = logging.getLogger(__name__)
log.addHandler(logging.NullHandler())

class Keithley6517B(Instrument, KeithleyBuffer):
    """ Represents the Keithely 6517B ElectroMeter and provides a
    high-level interface for interacting with the instrument.

    .. code-block:: python

        keithley = Keithley6517B("GPIB::1")

        keithley.apply_voltage()              # Sets up to source current
        keithley.source_voltage_range = 200   # Sets the source voltage
                                              # range to 200 V
        keithley.source_voltage = 20          # Sets the source voltage to 20 V
        keithley.enable_source()              # Enables the source output

        keithley.measure_resistance()         # Sets up to measure resistance

        keithley.ramp_to_voltage(50)          # Ramps the voltage to 50 V
        print(keithley.resistance)            # Prints the resistance in Ohms

        keithley.shutdown()                   # Ramps the voltage to 0 V
                                              # and disables output

    """

    source_enabled = Instrument.measurement(
        "OUTPUT?",
        """ Reads a boolean value that is True if the source is enabled. """,
        cast=bool
    )

    def extract_value(self, result):
        """ extracts the physical value from a result object returned
            by the instrument """
        m = re.fullmatch(r'([+\-0-9E.]+)[A-Z]{4}', result[0])
        if m:
            return float(m.group(1))
        return None

    ###############
    # Current (A) #
    ###############

    current = Instrument.measurement(
        ":MEAS?",
        """ Reads the current in Amps, if configured for this reading.
        """, get_process=extract_value
    )

    current_range = Instrument.control(
        ":SENS:CURR:RANG?", ":SENS:CURR:RANG:AUTO 0;:SENS:CURR:RANG %g",
        """ A floating point property that controls the measurement current
        range in Amps, which can take values between -20 and +20 mA.
        Auto-range is disabled when this property is set. """,
        validator=truncated_range,
        values=[-20e-3, 20e-3]
    )

    current_nplc = Instrument.control(
        ":SENS:CURR:NPLC?", ":SENS:CURR:NPLC %g",
        """ A floating point property that controls the number of power
        line cycles (NPLC) for the DC current measurements, which sets the
        integration period and measurement speed. Takes values from 0.01 to
        10, where 0.1, 1, and 10 are Fast, Medium, and Slow respectively. """,
        values=[0.01, 10]
    )

    source_current_resistance_limit = Instrument.control(
        ":SOUR:CURR:RLIM?", ":SOUR:CURR:RLIM %g",
        """ Boolean property which enables or disables resistance
        current limit """,
        cast=bool
    )

    ###############
    # Voltage (V) #
    ###############

    voltage = Instrument.measurement(
        ":MEAS:VOLT?",
        """ Reads the voltage in Volts, if configured for this reading.
        """, get_process=extract_value
    )

    voltage_range = Instrument.control(
        ":SENS:VOLT:RANG?", ":SENS:VOLT:RANG:AUTO 0;:SENS:VOLT:RANG %g",
        """ A floating point property that controls the measurement voltage
        range in Volts, which can take values from -1000 to 1000 V.
        Auto-range is disabled when this property is set. """,
        validator=truncated_range,
        values=[-1000, 1000]
    )

    voltage_nplc = Instrument.control(
        ":SENS:VOLT:NPLC?", ":SENS:VOLT:NPLC %g",
        """ A floating point property that controls the number of power
        line cycles (NPLC) for the DC voltage measurements, which sets the
        integration period and measurement speed. Takes values from 0.01 to
        10, where 0.1, 1, and 10 are Fast, Medium, and Slow respectively. """
    )

    source_voltage = Instrument.control(
        ":SOUR:VOLT?", ":SOUR:VOLT:LEV %g",
        """ A floating point property that controls the source voltage
        in Volts. """
    )

    source_voltage_range = Instrument.control(
        ":SOUR:VOLT:RANG?", ":SOUR:VOLT:RANG:AUTO 0;:SOUR:VOLT:RANG %g",
        """ A floating point property that controls the source voltage
        range in Volts, which can take values from -1000 to 1000 V.
        Auto-range is disabled when this property is set. """,
        validator=truncated_range,
        values=[-1000, 1000]
    )

    ####################
    # Resistance (Ohm) #
    ####################

    resistance = Instrument.measurement(
        ":READ?",
        """ Reads the resistance in Ohms, if configured for this reading.
        """, get_process=extract_value
    )
    resistance_range = Instrument.control(
        ":SENS:RES:RANG?", ":SENS:RES:RANG:AUTO 0;:SENS:RES:RANG %g",
        """ A floating point property that controls the resistance range
        in Ohms, which can take values from 0 to 100e18 Ohms.
        Auto-range is disabled when this property is set. """,
        validator=truncated_range,
        values=[0, 100e18]
    )
    resistance_nplc = Instrument.control(
        ":SENS:RES:NPLC?", ":SENS:RES:NPLC %g",
        """ A floating point property that controls the number of power line cycles
        (NPLC) for the 2-wire resistance measurements, which sets the
        integration period and measurement speed. Takes values from 0.01
        to 10, where 0.1, 1, and 10 are Fast, Medium, and Slow respectively.
        """
    )

    buffer_points = Instrument.control(
        ":TRAC:POIN?", ":TRAC:POIN %d",
        """ An integer property that controls the number of buffer points. This
        does not represent actual points in the buffer, but the configuration
        value instead. """,
        validator=truncated_range,
        values=[1, 6875000],
        cast=int
    )

    ####################
    # Methods        #
    ####################

    def __init__(self, adapter, **kwargs):
        super(Keithley6517B, self).__init__(
            adapter, "Keithley 6517B Electrometer/High Resistance Meter",
            **kwargs
        )

    def enable_source(self):
        """ Enables the source of current or voltage depending on the
        configuration of the instrument. """
        self.write("OUTPUT ON")

    def disable_source(self):
        """ Disables the source of current or voltage depending on the
        configuration of the instrument. """
        self.write("OUTPUT OFF")

    def measure_resistance(self, nplc=1, resistance=2.1e5, auto_range=True):
        """ Configures the measurement of resistance.

        :param nplc: Number of power line cycles (NPLC) from 0.01 to 10
        :param resistance: Upper limit of resistance in Ohms,
                           from -210 POhms to 210 POhms
        :param auto_range: Enables auto_range if True, else uses the
                           resistance_range attribut
        """
        log.info("%s is measuring resistance.", self.name)
        self.write(":SENS:FUNC 'RES';"
                   ":SENS:RES:NPLC %f;" % nplc)
        if auto_range:
            self.write(":SENS:RES:RANG:AUTO 1;")
        else:
            self.resistance_range = resistance
        self.check_errors()

    def measure_voltage(self, nplc=1, voltage=21.0, auto_range=True):
        """ Configures the measurement of voltage.

        :param nplc: Number of power line cycles (NPLC) from 0.01 to 10
        :param voltage: Upper limit of voltage in Volts, from -1000 V to 1000 V
        :param auto_range: Enables auto_range if True, else uses the
                           voltage_range attribut
        """
        log.info("%s is measuring voltage.", self.name)
        self.write(":SENS:FUNC 'VOLT';"
                   ":SENS:VOLT:NPLC %f;" % nplc)
        if auto_range:
            self.write(":SENS:VOLT:RANG:AUTO 1;")
        else:
            self.voltage_range = voltage
        self.check_errors()

    def measure_current(self, nplc=1, current=1.05e-4, auto_range=True):
        """ Configures the measurement of current.

        :param nplc: Number of power line cycles (NPLC) from 0.01 to 10
        :param current: Upper limit of current in Amps, from -21 mA to 21 mA
        :param auto_range: Enables auto_range if True, else uses the
                           current_range attribut
        """
        log.info("%s is measuring current.", self.name)
        self.write(":SENS:FUNC 'CURR';"
                   ":SENS:CURR:NPLC %f;" % nplc)
        if auto_range:
            self.write(":SENS:CURR:RANG:AUTO 1;")
        else:
            self.current_range = current
        self.check_errors()

    def auto_range_source(self):
        """ Configures the source to use an automatic range.
        """
        self.write(":SOUR:VOLT:RANG:AUTO 1")

    def apply_voltage(self, voltage_range=None):
        """ Configures the instrument to apply a source voltage, and
        uses an auto range unless a voltage range is specified.

        :param voltage_range: A :attr:`~.Keithley6517B.voltage_range` value
                              or None (activates auto range)
        """
        log.info("%s is sourcing voltage.", self.name)
        if voltage_range is None:
            self.auto_range_source()
        else:
            self.source_voltage_range = voltage_range
        self.check_errors()

    @property
    def error(self):
        """ Returns a tuple of an error code and message from a
        single error. """
        err = self.values(":system:error?")
        if len(err) < 2:
            err = self.read()  # Try reading again
        code = err[0]
        message = err[1].replace('"', '')
        return (code, message)

    def check_errors(self):
        """ Logs any system errors reported by the instrument.
        """
        code, message = self.error
        while code != 0:
            t = time.time()
            log.info("Keithley 6517B reported error: %d, %s", code, message)
            code, message = self.error
            if (time.time()-t) > 10:
                log.warning("Timed out for Keithley 6517B error retrieval.")

    def reset(self):
        """ Resets the instrument and clears the queue.  """
        self.write("*RST;:stat:pres;:*CLS;")

    def ramp_to_voltage(self, target_voltage, steps=30, pause=20e-3):
        """ Ramps to a target voltage from the set voltage value over
        a certain number of linear steps, each separated by a pause duration.

        :param target_voltage: A voltage in Volts
        :param steps: An integer number of steps
        :param pause: A pause duration in seconds to wait between steps
        """
        voltages = np.linspace(
            self.source_voltage,
            target_voltage,
            steps
        )
        for voltage in voltages:
            self.source_voltage = voltage
            time.sleep(pause)

    def trigger(self):
        """ Executes a bus trigger, which can be used when
        :meth:`~.trigger_on_bus` is configured.
        """
        return self.write("*TRG")

    def shutdown(self):
        """ Ensures that the current or voltage is turned to zero
        and disables the output. """
        log.info("Shutting down %s.", self.name)
        self.ramp_to_voltage(0.0)
        self.stop_buffer()
        self.disable_source()
<|endoftext|>


<commit_before>#!/usr/bin/env python
#
# Copyright (C) 2013 Stanislav Golovanov <stgolovanov@gmail.com>
#                    Strahinja Val Markovic  <val@markovic.io>
#
# YouCompleteMe is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# YouCompleteMe is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with YouCompleteMe.  If not, see <http://www.gnu.org/licenses/>.

from completers.threaded_completer import ThreadedCompleter
from completers.cpp.clang_completer import InCFamilyFile
from completers.cpp.flags import Flags
import vim
import vimsupport
import os
import re

USE_WORKING_DIR = vimsupport.GetBoolValue(
  'g:ycm_filepath_completion_use_working_dir' )

class FilenameCompleter( ThreadedCompleter ):
  """
  General completer that provides filename and filepath completions.
  """

  def __init__( self ):
    super( FilenameCompleter, self ).__init__()
    self._flags = Flags()

    self._path_regex = re.compile( """
      # 1 or more 'D:/'-like token or '/' or '~' or './' or '../'
      (?:[A-z]+:/|[/~]|\./|\.+/)+

      # any alphanumeric symbal and space literal
      (?:[ /a-zA-Z0-9()$+_~.\x80-\xff-\[\]]|

      # skip any special symbols
      [^\x20-\x7E]|

      # backslash and 1 char after it. + matches 1 or more of whole group
      \\.)*$
      """, re.X )

    include_regex_common = '^\s*#(?:include|import)\s*(?:"|<)'
    self._include_start_regex = re.compile( include_regex_common + '$' )
    self._include_regex = re.compile( include_regex_common )

  def AtIncludeStatementStart( self, start_column ):
    return ( InCFamilyFile() and
             self._include_start_regex.match(
               vim.current.line[ :start_column ] ) )

  def ShouldUseNowInner( self, start_column ):
    return ( vim.current.line[ start_column - 1 ] == '/' or
             self.AtIncludeStatementStart( start_column ) )

  def SupportedFiletypes( self ):
    return []

  def ComputeCandidates( self, unused_query, start_column ):
    line = vim.current.line[ :start_column ]

    if InCFamilyFile():
      include_match = self._include_regex.search( line )
      if include_match:
        path_dir = line[ include_match.end(): ]
        # We do what GCC does for <> versus "":
        # http://gcc.gnu.org/onlinedocs/cpp/Include-Syntax.html
        include_current_file_dir = '<' not in include_match.group()
        return GenerateCandidatesForPaths(
          self.GetPathsIncludeCase( path_dir, include_current_file_dir ) )

    path_match = self._path_regex.search( line )
    path_dir = os.path.expanduser( path_match.group() ) if path_match else ''

    return GenerateCandidatesForPaths( GetPathsStandardCase( path_dir ) )

  def GetPathsIncludeCase( self, path_dir, include_current_file_dir ):
    paths = []
    include_paths = self._flags.UserIncludePaths( vim.current.buffer.name )

    if include_current_file_dir:
      include_paths.append( os.path.dirname( vim.current.buffer.name ) )

    for include_path in include_paths:
      try:
        relative_paths = os.listdir( os.path.join( include_path, path_dir ) )
      except:
        relative_paths = []

      paths.extend( os.path.join( include_path, relative_path ) for
                    relative_path in relative_paths  )

    return sorted( set( paths ) )

def GetPathsStandardCase( path_dir ):
  if not USE_WORKING_DIR and not path_dir.startswith( '/' ):
    path_dir = os.path.join( os.path.dirname( vim.current.buffer.name ),
                             path_dir )

  try:
    relative_paths = os.listdir( path_dir )
  except:
    relative_paths = []

  return ( os.path.join( path_dir, relative_path )
           for relative_path in relative_paths )

def GenerateCandidatesForPaths( absolute_paths ):
  def GenerateCandidateForPath( absolute_path ):
    is_dir = os.path.isdir( absolute_path )
    return { 'word': os.path.basename( absolute_path ),
              'dup': 1,
              'menu': '[Dir]' if is_dir else '[File]' }

  return [ GenerateCandidateForPath( path ) for path in absolute_paths ]
<commit_msg>Fix bug with [File] being shown instead of [Dir]<commit_after>#!/usr/bin/env python
#
# Copyright (C) 2013 Stanislav Golovanov <stgolovanov@gmail.com>
#                    Strahinja Val Markovic  <val@markovic.io>
#
# YouCompleteMe is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# YouCompleteMe is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with YouCompleteMe.  If not, see <http://www.gnu.org/licenses/>.

from completers.threaded_completer import ThreadedCompleter
from completers.cpp.clang_completer import InCFamilyFile
from completers.cpp.flags import Flags
import vim
import vimsupport
import os
import re

USE_WORKING_DIR = vimsupport.GetBoolValue(
  'g:ycm_filepath_completion_use_working_dir' )

class FilenameCompleter( ThreadedCompleter ):
  """
  General completer that provides filename and filepath completions.
  """

  def __init__( self ):
    super( FilenameCompleter, self ).__init__()
    self._flags = Flags()

    self._path_regex = re.compile( """
      # 1 or more 'D:/'-like token or '/' or '~' or './' or '../'
      (?:[A-z]+:/|[/~]|\./|\.+/)+

      # any alphanumeric symbal and space literal
      (?:[ /a-zA-Z0-9()$+_~.\x80-\xff-\[\]]|

      # skip any special symbols
      [^\x20-\x7E]|

      # backslash and 1 char after it. + matches 1 or more of whole group
      \\.)*$
      """, re.X )

    include_regex_common = '^\s*#(?:include|import)\s*(?:"|<)'
    self._include_start_regex = re.compile( include_regex_common + '$' )
    self._include_regex = re.compile( include_regex_common )

  def AtIncludeStatementStart( self, start_column ):
    return ( InCFamilyFile() and
             self._include_start_regex.match(
               vim.current.line[ :start_column ] ) )

  def ShouldUseNowInner( self, start_column ):
    return ( vim.current.line[ start_column - 1 ] == '/' or
             self.AtIncludeStatementStart( start_column ) )

  def SupportedFiletypes( self ):
    return []

  def ComputeCandidates( self, unused_query, start_column ):
    line = vim.current.line[ :start_column ]

    if InCFamilyFile():
      include_match = self._include_regex.search( line )
      if include_match:
        path_dir = line[ include_match.end(): ]
        # We do what GCC does for <> versus "":
        # http://gcc.gnu.org/onlinedocs/cpp/Include-Syntax.html
        include_current_file_dir = '<' not in include_match.group()
        return GenerateCandidatesForPaths(
          self.GetPathsIncludeCase( path_dir, include_current_file_dir ) )

    path_match = self._path_regex.search( line )
    path_dir = os.path.expanduser( path_match.group() ) if path_match else ''

    return GenerateCandidatesForPaths( GetPathsStandardCase( path_dir ) )

  def GetPathsIncludeCase( self, path_dir, include_current_file_dir ):
    paths = []
    include_paths = self._flags.UserIncludePaths( vim.current.buffer.name )

    if include_current_file_dir:
      include_paths.append( os.path.dirname( vim.current.buffer.name ) )

    for include_path in include_paths:
      try:
        relative_paths = os.listdir( os.path.join( include_path, path_dir ) )
      except:
        relative_paths = []

      paths.extend( os.path.join( include_path, path_dir, relative_path ) for
                    relative_path in relative_paths  )

    return sorted( set( paths ) )

def GetPathsStandardCase( path_dir ):
  if not USE_WORKING_DIR and not path_dir.startswith( '/' ):
    path_dir = os.path.join( os.path.dirname( vim.current.buffer.name ),
                             path_dir )

  try:
    relative_paths = os.listdir( path_dir )
  except:
    relative_paths = []

  return ( os.path.join( path_dir, relative_path )
           for relative_path in relative_paths )

def GenerateCandidatesForPaths( absolute_paths ):
  def GenerateCandidateForPath( absolute_path ):
    is_dir = os.path.isdir( absolute_path )
    return { 'word': os.path.basename( absolute_path ),
              'dup': 1,
              'menu': '[Dir]' if is_dir else '[File]' }

  return [ GenerateCandidateForPath( path ) for path in absolute_paths ]
<|endoftext|>


<commit_before>class Node(object):
    def __init__(self, value):
        pass

    def value(self):
        pass

    def next(self):
        pass

class LinkedList(object):
    def __init__(self, values=[]):
        self.size = 0
        for value in values:
            self.push(value)

    def __len__(self):
        return self.size

    def head(self):
        pass

    def push(self, value):
        node = Node(value)
        if self.head is None:
            self.head = node

        self.size += 1

    def pop(self):
        pass

    def reversed(self):
        pass

class EmptyListException(Exception):
    pass
<commit_msg>Mark instance variables private with leading _<commit_after>class Node(object):
    def __init__(self, value):
        pass

    def value(self):
        pass

    def next(self):
        pass

class LinkedList(object):
    def __init__(self, values=[]):
        self._size = 0
        self._head = None

        for value in values:
            self.push(value)

    def __len__(self):
        return self._size

    def head(self):
        if self._head is None:
            raise EmptyListException("Head is empty")

    def push(self, value):
        node = Node(value)
        if self._head is None:
            self._head = node

        self._size += 1

    def pop(self):
        pass

    def reversed(self):
        pass

class EmptyListException(Exception):
    def __init__(self, message):
        self.message = message
<|endoftext|>


<commit_before>#!/usr/bin/python
#
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import json

import flask
import pytest
from google.cloud.sqlcommenter.flask import get_flask_info

from .app import app

# Following the example provided at
# https://flask.palletsprojects.com/en/1.1.x/testing/#the-testing-skeleton

@pytest.fixture
def client():
    app.config['TESTING'] = True
    with app.test_client() as client:
        yield client

def test_get_flask_info_in_request_context(client):
    expected = {
        'controller': 'flask_info',
        'framework': 'flask:%s' % flask.__version__,
        'route': '/flask-info',
    }
    resp = client.get('/flask-info')
    assert json.loads(resp.data.decode('utf-8')) == expected

def test_get_flask_info_in_404_error_context(client):
    expected = {
        'framework': 'flask:%s' % flask.__version__,
    }
    resp = client.get('/doesnt-exist')
    assert json.loads(resp.data.decode('utf-8')) == expected

def test_get_flask_info_outside_request_context(client):
    assert get_flask_info() == {}
<commit_msg>Check failure case<commit_after>#!/usr/bin/python
#
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import json

import flask
import pytest
from google.cloud.sqlcommenter.flask import get_flask_info

from .app import app

# Following the example provided at
# https://flask.palletsprojects.com/en/1.1.x/testing/#the-testing-skeleton

@pytest.fixture
def client():
    app.config['TESTING'] = True
    with app.test_client() as client:
        yield client

def test_get_flask_info_in_request_context(client):
    expected = {
        'controller': 'flask_info',
        'framework': 'flask:%s' % flask.__version__,
        'route': '/flask-info',
    }
    resp = client.get('/flask-info')
    assert json.loads(resp.data.decode('utf-8')) == {}

def test_get_flask_info_in_404_error_context(client):
    expected = {
        'framework': 'flask:%s' % flask.__version__,
    }
    resp = client.get('/doesnt-exist')
    assert json.loads(resp.data.decode('utf-8')) == expected

def test_get_flask_info_outside_request_context(client):
    assert get_flask_info() == {}
<|endoftext|>


<commit_before>from django.contrib import admin
from django.conf.urls import url, patterns, include
from rest_framework import routers
from concepts.views import ConceptVersionListAllView
from mappings.views import MappingListAllView

admin.autodiscover()

# Routers provide an easy way of automatically determining the URL conf
router = routers.DefaultRouter()
urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'ocl.views.home', name='home'),
    # url(r'^ocl/', include('ocl.foo.urls')),
    url(r'^', include(router.urls)),

    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    url(r'^admin/', include(admin.site.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    url(r'^api-token-auth/$', 'rest_framework.authtoken.views.obtain_auth_token'),

    # Top-level resource endpoints
    url(r'^collections/', include('collection.urls')),
    url(r'^concepts/', ConceptVersionListAllView.as_view(), name='all-concepts'),
    url(r'^orgs/', include('orgs.urls')),
    url(r'^users/', include('users.urls')),
    url(r'^mappings/$', MappingListAllView.as_view(), name='all-mappings'),

    # Shortcuts to endpoints corresponding to the currently logged in user
    url(r'^user/', include('user_urls')),
)

<commit_msg>Replaced missing /sources url<commit_after>from django.contrib import admin
from django.conf.urls import url, patterns, include
from rest_framework import routers
from concepts.views import ConceptVersionListAllView
from mappings.views import MappingListAllView
from sources.views import SourceListView

admin.autodiscover()

# Routers provide an easy way of automatically determining the URL conf
router = routers.DefaultRouter()
urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'ocl.views.home', name='home'),
    # url(r'^ocl/', include('ocl.foo.urls')),
    url(r'^', include(router.urls)),

    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    url(r'^admin/', include(admin.site.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    url(r'^api-token-auth/$', 'rest_framework.authtoken.views.obtain_auth_token'),

    # Top-level resource endpoints
    url(r'^collections/', include('collection.urls')),
    url(r'^concepts/', ConceptVersionListAllView.as_view(), name='all-concepts'),
    url(r'^mappings/$', MappingListAllView.as_view(), name='all-mappings'),
    url(r'^orgs/', include('orgs.urls')),
    url(r'^sources/$', SourceListView.as_view(), name='source-list'),
    url(r'^users/', include('users.urls')),

    # Shortcuts to endpoints corresponding to the currently logged in user
    url(r'^user/', include('user_urls')),
)

<|endoftext|>