<commit_before>#!/usr/bin/python
# Compares two drules files and produces a merged result.
# Also prints differences (missing things in drules1) to stdout.
import sys, re
import copy
import drules_struct_pb2

def read_drules(drules):
  """Parses the structure and extracts elements for lowest and highest zooms
  for each rule."""
  result = {}

  for elem in drules.cont:
    if not elem.element:
      continue
    zooms = [None, None]
    for el in elem.element:
      zoom = el.scale
      if zoom > 0:
        if not zooms[1] or zoom > zooms[1].scale:
          zooms[1] = el
        if not zooms[0] or zoom < zooms[0].scale:
          zooms[0] = el
    if zooms[0]:
      name = str(elem.name)
      if name in result:
        if result[name][0].scale < zooms[0].scale:
          zooms[0] = result[name][0]
        if result[name][1].scale > zooms[1].scale:
          zooms[1] = result[name][1]
      result[name] = zooms
  return result

def zooms_string(z1, z2):
  """Prints 'zoom N' or 'zooms N-M'."""
  if z2 != z1:
    return "zooms {}-{}".format(min(z1, z2), max(z1, z2))
  else:
    return "zoom {}".format(z1)

def create_diff(zooms1, zooms2):
  """Calculates difference between zoom dicts, and returns a tuple:
  (add_zooms_low, add_zooms_high, add_types), for missing zoom levels
  and missing types altogether. Zooms are separate to preserve sorting
  order in elements."""
  add_zooms_low = {}
  add_zooms_high = {}
  seen = set([x for x in zooms2])
  for typ in zooms1:
    if typ in zooms2:
      seen.remove(typ)
      if zooms2[typ][0].scale < zooms1[typ][0].scale:
        print "{}: missing low {}".format(typ, zooms_string(zooms2[typ][0].scale, zooms1[typ][0].scale - 1))
        if not typ in add_zooms_low:
          add_zooms_low[typ] = []
        for z in range(zooms2[typ][0].scale, zooms1[typ][0].scale):
          fix = copy.deepcopy(zooms1[typ][0])
          fix.scale = z
          add_zooms_low[typ].append(fix)
      elif zooms2[typ][0].scale > zooms1[typ][0].scale:
        print "{}: extra low {}".format(typ, zooms_string(zooms1[typ][0].scale, zooms2[typ][0].scale - 1))

      if zooms2[typ][1].scale > zooms1[typ][1].scale:
        print "{}: missing high {}".format(typ, zooms_string(zooms1[typ][1].scale + 1, zooms2[typ][1].scale))
        if not typ in add_zooms_high:
          add_zooms_high[typ] = []
        for z in range(zooms1[typ][1].scale, zooms2[typ][1].scale):
          fix = copy.deepcopy(zooms1[typ][1])
          fix.scale = z + 1
          add_zooms_high[typ].append(fix)
      elif zooms2[typ][1].scale < zooms1[typ][1].scale:
        print "{}: extra high {}".format(typ, zooms_string(zooms2[typ][1].scale + 1, zooms1[typ][1].scale))
    else:
      print "{}: not found in the alternative style; {}".format(typ, zooms_string(zooms1[typ][0].scale, zooms1[typ][1].scale))

  add_types = []
  for typ in seen:
    print "{}: missing completely; {}".format(typ, zooms_string(zooms2[typ][0].scale, zooms2[typ][1].scale))
    cont = drules_struct_pb2.ClassifElementProto()
    cont.name = typ
    for z in range(zooms2[typ][0].scale, zooms2[typ][1].scale):
      fix = copy.deepcopy(zooms2[typ][0])
      fix.scale = z
      cont.element.extend([fix])
    add_types.append(cont)

  return (add_zooms_low, add_zooms_high, add_types)

def apply_diff(drules, diff):
  result = drules_struct_pb2.ContainerProto()
  for rule in drules.cont:
    typ = str(rule.name)
    fix = drules_struct_pb2.ClassifElementProto()
    fix.name = typ
    if typ in diff[0]:
      fix.element.extend(diff[0][typ])
    if rule.element:
      fix.element.extend([el for el in rule.element])
    if typ in diff[1]:
      fix.element.extend(diff[1][typ])
    result.cont.extend([fix])
  result.cont.extend(diff[2])
  return result

if len(sys.argv) <= 3:
  print 'Usage: {} <drules1.bin> <drules2.bin> <drules_out.bin> [drules_out.txt]'.format(sys.argv[0])
  sys.exit(1)

drules1 = drules_struct_pb2.ContainerProto()
drules1.ParseFromString(open(sys.argv[1]).read())
drules2 = drules_struct_pb2.ContainerProto()
drules2.ParseFromString(open(sys.argv[2]).read())

zooms1 = read_drules(drules1)
zooms2 = read_drules(drules2)
diff = create_diff(zooms1, zooms2)
merged = apply_diff(drules1, diff)

with open(sys.argv[3], 'wb') as f:
  f.write(merged.SerializeToString())
if len(sys.argv) > 4:
  with open(sys.argv[4], 'wb') as f:
    f.write(unicode(merged))
<commit_msg>[styles] drules_merge.py review fixes<commit_after>#!/usr/bin/python
# Compares two drules files and produces a merged result.
# Also prints differences (missing things in drules1) to stdout.
import sys, re
import copy
import drules_struct_pb2

def read_drules(drules):
  """Parses the structure and extracts elements for lowest and highest zooms
  for each rule."""
  result = {}

  for rule in drules.cont:
    zooms = [None, None]
    for elem in rule.element:
      zoom = rule.scale
      if zoom >= 0:
        if zooms[1] is None or zoom > zooms[1].scale:
          zooms[1] = elem
        if zooms[0] is None or zoom < zooms[0].scale:
          zooms[0] = elem
    if zooms[0] is not None:
      name = str(rule.name)
      if name in result:
        if result[name][0].scale < zooms[0].scale:
          zooms[0] = result[name][0]
        if result[name][1].scale > zooms[1].scale:
          zooms[1] = result[name][1]
      result[name] = zooms
  return result

def zooms_string(z1, z2):
  """Prints 'zoom N' or 'zooms N-M'."""
  if z2 != z1:
    return "zooms {}-{}".format(min(z1, z2), max(z1, z2))
  else:
    return "zoom {}".format(z1)

def create_diff(zooms1, zooms2):
  """Calculates difference between zoom dicts, and returns a tuple:
  (add_zooms_low, add_zooms_high, add_types), for missing zoom levels
  and missing types altogether. Zooms are separate to preserve sorting
  order in elements."""
  add_elements_low = {}
  add_elements_high = {}
  seen = set([x for x in zooms2])
  for typ in zooms1:
    if typ not in zooms2:
      print "{}: not found in the alternative style; {}".format(typ, zooms_string(zooms1[typ][0].scale, zooms1[typ][1].scale))
    else:
      seen.remove(typ)
      if zooms2[typ][0].scale < zooms1[typ][0].scale:
        print "{}: missing low {}".format(typ, zooms_string(zooms2[typ][0].scale, zooms1[typ][0].scale - 1))
        if not typ in add_elements_low:
          add_elements_low[typ] = []
        for z in range(zooms2[typ][0].scale, zooms1[typ][0].scale):
          fix = copy.deepcopy(zooms1[typ][0])
          fix.scale = z
          add_elements_low[typ].append(fix)
      elif zooms2[typ][0].scale > zooms1[typ][0].scale:
        print "{}: extra low {}".format(typ, zooms_string(zooms1[typ][0].scale, zooms2[typ][0].scale - 1))

      if zooms2[typ][1].scale > zooms1[typ][1].scale:
        print "{}: missing high {}".format(typ, zooms_string(zooms1[typ][1].scale + 1, zooms2[typ][1].scale))
        if not typ in add_elements_high:
          add_elements_high[typ] = []
        for z in range(zooms1[typ][1].scale, zooms2[typ][1].scale):
          fix = copy.deepcopy(zooms1[typ][1])
          fix.scale = z + 1
          add_elements_high[typ].append(fix)
      elif zooms2[typ][1].scale < zooms1[typ][1].scale:
        print "{}: extra high {}".format(typ, zooms_string(zooms2[typ][1].scale + 1, zooms1[typ][1].scale))

  add_types = []
  for typ in seen:
    print "{}: missing completely; {}".format(typ, zooms_string(zooms2[typ][0].scale, zooms2[typ][1].scale))
    cont = drules_struct_pb2.ClassifElementProto()
    cont.name = typ
    for z in range(zooms2[typ][0].scale, zooms2[typ][1].scale):
      fix = copy.deepcopy(zooms2[typ][0])
      fix.scale = z
      cont.element.extend([fix])
    add_types.append(cont)

  return (add_elements_low, add_elements_high, add_types)

def apply_diff(drules, diff):
  """Applies diff tuple (from create_diff) to a drules set."""
  result = drules_struct_pb2.ContainerProto()
  for rule in drules.cont:
    typ = str(rule.name)
    fix = drules_struct_pb2.ClassifElementProto()
    fix.name = typ
    if typ in diff[0]:
      fix.element.extend(diff[0][typ])
    if rule.element:
      fix.element.extend([el for el in rule.element])
    if typ in diff[1]:
      fix.element.extend(diff[1][typ])
    result.cont.extend([fix])
  result.cont.extend(diff[2])
  return result

if __name__ == '__main__':
  if len(sys.argv) <= 3:
    print 'Usage: {} <drules1.bin> <drules2.bin> <drules_out.bin> [drules_out.txt]'.format(sys.argv[0])
    sys.exit(1)

  drules1 = drules_struct_pb2.ContainerProto()
  drules1.ParseFromString(open(sys.argv[1]).read())
  drules2 = drules_struct_pb2.ContainerProto()
  drules2.ParseFromString(open(sys.argv[2]).read())

  zooms1 = read_drules(drules1)
  zooms2 = read_drules(drules2)
  diff = create_diff(zooms1, zooms2)
  merged = apply_diff(drules1, diff)

  with open(sys.argv[3], 'wb') as f:
    f.write(merged.SerializeToString())
  if len(sys.argv) > 4:
    with open(sys.argv[4], 'wb') as f:
      f.write(unicode(merged))
<|endoftext|>


<commit_before>from QLearner import QLearningAlgorithm
from AngryBirds import AngryBirdsGame
import math
from abAPI import *
from util import *
from GameAgent import angryAgent
from matplotlib import pyplot as plt
import numpy as np
import matplotlib
from sparseLearnerRLSVI import RLSVI_wrapper as RLSVI
import pickle

matplotlib.use('TkAgg')

def evaluator(rlAlgorithm,featureExtractor,nameAlg,nameFeat,multiple = 1.0,numTrials=50, epsilon = 0.3, sigma = 500):
    ab = AngryBirdsMDP()
    trial = 0
    levelsPassed=[]
    totalRewards =[]
    name = nameAlg+'_'+nameFeat+'_'+str(64*multiple)

    agent = angryAgent()

    rl = rlAlgorithm(actions=lambda x: agent.getAngryBirdsActions(x,multiple),featureExtractor=featureExtractor, epsilon = epsilon)

    if nameAlg == 'Q':
        while trial<numTrials:
            print(trial)
            rl.explorationProb = epsilon
            simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
            rl.explorationProb = 0.0
            outcome = simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
            levelsPassed = levelsPassed + outcome['levelsPassed']
            totalRewards = totalRewards + outcome['totalRewards']
            print(totalRewards)
            trial +=1

    elif nameAlg == 'LSVI':
        while trial<numTrials:
            try:
                print (trial)
                rl.makeLSVI(epsilon)
                simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
                rl.makeLSVI(0.0)
                outcome = simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
                levelsPassed = levelsPassed + outcome['levelsPassed']
                totalRewards = totalRewards + outcome['totalRewards']
                trial +=1
            except AssertionError:
                break
    elif nameAlg == 'RLSVI':
        while trial<numTrials:
            try:
                print (trial)
                rl.makeRLSVI()
                simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
                rl.makeLSVI(0.0)
                outcome = simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
                levelsPassed = levelsPassed + outcome['levelsPassed']
                totalRewards = totalRewards + outcome['totalRewards']
                trial +=1
            except AssertionError:
                break

        while trial<numTrials:
            try:
                print (trial)
                rl.rlsvi.sigma = sigma
                simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
                rl.rlsvi.sigma = 1.0
                outcome = simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
                levelsPassed = levelsPassed + outcome['levelsPassed']
                totalRewards = totalRewards + outcome['totalRewards']
                trial +=1
            except AssertionError:
                break

    cumlevelsPassed = np.cumsum(levelsPassed)/range(1,len(levelsPassed)+1)
    cumtotalRewards = np.cumsum(totalRewards)/range(1,len(totalRewards)+1)

    with open('../results/levelsPassed_'+name,'wb') as file:
        pickle.dump(levelsPassed,file)
    with open('../results/cumlevelsPassed_'+name,'wb') as file:
        pickle.dump(cumlevelsPassed,file)
    with open('../results/totalRewards_'+name,'wb') as file:
        pickle.dump(totalRewards,file)
    with open('../results/cumtotalRewards_'+name,'wb') as file:
        pickle.dump(cumtotalRewards,file)

    print('Max Total Rewards _'+name,max(totalRewards))

    trials = range(1,len(cumlevelsPassed)+1)

    plt.figure()

    plt.plot(trials,cumlevelsPassed,lw=2,color='blue')
    plt.scatter(trials,cumlevelsPassed)
    plt.xlabel('Number of trials',fontsize='large')
    plt.ylabel('Number of levels passed',fontsize='large')
    plt.title('Rewards per trials', fontsize=20)
    maxLevel=0
    for i in range(len(cumlevelsPassed)):
        if levelsPassed[i]>maxLevel:
            maxLevel=levelsPassed[i]
            plt.axvline(i+1,color='r', linestyle='--')
    plt.savefig('../plots/levelsPassed__'+name+'.png')

    plt.figure()
    plt.plot(trials,cumtotalRewards,lw=2,color='green')
    plt.scatter(trials,cumtotalRewards)
    plt.xlabel('Number of trials',fontsize='large')
    plt.ylabel('Number of total rewards',fontsize='large')
    plt.title('Rewards per trials', fontsize=20)
    maxLevel=0
    for i in range(len(cumlevelsPassed)):
        if levelsPassed[i]>maxLevel:
            maxLevel=levelsPassed[i]
            plt.axvline(i+1,color='r', linestyle='--')
    plt.savefig('../plots/totalRewards_'+name+'.png')

def level_evaluator(level,rlAlgorithm,featureExtractor,nameAlg,nameFeat,numFeat = 64,numTrials=50, explorationProb = 0.3, sigma = 500):

    ab = AngryBirdsMDP(level = level)

    rl = rlAlgorithm(actions=agent.getAngryBirdsActions,featureExtractor=featureExtractor,discount=ab.discount(),\
                            explorationProb=explorationProb)
    trainingOutcomes = simulate(ab,rl,numTrials=numTrials, maxIterations=1000, verbose=False, show=False)

    explorationProb = 0.0
    if nameAlg =='Q':
        rl.setExplorationProb(explorationProb)
    elif nameAlg=='LSVI':
        rl.rlsvi.epsilon = explorationProb
    else:
        rl.rlsvi.sigma = 1.0
    testOutcomes = simulate(ab,rl,numTrials=5,verbose = False, show=False)

    print(trainingOutcomes)
    print(testOutcomes)

    totalRewards = trainingOutcomes['totalRewards']
    trials = range(1,numTrials+1)

    plt.figure()
    plt.plot(trials,totalRewards,lw=2,color='green')
    plt.scatter(trials,totalRewards)
    plt.xlabel('Number of trials',fontsize='large')
    plt.ylabel('Number of total rewards for level 3',fontsize='large')
    plt.title('Rewards per trials', fontsize=20)
    plt.savefig('totalRewardsL3.png')

if __name__ == '__main__':

    agent = angryAgent()
    # evaluator(QLearningAlgorithm,agent.PPFeatureExtractor,'Q','PP',multiple = 1.0,numTrials=50, epsilon = 0.3, sigma = 500)
    # evaluator(QLearningAlgorithm,agent.NPPFeatureExtractor,'Q','NPP',multiple = 1.0,numTrials=50, epsilon = 0.3, sigma = 500)
    evaluator(QLearningAlgorithm,agent.NPPOFeatureExtractor,'Q','NPPO',multiple = 1.0,numTrials=50, epsilon = 0.3, sigma = 500)
    # evaluator(QLearningAlgorithm,agent.NPPSFeatureExtractor,'Q','NPPO',multiple = 1.0,numTrials=50, epsilon = 0.3, sigma = 500)
    # evaluator(RLSVI,agent.featureExtractorXYaction,'RLSVI','PP',numFeat = 1.0,numTrials=50, epsilon = 0.0, sigma = 500)
    # evaluator(RLSVI,agent.nestedGridFeatureExtractor,'RLSVI','NPP',numFeat = 1.0,numTrials=50, epsilon = 0.0, sigma = 500)
    # evaluator(RLSVI,agent.custom2FeatureExtractor,'RLSVI','NPPO',numFeat = 1.0,numTrials=50, epsilon = 0.0, sigma = 500)
    # evaluator(RLSVI,agent.featureExtractorXYaction,'LSVI','PP',numFeat = 1.0,numTrials=50, epsilon = 0.3, sigma = 500)
    # evaluator(RLSVI,agent.nestedGridFeatureExtractor,'LSVI','NPP',numFeat = 1.0,numTrials=50, epsilon = 0.3, sigma = 500)
    # evaluator(RLSVI,agent.custom2FeatureExtractor,'LSVI','NPPO',numFeat = 1.0,numTrials=50, epsilon = 0.3, sigma = 500)

#
# ############################################# Evaluation of Level 5
#     ab = AngryBirdsMDP(level = 5)
#     explorationProb = 0.3
#     numTrials = 50
#     agent = angryAgent()
#
#     rl = QLearningAlgorithm(actions=agent.getAngryBirdsActions,featureExtractor=featureExtractor,discount=ab.discount(),\
#                             explorationProb=explorationProb)
#     trainingOutcomes = simulate(ab,rl,numTrials=numTrials, maxIterations=1000, verbose=False, show=False)
#
#     explorationProb = 0
#     agent = angryAgent()
#     rl.setExplorationProb(explorationProb)
#     testOutcomes = simulate(ab,rl,numTrials=5,verbose = False, show=False)
#
#     print(trainingOutcomes)
#     print(testOutcomes)
#     totalRewards = trainingOutcomes['totalRewards']
#     trials = range(1,numTrials+1)
#
#
#     plt.figure()
#     plt.plot(trials,totalRewards,lw=2,color='green')
#     plt.scatter(trials,totalRewards)
#     plt.xlabel('Number of trials',fontsize='large')
#     plt.ylabel('Number of total rewards for level 5',fontsize='large')
#     plt.title('Rewards per trials', fontsize=20)
#     plt.savefig('totalRewardsL5.png')
#
# ############################################# Evaluation of Level 5 while training in 3
#     ab = AngryBirdsMDP(level = 7)
#     explorationProb = 0.3
#     numTrials = 50
#     agent = angryAgent()
#
#     rl = QLearningAlgorithm(actions=agent.getAngryBirdsActions,featureExtractor=featureExtractor,discount=ab.discount(),\
#                             explorationProb=explorationProb)
#     trainingOutcomes = simulate(ab,rl,numTrials=numTrials, maxIterations=1000, verbose=False, show=False)
#
#     explorationProb = 0
#     ab = AngryBirdsMDP(level = 7)
#     agent = angryAgent()
#     rl.setExplorationProb(explorationProb)
#     testOutcomes = simulate(ab,rl,numTrials=5,verbose = False  , show=False)
#
#     print(trainingOutcomes)
#     print(testOutcomes)
#     totalRewards = trainingOutcomes['totalRewards']
#     trials = range(1,numTrials+1)
#
#
#     plt.figure()
#     plt.plot(trials,totalRewards,lw=2,color='green')
#     plt.scatter(trials,totalRewards)
#     plt.xlabel('Number of trials',fontsize='large')
#     plt.ylabel('Number of total rewards for level 7',fontsize='large')
#     plt.title('Rewards per trials', fontsize=20)
#     plt.savefig('totalRewardsL7.png')
#
<commit_msg>Changes<commit_after>from QLearner import QLearningAlgorithm
from AngryBirds import AngryBirdsGame
import math
from abAPI import *
from util import *
from GameAgent import angryAgent
from matplotlib import pyplot as plt
import numpy as np
import matplotlib
from sparseLearnerRLSVI import RLSVI_wrapper as RLSVI
import pickle

matplotlib.use('TkAgg')

def evaluator(rlAlgorithm,featureExtractor,nameAlg,nameFeat,multiple = 1.0,numTrials=50, epsilon = 0.3, sigma = 500):
    ab = AngryBirdsMDP()
    trial = 0
    levelsPassed=[]
    totalRewards =[]
    name = nameAlg+'_'+nameFeat+'_'+str(64*multiple)

    agent = angryAgent()

    rl = rlAlgorithm(actions=lambda x: agent.getAngryBirdsActions(x,multiple),featureExtractor=featureExtractor, epsilon = epsilon)

    if nameAlg == 'Q':
        while trial<numTrials:
            print(trial)
            rl.explorationProb = epsilon
            simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
            rl.explorationProb = 0.0
            outcome = simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
            levelsPassed = levelsPassed + outcome['levelsPassed']
            totalRewards = totalRewards + outcome['totalRewards']
            print(totalRewards)
            trial +=1

    elif nameAlg == 'LSVI':
        while trial<numTrials:
            try:
                print (trial)
                rl.makeLSVI(epsilon)
                simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
                rl.makeLSVI(0.0)
                outcome = simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
                levelsPassed = levelsPassed + outcome['levelsPassed']
                totalRewards = totalRewards + outcome['totalRewards']
                trial +=1
            except AssertionError:
                break
    elif nameAlg == 'RLSVI':
        while trial<numTrials:
            try:
                print (trial)
                rl.makeRLSVI()
                simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
                rl.makeLSVI(0.0)
                outcome = simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
                levelsPassed = levelsPassed + outcome['levelsPassed']
                totalRewards = totalRewards + outcome['totalRewards']
                trial +=1
            except AssertionError:
                break

        while trial<numTrials:
            try:
                print (trial)
                rl.rlsvi.sigma = sigma
                simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
                rl.rlsvi.sigma = 1.0
                outcome = simulate(ab,rl,numTrials=1, maxIterations=1000, verbose=False, show=False)
                levelsPassed = levelsPassed + outcome['levelsPassed']
                totalRewards = totalRewards + outcome['totalRewards']
                trial +=1
            except AssertionError:
                break

    cumlevelsPassed = np.cumsum(levelsPassed)/range(1,len(levelsPassed)+1)
    cumtotalRewards = np.cumsum(totalRewards)/range(1,len(totalRewards)+1)

    with open('../results/levelsPassed_'+name,'wb') as file:
        pickle.dump(levelsPassed,file)
    with open('../results/cumlevelsPassed_'+name,'wb') as file:
        pickle.dump(cumlevelsPassed,file)
    with open('../results/totalRewards_'+name,'wb') as file:
        pickle.dump(totalRewards,file)
    with open('../results/cumtotalRewards_'+name,'wb') as file:
        pickle.dump(cumtotalRewards,file)

    print('Max Total Rewards _'+name,max(totalRewards))

    trials = range(1,len(cumlevelsPassed)+1)

    plt.figure()

    plt.plot(trials,cumlevelsPassed,lw=2,color='blue')
    plt.scatter(trials,cumlevelsPassed)
    plt.xlabel('Number of trials',fontsize='large')
    plt.ylabel('Number of levels passed',fontsize='large')
    plt.title('Rewards per trials', fontsize=20)
    maxLevel=0
    for i in range(len(cumlevelsPassed)):
        if levelsPassed[i]>maxLevel:
            maxLevel=levelsPassed[i]
            plt.axvline(i+1,color='r', linestyle='--')
    plt.savefig('../plots/levelsPassed__'+name+'.png')

    plt.figure()
    plt.plot(trials,cumtotalRewards,lw=2,color='green')
    plt.scatter(trials,cumtotalRewards)
    plt.xlabel('Number of trials',fontsize='large')
    plt.ylabel('Number of total rewards',fontsize='large')
    plt.title('Rewards per trials', fontsize=20)
    maxLevel=0
    for i in range(len(cumlevelsPassed)):
        if levelsPassed[i]>maxLevel:
            maxLevel=levelsPassed[i]
            plt.axvline(i+1,color='r', linestyle='--')
    plt.savefig('../plots/totalRewards_'+name+'.png')

def level_evaluator(level,rlAlgorithm,featureExtractor,nameAlg,nameFeat,numFeat = 64,numTrials=50, explorationProb = 0.3, sigma = 500):

    ab = AngryBirdsMDP(level = level)

    rl = rlAlgorithm(actions=agent.getAngryBirdsActions,featureExtractor=featureExtractor,discount=ab.discount(),\
                            explorationProb=explorationProb)
    trainingOutcomes = simulate(ab,rl,numTrials=numTrials, maxIterations=1000, verbose=False, show=False)

    explorationProb = 0.0
    if nameAlg =='Q':
        rl.setExplorationProb(explorationProb)
    elif nameAlg=='LSVI':
        rl.rlsvi.epsilon = explorationProb
    else:
        rl.rlsvi.sigma = 1.0
    testOutcomes = simulate(ab,rl,numTrials=5,verbose = False, show=False)

    print(trainingOutcomes)
    print(testOutcomes)

    totalRewards = trainingOutcomes['totalRewards']
    trials = range(1,numTrials+1)

    plt.figure()
    plt.plot(trials,totalRewards,lw=2,color='green')
    plt.scatter(trials,totalRewards)
    plt.xlabel('Number of trials',fontsize='large')
    plt.ylabel('Number of total rewards for level 3',fontsize='large')
    plt.title('Rewards per trials', fontsize=20)
    plt.savefig('totalRewardsL3.png')

if __name__ == '__main__':

    agent = angryAgent()
    # evaluator(QLearningAlgorithm,agent.PPFeatureExtractor,'Q','PP',multiple = 1.0,numTrials=50, epsilon = 0.3, sigma = 500)
    # evaluator(QLearningAlgorithm,agent.NPPFeatureExtractor,'Q','NPP',multiple = 1.0,numTrials=50, epsilon = 0.3, sigma = 500)
    # evaluator(QLearningAlgorithm,agent.NPPOFeatureExtractor,'Q','NPPO',multiple = 1.0,numTrials=50, epsilon = 0.3, sigma = 500)
    # evaluator(QLearningAlgorithm,agent.NPPSFeatureExtractor,'Q','NPPO',multiple = 1.0,numTrials=50, epsilon = 0.3, sigma = 500)
    # evaluator(RLSVI,agent.featureExtractorXYaction,'RLSVI','PP',numFeat = 1.0,numTrials=50, epsilon = 0.0, sigma = 500)
    # evaluator(RLSVI,agent.nestedGridFeatureExtractor,'RLSVI','NPP',numFeat = 1.0,numTrials=50, epsilon = 0.0, sigma = 500)
    # evaluator(RLSVI,agent.custom2FeatureExtractor,'RLSVI','NPPO',numFeat = 1.0,numTrials=50, epsilon = 0.0, sigma = 500)
    # evaluator(RLSVI,agent.featureExtractorXYaction,'LSVI','PP',numFeat = 1.0,numTrials=50, epsilon = 0.3, sigma = 500)
    # evaluator(RLSVI,agent.nestedGridFeatureExtractor,'LSVI','NPP',numFeat = 1.0,numTrials=50, epsilon = 0.3, sigma = 500)
    # evaluator(RLSVI,agent.custom2FeatureExtractor,'LSVI','NPPO',numFeat = 1.0,numTrials=50, epsilon = 0.3, sigma = 500)

#
# ############################################# Evaluation of Level 5
#     ab = AngryBirdsMDP(level = 5)
#     explorationProb = 0.3
#     numTrials = 50
#     agent = angryAgent()
#
#     rl = QLearningAlgorithm(actions=agent.getAngryBirdsActions,featureExtractor=featureExtractor,discount=ab.discount(),\
#                             explorationProb=explorationProb)
#     trainingOutcomes = simulate(ab,rl,numTrials=numTrials, maxIterations=1000, verbose=False, show=False)
#
#     explorationProb = 0
#     agent = angryAgent()
#     rl.setExplorationProb(explorationProb)
#     testOutcomes = simulate(ab,rl,numTrials=5,verbose = False, show=False)
#
#     print(trainingOutcomes)
#     print(testOutcomes)
#     totalRewards = trainingOutcomes['totalRewards']
#     trials = range(1,numTrials+1)
#
#
#     plt.figure()
#     plt.plot(trials,totalRewards,lw=2,color='green')
#     plt.scatter(trials,totalRewards)
#     plt.xlabel('Number of trials',fontsize='large')
#     plt.ylabel('Number of total rewards for level 5',fontsize='large')
#     plt.title('Rewards per trials', fontsize=20)
#     plt.savefig('totalRewardsL5.png')
#
# ############################################# Evaluation of Level 5 while training in 3
#     ab = AngryBirdsMDP(level = 7)
#     explorationProb = 0.3
#     numTrials = 50
#     agent = angryAgent()
#
#     rl = QLearningAlgorithm(actions=agent.getAngryBirdsActions,featureExtractor=featureExtractor,discount=ab.discount(),\
#                             explorationProb=explorationProb)
#     trainingOutcomes = simulate(ab,rl,numTrials=numTrials, maxIterations=1000, verbose=False, show=False)
#
#     explorationProb = 0
#     ab = AngryBirdsMDP(level = 7)
#     agent = angryAgent()
#     rl.setExplorationProb(explorationProb)
#     testOutcomes = simulate(ab,rl,numTrials=5,verbose = False  , show=False)
#
#     print(trainingOutcomes)
#     print(testOutcomes)
#     totalRewards = trainingOutcomes['totalRewards']
#     trials = range(1,numTrials+1)
#
#
#     plt.figure()
#     plt.plot(trials,totalRewards,lw=2,color='green')
#     plt.scatter(trials,totalRewards)
#     plt.xlabel('Number of trials',fontsize='large')
#     plt.ylabel('Number of total rewards for level 7',fontsize='large')
#     plt.title('Rewards per trials', fontsize=20)
#     plt.savefig('totalRewardsL7.png')
#
<|endoftext|>


<commit_before>#
# face_track.py -  Registery and tracking of faces
# Copyright (C) 2014  Hanson Robotics
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

from owyl import blackboard
import rospy
from pi_face_tracker.msg import FaceEvent

# A registery of all the faces currently visible.
# Copies face data to owyl blackboard.
class FaceTrack:

	def __init__(self, owyl_bboard):

		print("Starting Face Tracker")
		self.blackboard = owyl_bboard
		self.visible_faces = []

		# pi_vision topics and events
		self.TOPIC_FACE_EVENT = "face_event"
		self.EVENT_NEW_FACE = "new_face"
		self.EVENT_LOST_FACE = "lost_face"

		# Face appearance/disappearance from pi_vision
		rospy.Subscriber(self.TOPIC_FACE_EVENT, FaceEvent, self.face_event_cb)

		# Face location information from pi_vision

	def face_event_cb(self, data):
		self.blackboard["is_interruption"] = True
		if data.face_event == self.EVENT_NEW_FACE:
			self.blackboard["new_face"] = str(data.face_id)
			self.blackboard["background_face_targets"].append(self.blackboard["new_face"])
			print "New face added to visibile faces: " + \
				str(self.blackboard["background_face_targets"])

		elif data.face_event == self.EVENT_LOST_FACE:
			if data.face_id in self.blackboard["background_face_targets"]:
				self.blackboard["lost_face"] = str(data.face_id)
				self.blackboard["background_face_targets"].remove(self.blackboard["lost_face"])
				# If the robot lost the new face during the initial
				# interaction, reset new_face variable
				if self.blackboard["new_face"] == self.blackboard["lost_face"]:
					self.blackboard["new_face"] = ""

				print "Lost face; visibile faces now: " + \
					str(self.blackboard["background_face_targets"])
<commit_msg>Minor code cleanup<commit_after>#
# face_track.py -  Registery and tracking of faces
# Copyright (C) 2014  Hanson Robotics
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

from owyl import blackboard
import rospy
from pi_face_tracker.msg import FaceEvent, Faces

# A registery of all the faces currently visible.
# Copies face data to owyl blackboard.
class FaceTrack:

	def __init__(self, owyl_bboard):

		print("Starting Face Tracker")
		self.blackboard = owyl_bboard
		self.visible_faces = []

		# pi_vision topics and events
		self.TOPIC_FACE_EVENT = "face_event"
		self.EVENT_NEW_FACE = "new_face"
		self.EVENT_LOST_FACE = "lost_face"

		self.TOPIC_FACE_LOCATIONS = "face_locations"

		# Face appearance/disappearance from pi_vision
		rospy.Subscriber(self.TOPIC_FACE_EVENT, FaceEvent, self.face_event_cb)

		# Face location information from pi_vision
		rospy.Subscriber(self.TOPIC_FACE_LOCATIONS, Faces, self.face_loc_cb)

	def face_event_cb(self, data):
		self.blackboard["is_interruption"] = True
		if data.face_event == self.EVENT_NEW_FACE:
			str_id = str(data.face_id)
			self.blackboard["new_face"] = str_id
			self.blackboard["background_face_targets"].append(str_id)
			print "New face added to visibile faces: " + \
				str(self.blackboard["background_face_targets"])

		elif data.face_event == self.EVENT_LOST_FACE:
			str_id = str(data.face_id)
			if str_id in self.blackboard["background_face_targets"]:
				self.blackboard["lost_face"] = str_id
				self.blackboard["background_face_targets"].remove(str_id)
				# If the robot lost the new face during the initial
				# interaction, reset new_face variable
				if self.blackboard["new_face"] == str_id :
					self.blackboard["new_face"] = ""

				print "Lost face; visibile faces now: " + \
					str(self.blackboard["background_face_targets"])

	def face_loc_cb(self, data):
		# print("duude ola:" + str(data))
		print("")
<|endoftext|>


<commit_before>"""
Copyright: (c) 2012 Artem Nezvigin <artem@artnez.com>
License: MIT, see LICENSE for details
"""

import os
import re
import sqlite3
import atexit
import string # pylint:disable=W0402
import logging
from threading import current_thread
from tempfile import gettempdir
from contextlib import closing
from glob import glob
from uuid import uuid4, uuid5
from hashlib import sha1
from random import random, shuffle
from time import time
from natsort import natsort
from functools import wraps
from faceoff.debug import debug

_curdir = os.path.dirname(__file__)
_schema = os.path.join(_curdir, 'schema')
_global_factory = None

def init_app(app):
    """
    Configures the provided app's database connection layer. Attaches a `db`
    property to the app object that will act as a database connection factory
    for the application's threads and subprocesses to use.
    """
    db_path = app.config['DB_PATH']
    if not db_path:
        db_path = make_temp_db()
    elif not os.path.exists(db_path):
        db_path = make_new_db(db_path)
    app.db = Factory(db_path)
    set_global_factory(app.db)

def make_temp_db():
    """
    Creates a temporary database file and deletes when the process is ends.
    Returns the path to the temporary file.
    """
    db_link = os.path.expanduser(os.path.join('~', '.faceoff.tmp.db'))
    if not os.path.exists(db_link):
        pid, tid = os.getpid(), current_thread().ident
        db_path = os.path.join(gettempdir(), 'faceoff%s%s.tmp.db' % (pid, tid))
        build_schema(db_path, _schema)
        os.symlink(db_path, db_link)
        atexit.register(clean_temp_db(db_path, db_link))
        logger().info('created tmp db at %s linked by %s' % (db_path, db_link))
    return db_link

def clean_temp_db(db_path, db_link):
    """
    Returns a closed function that deletes the temporary database file at
    the given path.
    """
    def cleaner():
        logger().info('cleanup temp db file %s' % db_path)
        os.remove(db_path)
        logger().info('cleanup temp db link %s' % db_link)
        os.remove(db_link)
    return cleaner

def make_new_db(path):
    """
    Creates a new database at the given location.
    """
    build_schema(path, _schema)
    logger().info('created fresh db %s' % path)
    return path

def build_schema(db_path, schema_path):
    """
    Rebuilds the database using the given schema directory.
    """
    with closing(sqlite3.connect(db_path)) as conn:
        conn.executescript(get_schema_sql(schema_path))

def get_schema_files(schema_path):
    """
    Returns a list of schema SQL files, sorted by version number.
    """
    files = glob(os.path.join(schema_path, '*.sql'))
    natsort(files)
    return files

def get_schema_sql(schema_path):
    """
    Concatenates all schema files into a single script for running.
    """
    scripts = []
    for path in get_schema_files(schema_path):
        with open(path) as f:
            scripts.append(f.read().strip())
    return '\n'.join(scripts)

def logger(name='db.general'):
    """
    Log into the internal database logger.
    """
    return logging.getLogger(name)

def use_db(f):
    """
    Decorator that wraps functions and inserts a global database object as first
    parameter.
    """
    varnames = f.func_code.co_varnames
    has_self = len(varnames) > 0 and varnames[0] == 'self'
    @wraps(f)
    def decorator(*args, **kwargs):
        if len(args) > 0 and isinstance(args[0], Connection):
            return f(*args, **kwargs)
        if kwargs.has_key('db'):
            db = get_connection(kwargs['db'])
            del kwargs['db']
        else:
            db = get_connection()
        if has_self:
            args = (args[0], db) + args[1:]
        else:
            args = (db,) + args
        return f(*args, **kwargs)
    return decorator

def get_connection(conn=None):
    """
    Attempts to load a database connection object. If a valid connection object
    is provided explicitly, it is used. If not, an attempt is made to load the
    connection from the flask global registry.
    """
    if conn:
        return conn
    from flask import g
    if not hasattr(g, 'db'):
        g.db = get_global_factory().connect()
    return g.db

def get_global_factory():
    """
    Returns the global connection factory. Use `set_global_factory` to set this
    value at some point when the application initializes.
    """
    return _global_factory

def set_global_factory(factory):
    """
    Sets the global database connection factory. This factory is used to create
    new database connections on demand.
    """
    global _global_factory
    _global_factory = factory

class Factory(object):
    """
    Database connection factory. Stores database configuration settings and
    creates new database connections.
    """

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

    def connect(self, **options):
        opts = self.default_options()
        opts.update(options)
        conn = sqlite3.connect(self.db_path, factory=Connection, **opts)
        conn.row_factory = sqlite3.Row
        return conn

    def default_options(self):
        return {'isolation_level': None}

class Connection(sqlite3.Connection):
    """
    Wraps the native database connection object to provide logging ability as
    well as some helper functions to make querying more concise.
    """

    def __init__(self, *args, **kwargs):
        self.ident = self._ident(args[0])
        self._log('connect %s' % args[0])
        self.is_building = False
        sqlite3.Connection.__init__(self, *args, **kwargs)

    def find(self, table, pk=None, sort=None, order=None, **where):
        """
        Searches `table` for the given criteria and returns the first available
        record. If no records found, None is returned.
        """
        if pk:
            where['id'] = pk
        rows = self.search(table, sort=sort, order=order, limit=1, **where)
        return rows[0] if rows else None

    def search(self, table, sort=None, order=None, limit=None, **where):
        """
        Searches `table` for the given criteria and returns all matching
        records. If no records found, an empty list is returned.
        """
        query = 'SELECT * FROM "%s"' % self.clean(table)
        param = []
        if len(where):
            fields = []
            for name, value in where.iteritems():
                name = self.clean(name)
                if isinstance(value, list):
                    values = '","'.join(value)
                    fields.append('"%s" IN ("%s")' % (name, values))
                else:
                    fields.append('"%s"=?' % name)
                    param.append(value)
            query += ' WHERE ' + ' AND '.join(fields)
        if sort is not None:
            if not isinstance(sort, Expr):
                sort ='"%s"' % self.clean(sort)
            sort = str(sort)
            if order != 'asc':
                order = 'desc'
            query += ' ORDER BY %s %s' % (sort, order)
        if limit is not None:
            query += ' LIMIT %d ' % int(limit)
        c = self.execute(query, param)
        rows = []
        [rows.append(dict(zip(row.keys(), row))) for row in c.fetchall()]
        c.close()
        return rows

    def insert(self, table, pk=None, **fields):
        """
        Creates a record with primary key `pk` in `table` with the given data.
        If no `pk` is specified, it is uniquely generated.
        """
        if pk is not False:
            fields['id'] = pk or self.generate_pk(table)
        query = 'INSERT INTO "%(table)s" ("%(names)s") VALUES (%(param)s)' % {
            'table': self.clean(table),
            'names': '","'.join(map(self.clean, fields.keys())),
            'param': ','.join(['?'] * len(fields))
            }
        self.execute(query, fields.values())
        return fields['id'] if fields.has_key('id') else True

    def update(self, table, pk, **fields):
        """
        Updates a record with primary key `pk` in `table` with the given data.
        """
        if not len(fields):
            return
        query = 'UPDATE "%(table)s" SET %(pairs)s WHERE "id"=?' % {
            'table': self.clean(table),
            'pairs': ','.join(['"%s"=?' % self.clean(n) for n in fields.keys()])
            }
        self.execute(query, fields.values() + [pk])

    def delete(self, table, pk):
        """
        Deletes a record by primary key `pk` on the given `table`.
        """
        self.execute('DELETE FROM "%s" WHERE "id"=?' % table, [pk])

    def select(self, query, param):
        """
        Runs a select query and returns the entire result set.
        """
        cursor = self.execute(query, param)
        rows = []
        [rows.append(dict(zip(row.keys(), row))) for row in cursor.fetchall()]
        cursor.close()
        return rows

    def truncate_table(self, table):
        """
        Deletes all records in `table`.
        """
        self.execute('DELETE FROM "%s"' % table)

    def generate_pk(self, table):
        """
        Returns a new primary key that is guaranteed to be unique. A version 5
        UUID is generated and returned as a 32 character hex string.
        """
        return uuid5(uuid4(), table).hex

    def generate_slug(self, table, field='slug', length=4):
        """
        Returns a new unique slug for the given table name.
        """
        chars = list(string.ascii_lowercase + string.digits)
        while True:
            shuffle(chars)
            slug = ''.join(chars[0:length])
            if self.find(table, **{field: slug}) is None:
                break
        return slug

    def clean(self, string):
        """
        Enforces a strict naming convention to prevent SQL injection. This
        should be used when SQL identifiers (eg: table name, column name, etc)
        come from an untrusted source.
        """
        return re.sub(r'[^\w]', '', string)

    def cursor(self, cursorClass=None):
        return sqlite3.Connection.cursor(self, cursorClass or Cursor)

    def commit(self, *args, **kwargs):
        self._log('commit')
        return sqlite3.Connection.commit(self, *args, **kwargs)

    def rollback(self, *args, **kwargs):
        self._log('rollback')
        return sqlite3.Connection.rollback(self, *args, **kwargs)

    def close(self, *args, **kwargs):
        self._log('close')
        return sqlite3.Connection.close(self, *args, **kwargs)

    def _ident(self, path):
        """
        Generates a unique connection ID that will help identify connection
        patterns in log files.
        """
        tid , pid, rand, ts = current_thread().ident, os.getpid(), random(), time()
        ident = '%s_%s_%s_%s_%s' % (tid, pid, rand, ts, path)
        return sha1(ident).hexdigest()

    def _log(self, message, level='debug'):
        message = '[%s] %s' % (self.ident, message)
        getattr(logger('db.query'), level)(message)

class Cursor(sqlite3.Cursor):
    """
    Wraps the native database cursor object to provide logging ability.
    """

    def execute(self, sql, *args, **kwargs):
        self._log('execute: %s' % sql)
        return sqlite3.Cursor.execute(self, sql, *args, **kwargs)

    def executemany(self, sql, *args):
        self._log('executemany: %s' % sql)
        return sqlite3.Cursor.executemany(self, sql, *args)

    def executescript(self, sql):
        self._log('executescript: %s' % sql)
        return sqlite3.Cursor.executescript(self, sql)

    def fetchone(self):
        self._log('fetchone')
        return sqlite3.Cursor.fetchone(self)

    def fetchmany(self, *args, **kwargs):
        self._log('fetchmany')
        return sqlite3.Cursor.fetchmany(self, *args, **kwargs)

    def fetchall(self):
        self._log('fetchall')
        return sqlite3.Cursor.fetchall(self)

    def _log(self, *args, **kwargs):
        """ Proxy all logs to the connection logger. """
        self.connection._log(*args, **kwargs) # pylint: disable=E1101

class Expr(object):
    """
    Represents a raw SQL expression. Useful when trying to differentiate user
    input from internally generated SQL code.
    """

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

    def __str__(self):
        return self.sql
<commit_msg>fixed db-path not expanding tilden to user home dir<commit_after>"""
Copyright: (c) 2012 Artem Nezvigin <artem@artnez.com>
License: MIT, see LICENSE for details
"""

import os
import re
import sqlite3
import atexit
import string # pylint:disable=W0402
import logging
from threading import current_thread
from tempfile import gettempdir
from contextlib import closing
from glob import glob
from uuid import uuid4, uuid5
from hashlib import sha1
from random import random, shuffle
from time import time
from natsort import natsort
from functools import wraps
from faceoff.debug import debug

_curdir = os.path.dirname(__file__)
_schema = os.path.join(_curdir, 'schema')
_global_factory = None

def init_app(app):
    """
    Configures the provided app's database connection layer. Attaches a `db`
    property to the app object that will act as a database connection factory
    for the application's threads and subprocesses to use.
    """
    db_path = app.config['DB_PATH']
    if db_path:
        db_path = os.path.expanduser(db_path)
        if not os.path.exists(db_path):
            db_path = make_new_db(db_path)
    else:
        db_path = make_temp_db()
    app.db = Factory(db_path)
    set_global_factory(app.db)

def make_temp_db():
    """
    Creates a temporary database file and deletes when the process is ends.
    Returns the path to the temporary file.
    """
    db_link = os.path.expanduser(os.path.join('~', '.faceoff.tmp.db'))
    if not os.path.exists(db_link):
        pid, tid = os.getpid(), current_thread().ident
        db_path = os.path.join(gettempdir(), 'faceoff%s%s.tmp.db' % (pid, tid))
        build_schema(db_path, _schema)
        os.symlink(db_path, db_link)
        atexit.register(clean_temp_db(db_path, db_link))
        logger().info('created tmp db at %s linked by %s' % (db_path, db_link))
    return db_link

def clean_temp_db(db_path, db_link):
    """
    Returns a closed function that deletes the temporary database file at
    the given path.
    """
    def cleaner():
        logger().info('cleanup temp db file %s' % db_path)
        os.remove(db_path)
        logger().info('cleanup temp db link %s' % db_link)
        os.remove(db_link)
    return cleaner

def make_new_db(path):
    """
    Creates a new database at the given location.
    """
    build_schema(path, _schema)
    logger().info('created fresh db %s' % path)
    return path

def build_schema(db_path, schema_path):
    """
    Rebuilds the database using the given schema directory.
    """
    with closing(sqlite3.connect(db_path)) as conn:
        conn.executescript(get_schema_sql(schema_path))

def get_schema_files(schema_path):
    """
    Returns a list of schema SQL files, sorted by version number.
    """
    files = glob(os.path.join(schema_path, '*.sql'))
    natsort(files)
    return files

def get_schema_sql(schema_path):
    """
    Concatenates all schema files into a single script for running.
    """
    scripts = []
    for path in get_schema_files(schema_path):
        with open(path) as f:
            scripts.append(f.read().strip())
    return '\n'.join(scripts)

def logger(name='db.general'):
    """
    Log into the internal database logger.
    """
    return logging.getLogger(name)

def use_db(f):
    """
    Decorator that wraps functions and inserts a global database object as first
    parameter.
    """
    varnames = f.func_code.co_varnames
    has_self = len(varnames) > 0 and varnames[0] == 'self'
    @wraps(f)
    def decorator(*args, **kwargs):
        if len(args) > 0 and isinstance(args[0], Connection):
            return f(*args, **kwargs)
        if kwargs.has_key('db'):
            db = get_connection(kwargs['db'])
            del kwargs['db']
        else:
            db = get_connection()
        if has_self:
            args = (args[0], db) + args[1:]
        else:
            args = (db,) + args
        return f(*args, **kwargs)
    return decorator

def get_connection(conn=None):
    """
    Attempts to load a database connection object. If a valid connection object
    is provided explicitly, it is used. If not, an attempt is made to load the
    connection from the flask global registry.
    """
    if conn:
        return conn
    from flask import g
    if not hasattr(g, 'db'):
        g.db = get_global_factory().connect()
    return g.db

def get_global_factory():
    """
    Returns the global connection factory. Use `set_global_factory` to set this
    value at some point when the application initializes.
    """
    return _global_factory

def set_global_factory(factory):
    """
    Sets the global database connection factory. This factory is used to create
    new database connections on demand.
    """
    global _global_factory
    _global_factory = factory

class Factory(object):
    """
    Database connection factory. Stores database configuration settings and
    creates new database connections.
    """

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

    def connect(self, **options):
        opts = self.default_options()
        opts.update(options)
        conn = sqlite3.connect(self.db_path, factory=Connection, **opts)
        conn.row_factory = sqlite3.Row
        return conn

    def default_options(self):
        return {'isolation_level': None}

class Connection(sqlite3.Connection):
    """
    Wraps the native database connection object to provide logging ability as
    well as some helper functions to make querying more concise.
    """

    def __init__(self, *args, **kwargs):
        self.ident = self._ident(args[0])
        self._log('connect %s' % args[0])
        self.is_building = False
        sqlite3.Connection.__init__(self, *args, **kwargs)

    def find(self, table, pk=None, sort=None, order=None, **where):
        """
        Searches `table` for the given criteria and returns the first available
        record. If no records found, None is returned.
        """
        if pk:
            where['id'] = pk
        rows = self.search(table, sort=sort, order=order, limit=1, **where)
        return rows[0] if rows else None

    def search(self, table, sort=None, order=None, limit=None, **where):
        """
        Searches `table` for the given criteria and returns all matching
        records. If no records found, an empty list is returned.
        """
        query = 'SELECT * FROM "%s"' % self.clean(table)
        param = []
        if len(where):
            fields = []
            for name, value in where.iteritems():
                name = self.clean(name)
                if isinstance(value, list):
                    values = '","'.join(value)
                    fields.append('"%s" IN ("%s")' % (name, values))
                else:
                    fields.append('"%s"=?' % name)
                    param.append(value)
            query += ' WHERE ' + ' AND '.join(fields)
        if sort is not None:
            if not isinstance(sort, Expr):
                sort ='"%s"' % self.clean(sort)
            sort = str(sort)
            if order != 'asc':
                order = 'desc'
            query += ' ORDER BY %s %s' % (sort, order)
        if limit is not None:
            query += ' LIMIT %d ' % int(limit)
        c = self.execute(query, param)
        rows = []
        [rows.append(dict(zip(row.keys(), row))) for row in c.fetchall()]
        c.close()
        return rows

    def insert(self, table, pk=None, **fields):
        """
        Creates a record with primary key `pk` in `table` with the given data.
        If no `pk` is specified, it is uniquely generated.
        """
        if pk is not False:
            fields['id'] = pk or self.generate_pk(table)
        query = 'INSERT INTO "%(table)s" ("%(names)s") VALUES (%(param)s)' % {
            'table': self.clean(table),
            'names': '","'.join(map(self.clean, fields.keys())),
            'param': ','.join(['?'] * len(fields))
            }
        self.execute(query, fields.values())
        return fields['id'] if fields.has_key('id') else True

    def update(self, table, pk, **fields):
        """
        Updates a record with primary key `pk` in `table` with the given data.
        """
        if not len(fields):
            return
        query = 'UPDATE "%(table)s" SET %(pairs)s WHERE "id"=?' % {
            'table': self.clean(table),
            'pairs': ','.join(['"%s"=?' % self.clean(n) for n in fields.keys()])
            }
        self.execute(query, fields.values() + [pk])

    def delete(self, table, pk):
        """
        Deletes a record by primary key `pk` on the given `table`.
        """
        self.execute('DELETE FROM "%s" WHERE "id"=?' % table, [pk])

    def select(self, query, param):
        """
        Runs a select query and returns the entire result set.
        """
        cursor = self.execute(query, param)
        rows = []
        [rows.append(dict(zip(row.keys(), row))) for row in cursor.fetchall()]
        cursor.close()
        return rows

    def truncate_table(self, table):
        """
        Deletes all records in `table`.
        """
        self.execute('DELETE FROM "%s"' % table)

    def generate_pk(self, table):
        """
        Returns a new primary key that is guaranteed to be unique. A version 5
        UUID is generated and returned as a 32 character hex string.
        """
        return uuid5(uuid4(), table).hex

    def generate_slug(self, table, field='slug', length=4):
        """
        Returns a new unique slug for the given table name.
        """
        chars = list(string.ascii_lowercase + string.digits)
        while True:
            shuffle(chars)
            slug = ''.join(chars[0:length])
            if self.find(table, **{field: slug}) is None:
                break
        return slug

    def clean(self, string):
        """
        Enforces a strict naming convention to prevent SQL injection. This
        should be used when SQL identifiers (eg: table name, column name, etc)
        come from an untrusted source.
        """
        return re.sub(r'[^\w]', '', string)

    def cursor(self, cursorClass=None):
        return sqlite3.Connection.cursor(self, cursorClass or Cursor)

    def commit(self, *args, **kwargs):
        self._log('commit')
        return sqlite3.Connection.commit(self, *args, **kwargs)

    def rollback(self, *args, **kwargs):
        self._log('rollback')
        return sqlite3.Connection.rollback(self, *args, **kwargs)

    def close(self, *args, **kwargs):
        self._log('close')
        return sqlite3.Connection.close(self, *args, **kwargs)

    def _ident(self, path):
        """
        Generates a unique connection ID that will help identify connection
        patterns in log files.
        """
        tid , pid, rand, ts = current_thread().ident, os.getpid(), random(), time()
        ident = '%s_%s_%s_%s_%s' % (tid, pid, rand, ts, path)
        return sha1(ident).hexdigest()

    def _log(self, message, level='debug'):
        message = '[%s] %s' % (self.ident, message)
        getattr(logger('db.query'), level)(message)

class Cursor(sqlite3.Cursor):
    """
    Wraps the native database cursor object to provide logging ability.
    """

    def execute(self, sql, *args, **kwargs):
        self._log('execute: %s' % sql)
        return sqlite3.Cursor.execute(self, sql, *args, **kwargs)

    def executemany(self, sql, *args):
        self._log('executemany: %s' % sql)
        return sqlite3.Cursor.executemany(self, sql, *args)

    def executescript(self, sql):
        self._log('executescript: %s' % sql)
        return sqlite3.Cursor.executescript(self, sql)

    def fetchone(self):
        self._log('fetchone')
        return sqlite3.Cursor.fetchone(self)

    def fetchmany(self, *args, **kwargs):
        self._log('fetchmany')
        return sqlite3.Cursor.fetchmany(self, *args, **kwargs)

    def fetchall(self):
        self._log('fetchall')
        return sqlite3.Cursor.fetchall(self)

    def _log(self, *args, **kwargs):
        """ Proxy all logs to the connection logger. """
        self.connection._log(*args, **kwargs) # pylint: disable=E1101

class Expr(object):
    """
    Represents a raw SQL expression. Useful when trying to differentiate user
    input from internally generated SQL code.
    """

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

    def __str__(self):
        return self.sql
<|endoftext|>


<commit_before>import numpy as np
#~ from pyqtgraph.Qt import QtCore, QtGui
from ..gui import QT
import pyqtgraph as pg
from pyqtgraph.util.mutex import Mutex

import pyacq
from pyacq import WidgetNode,ThreadPollInput, StreamConverter, InputStream
from pyacq.viewers import QOscilloscope

#~ _dtype_spike = [('index', 'int64'), ('label', 'int64'), ('jitter', 'float64'),]
from ..peeler import _dtype_spike
from ..tools import make_color_dict
from ..labelcodes import LABEL_UNCLASSIFIED

class OnlineTraceViewer(QOscilloscope):

    _input_specs = {'signals': dict(streamtype='signals'),
                                'spikes': dict(streamtype='events', shape = (-1, ),  dtype=_dtype_spike),
                                    }

    _default_params = QOscilloscope._default_params

    def __init__(self, **kargs):
        QOscilloscope.__init__(self, **kargs)
        self.mutex = Mutex()

    def _configure(self, peak_buffer_size = 100000, catalogue=None, **kargs):
        QOscilloscope._configure(self, **kargs)
        self.peak_buffer_size = peak_buffer_size
        self.catalogue = catalogue
        assert catalogue is not None

    def _initialize(self, **kargs):
        QOscilloscope._initialize(self, **kargs)

        self.inputs['spikes'].set_buffer(size=self.peak_buffer_size, double=False)

        # poller onpeak
        self._last_peak = 0
        self.poller_peak = ThreadPollInput(input_stream=self.inputs['spikes'], return_data=True)
        self.poller_peak.new_data.connect(self._on_new_peak)

        self.spikes_array = self.inputs['spikes'].buffer.buffer

        self.scatters = {}
        self.change_catalogue(self.catalogue)

        self.params['xsize'] = 1.
        self.params['decimation_method'] = 'min_max'
        self.params['mode'] = 'scan'
        self.params['scale_mode'] = 'same_for_all'

        self.timer_scale = QT.QTimer(singleShot=True, interval=500)
        self.timer_scale.timeout.connect(self.auto_scale)
        self.timer_scale.start()

    def _start(self, **kargs):
        QOscilloscope._start(self, **kargs)
        self._last_peak = 0
        self.poller_peak.start()

    def _stop(self, **kargs):
        QOscilloscope._stop(self, **kargs)
        self.poller_peak.stop()
        self.poller_peak.wait()

    def _close(self, **kargs):
        QOscilloscope._close(self, **kargs)

    def reset_curves_data(self):
        QOscilloscope.reset_curves_data(self)
        self.t_vect_full = np.arange(0,self.full_size, dtype=float)/self.sample_rate
        self.t_vect_full -= self.t_vect_full[-1]

    def _on_new_peak(self, pos, data):
        self._last_peak = pos

    def autoestimate_scales(self):
        # in our case preprocesssed signal is supposed to be normalized
        self.all_mean = np.zeros(self.nb_channel,)
        self.all_sd = np.ones(self.nb_channel,)
        return self.all_mean, self.all_sd

    def change_catalogue(self, catalogue):
        with self.mutex:

            for k, v in self.scatters.items():
                self.plot.removeItem(v)
            self.scatters = {}

            self.catalogue = catalogue

            colors = make_color_dict(self.catalogue['clusters'])

            self.qcolors = {}
            for k, color in colors.items():
                r, g, b = color
                self.qcolors[k] = QT.QColor(r*255, g*255, b*255)

            self.all_plotted_labels = self.catalogue['cluster_labels'].tolist() + [LABEL_UNCLASSIFIED]

            for k in self.all_plotted_labels:
                qcolor = self.qcolors[k]
                qcolor.setAlpha(150)
                scatter = pg.ScatterPlotItem(x=[ ], y= [ ], pen=None, brush=qcolor, size=10, pxMode = True)
                self.scatters[k] = scatter
                self.plot.addItem(scatter)

    def _refresh(self, **kargs):
        with self.mutex:
            QOscilloscope._refresh(self, **kargs)

            mode = self.params['mode']
            gains = np.array([p['gain'] for p in self.by_channel_params.children()])
            offsets = np.array([p['offset'] for p in self.by_channel_params.children()])
            visibles = np.array([p['visible'] for p in self.by_channel_params.children()], dtype=bool)

            head = self._head
            full_arr = self.inputs['signals'].get_data(head-self.full_size, head)
            if self._last_peak==0:
                return

            keep = (self.spikes_array['index']>head - self.full_size) & (self.spikes_array['index']<head)
            spikes = self.spikes_array[keep]

            spikes_ind = spikes['index'] - (head - self.full_size)
            real_spikes_amplitude = full_arr[spikes_ind, :]
            spikes_amplitude = real_spikes_amplitude.copy()
            spikes_amplitude[:, visibles] *= gains[visibles]
            spikes_amplitude[:, visibles] += offsets[visibles]

            if mode=='scroll':
                peak_times = self.t_vect_full[spikes_ind]
            elif mode =='scan':
                #some trick to play with fake time
                front = head % self.full_size
                ind1 = (spikes['index']%self.full_size)<front
                ind2 = (spikes['index']%self.full_size)>front
                peak_times = self.t_vect_full[spikes_ind]
                peak_times[ind1] += (self.t_vect_full[front] - self.t_vect_full[-1])
                peak_times[ind2] += (self.t_vect_full[front] - self.t_vect_full[0])

            for i, k in enumerate(self.all_plotted_labels):
                keep = k==spikes['cluster_label']
                if np.sum(keep)>0:
                    if k>=0:
                        chan = self.catalogue['max_on_channel'][i]
                        if visibles[chan]:
                            times, amps = peak_times[keep], spikes_amplitude[keep, chan]
                        else:
                            times, amps = [], []

                    else:
                        chan_max = np.argmax(np.abs(real_spikes_amplitude[keep, :]), axis=1)
                        keep2 = visibles[chan_max]
                        chan_max = chan_max[keep2]
                        keep[keep] &= keep2
                        times, amps = peak_times[keep], spikes_amplitude[keep, chan_max]

                    self.scatters[k].setData(times, amps)

                else:
                    self.scatters[k].setData([], [])

    def auto_scale(self, spacing_factor=25.):
        self.params_controller.compute_rescale(spacing_factor=spacing_factor)
        self.refresh()<commit_msg>Speculative bug.<commit_after>import numpy as np
#~ from pyqtgraph.Qt import QtCore, QtGui
from ..gui import QT
import pyqtgraph as pg
from pyqtgraph.util.mutex import Mutex

import pyacq
from pyacq import WidgetNode,ThreadPollInput, StreamConverter, InputStream
from pyacq.viewers import QOscilloscope

#~ _dtype_spike = [('index', 'int64'), ('label', 'int64'), ('jitter', 'float64'),]
from ..peeler import _dtype_spike
from ..tools import make_color_dict
from ..labelcodes import LABEL_UNCLASSIFIED

class OnlineTraceViewer(QOscilloscope):

    _input_specs = {'signals': dict(streamtype='signals'),
                                'spikes': dict(streamtype='events', shape = (-1, ),  dtype=_dtype_spike),
                                    }

    _default_params = QOscilloscope._default_params

    def __init__(self, **kargs):
        QOscilloscope.__init__(self, **kargs)
        self.mutex = Mutex()

    def _configure(self, peak_buffer_size = 100000, catalogue=None, **kargs):
        QOscilloscope._configure(self, **kargs)
        self.peak_buffer_size = peak_buffer_size
        self.catalogue = catalogue
        assert catalogue is not None

    def _initialize(self, **kargs):
        QOscilloscope._initialize(self, **kargs)

        self.inputs['spikes'].set_buffer(size=self.peak_buffer_size, double=False)

        # poller onpeak
        self._last_peak = 0
        self.poller_peak = ThreadPollInput(input_stream=self.inputs['spikes'], return_data=True)
        self.poller_peak.new_data.connect(self._on_new_peak)

        self.spikes_array = self.inputs['spikes'].buffer.buffer

        self.scatters = {}
        self.change_catalogue(self.catalogue)

        self.params['xsize'] = 1.
        self.params['decimation_method'] = 'min_max'
        self.params['mode'] = 'scan'
        self.params['scale_mode'] = 'same_for_all'

        self.timer_scale = QT.QTimer(singleShot=True, interval=500)
        self.timer_scale.timeout.connect(self.auto_scale)
        self.timer_scale.start()

    def _start(self, **kargs):
        QOscilloscope._start(self, **kargs)
        self._last_peak = 0
        self.poller_peak.start()

    def _stop(self, **kargs):
        QOscilloscope._stop(self, **kargs)
        self.poller_peak.stop()
        self.poller_peak.wait()

    def _close(self, **kargs):
        QOscilloscope._close(self, **kargs)

    def reset_curves_data(self):
        QOscilloscope.reset_curves_data(self)
        self.t_vect_full = np.arange(0,self.full_size, dtype=float)/self.sample_rate
        self.t_vect_full -= self.t_vect_full[-1]

    def _on_new_peak(self, pos, data):
        self._last_peak = pos

    def autoestimate_scales(self):
        # in our case preprocesssed signal is supposed to be normalized
        self.all_mean = np.zeros(self.nb_channel,)
        self.all_sd = np.ones(self.nb_channel,)
        return self.all_mean, self.all_sd

    def change_catalogue(self, catalogue):
        with self.mutex:

            for k, v in self.scatters.items():
                self.plot.removeItem(v)
            self.scatters = {}

            self.catalogue = catalogue

            colors = make_color_dict(self.catalogue['clusters'])

            self.qcolors = {}
            for k, color in colors.items():
                r, g, b = color
                self.qcolors[k] = QT.QColor(r*255, g*255, b*255)

            self.all_plotted_labels = self.catalogue['cluster_labels'].tolist() + [LABEL_UNCLASSIFIED]

            for k in self.all_plotted_labels:
                qcolor = self.qcolors[k]
                qcolor.setAlpha(150)
                scatter = pg.ScatterPlotItem(x=[ ], y= [ ], pen=None, brush=qcolor, size=10, pxMode = True)
                self.scatters[k] = scatter
                self.plot.addItem(scatter)

    def _refresh(self, **kargs):
        with self.mutex:
            QOscilloscope._refresh(self, **kargs)

            mode = self.params['mode']
            gains = np.array([p['gain'] for p in self.by_channel_params.children()])
            offsets = np.array([p['offset'] for p in self.by_channel_params.children()])
            visibles = np.array([p['visible'] for p in self.by_channel_params.children()], dtype=bool)

            head = self._head
            full_arr = self.inputs['signals'].get_data(head-self.full_size, head)
            if self._last_peak==0:
                return

            keep = (self.spikes_array['index']>head - self.full_size) & (self.spikes_array['index']<head)
            spikes = self.spikes_array[keep]

            spikes_ind = spikes['index'] - (head - self.full_size)
            spikes_ind = spikes_ind[spikes_ind<full_arr.shape[0]] # to avoid bug if last peak is great than head
            real_spikes_amplitude = full_arr[spikes_ind, :]
            spikes_amplitude = real_spikes_amplitude.copy()
            spikes_amplitude[:, visibles] *= gains[visibles]
            spikes_amplitude[:, visibles] += offsets[visibles]

            if mode=='scroll':
                peak_times = self.t_vect_full[spikes_ind]
            elif mode =='scan':
                #some trick to play with fake time
                front = head % self.full_size
                ind1 = (spikes['index']%self.full_size)<front
                ind2 = (spikes['index']%self.full_size)>front
                peak_times = self.t_vect_full[spikes_ind]
                peak_times[ind1] += (self.t_vect_full[front] - self.t_vect_full[-1])
                peak_times[ind2] += (self.t_vect_full[front] - self.t_vect_full[0])

            for i, k in enumerate(self.all_plotted_labels):
                keep = k==spikes['cluster_label']
                if np.sum(keep)>0:
                    if k>=0:
                        chan = self.catalogue['max_on_channel'][i]
                        if visibles[chan]:
                            times, amps = peak_times[keep], spikes_amplitude[keep, chan]
                        else:
                            times, amps = [], []

                    else:
                        chan_max = np.argmax(np.abs(real_spikes_amplitude[keep, :]), axis=1)
                        keep2 = visibles[chan_max]
                        chan_max = chan_max[keep2]
                        keep[keep] &= keep2
                        times, amps = peak_times[keep], spikes_amplitude[keep, chan_max]

                    self.scatters[k].setData(times, amps)

                else:
                    self.scatters[k].setData([], [])

    def auto_scale(self, spacing_factor=25.):
        self.params_controller.compute_rescale(spacing_factor=spacing_factor)
        self.refresh()<|endoftext|>