<commit_before>#!/usr/bin/env python3
# coding=utf-8
import json
import random
import time
from typing import Dict, List

import requests
from apscheduler.schedulers.background import BackgroundScheduler

from utils import config, reload_config, safe_append, merge_chores, colors, update, should_run_bi_weekly, \
    should_run_quad_weekly

# Base URL for Slack incoming webhooks
SLACK_URL = 'https://hooks.slack.com/services/{}'

def get_quote_of_the_day() -> None:
    """
    Fetch a memorable quote and post it to Slack
    :return:
    """
    r = requests.get('http://quotes.rest/qod.json?category=inspire').json()
    quote = r['contents']['quotes'][0]
    data = {
        'text': '_"' + quote['quote'] + '" —' + quote['author'] + "_"
    }
    post_to_slack(data)

def post_to_slack(data: Dict) -> None:
    """
    Handle the request to Slack
    :param data: JSON-ready data
    """
    requests.post(SLACK_URL.format(config['slack_token']), data=json.dumps(data))

def chores_to_slack(name: str, user_chores: Dict) -> None:
    """
    Format the prepared user chores for Slack
    :param name: Name of these chores (weekly, bi-weekly, etc.)
    :param user_chores: Dictionary of each user and their assigned chores
    """
    for user in user_chores:
        data = {
            'text': '{} chores for <@{}>'.format(name, user),
            'attachments': [],
        }
        for group in user_chores[user]:
            data['attachments'].append({
                'color': '#{}'.format(colors.get(group, '000000')),
                'fields': [
                    {
                        'title': group,
                        'value': '- ' + '\n- '.join(user_chores[user][group]),
                        'short': 'false',
                    },
                ],
            })
        post_to_slack(data)

def get_shared_chores(chores: Dict, chore_group: List) -> List:
    """
    Find chores that are shared and should be assigned to a pool of several users.
    :param chores: All chores
    :param chore_group: List of the categories that should be shared
    :return: A randomized list of chores to be assigned
    """
    shared_chores = []
    for group in chores:
        if group in chore_group:
            for chore in chores[group]:
                shared_chores.append((chore, group))
    return random.sample(shared_chores, len(shared_chores))

def get_user_chores(chores: Dict[str, str]) -> Dict[str, str]:
    """
    The meat of the program. Gets and assigns all the chores as desired.
    :param chores: All chores to assign
    :return: A dictionary of each user and their assigned chores
    """
    user_chores = {}
    # Prepare each user
    for user in config['users']:
        user_chores[user['name']] = {}
    # Randomly assign chores between all users
    for i, chore in enumerate(get_shared_chores(chores, config['shared_categories'])):
        safe_append(user_chores[config['users'][i % len(config['users'])]['name']], chore[1], chore[0])
    # Randomly assign chores between a secondary set of users
    for i, chore in enumerate(get_shared_chores(chores, config['secondary_shared_categories'])):
        safe_append(user_chores[config['secondary_shared_users'][i % len(config['secondary_shared_users'])]], chore[1],
                    chore[0])
    for group in chores:
        # We've already assigned the shared chores- move on
        if group in config['shared_categories']:
            pass
        # Whoever's not in the shared group has these chores on their own,
        # e.g. a second bathroom that's not shared
        elif group in config['secondary_shared_categories']:
            for user in config['users']:
                if user not in config['secondary_shared_users']:
                    for chore in chores[group]:
                        safe_append(user_chores[user['name']], group, chore)
        else:
            # Chores that need to go to every user individually
            for user in config['users']:
                for chore in chores[group]:
                    safe_append(user_chores[user['name']], group, chore)
    return user_chores

def get_chores(period: str) -> Dict[str, str]:
    """
    Find chores for this time period.
    :param period:
    :return: Dictionary of chores for this time period.
    """
    chores_dict = {}
    for group in config[period]:
        chores_dict.update(group)
    return chores_dict

def bi_weekly_clean():
    if should_run_bi_weekly():
        chores_to_slack('Bi-weekly', get_user_chores(get_chores('bi-weekly')))

def quad_weekly_clean():
    if should_run_quad_weekly():
        chores_to_slack('Quad-weekly', get_user_chores(get_chores('quad-weekly')))

def weekly_clean():
    chores_to_slack('Weekly', get_user_chores(get_chores('weekly')))

def credit_check():
    """
    Calculate whether any users have outstanding dues to pay the head of household, post to Slack.
    """
    for user in config['users']:
        if user.get('credit') and user['credit'] - config['dues'] <= 0:
            data = {
                'text': "<@{}>, you currently don't have enough credit"
                        " for the next rent payment. Please pay the minimum"
                        " amount to <@{}> as soon as possible. {}".format(user['name'], config['payto'],
                                                                          config.get('payments', ''))
            }
            post_to_slack(data)

def run_chores():
    """
    Decide which chores should be run, format them, and post to Slack.
    """
    all_chores = []
    chore_string = ""
    if should_run_quad_weekly():
        all_chores.append(get_user_chores(get_chores('quad-weekly')))
        chore_string += "Quad-Weekly, "
    if should_run_bi_weekly():
        all_chores.append(get_user_chores(get_chores('bi-weekly')))
        chore_string += "Bi-Weekly, "
    all_chores.append(get_user_chores(get_chores('weekly')))
    chore_string += "Weekly"
    all_chores = merge_chores(all_chores)
    chores_to_slack(chore_string, all_chores)

if __name__ == '__main__':
    reload_config()

    sched = BackgroundScheduler()
    sched.start()
    sched.add_job(update, trigger='cron', hour=6)
    sched.add_job(reload_config, trigger='cron', hour=7)
    sched.add_job(get_quote_of_the_day, trigger='cron', day_of_week='sat', hour=8)
    sched.add_job(run_chores, trigger='cron', day_of_week='sat', hour=8)
    sched.add_job(credit_check, trigger='cron', day='27-31', hour=8)

    while True:
        time.sleep(1)
<commit_msg>Really stupid bug<commit_after>#!/usr/bin/env python3
# coding=utf-8
import json
import random
import time
from typing import Dict, List

import requests
from apscheduler.schedulers.background import BackgroundScheduler

from utils import config, reload_config, safe_append, merge_chores, colors, update, should_run_bi_weekly, \
    should_run_quad_weekly

# Base URL for Slack incoming webhooks
SLACK_URL = 'https://hooks.slack.com/services/{}'

def get_quote_of_the_day() -> None:
    """
    Fetch a memorable quote and post it to Slack
    :return:
    """
    r = requests.get('http://quotes.rest/qod.json?category=inspire').json()
    quote = r['contents']['quotes'][0]
    data = {
        'text': '_"' + quote['quote'] + '" —' + quote['author'] + "_"
    }
    post_to_slack(data)

def post_to_slack(data: Dict) -> None:
    """
    Handle the request to Slack
    :param data: JSON-ready data
    """
    requests.post(SLACK_URL.format(config['slack_token']), data=json.dumps(data))

def chores_to_slack(name: str, user_chores: Dict) -> None:
    """
    Format the prepared user chores for Slack
    :param name: Name of these chores (weekly, bi-weekly, etc.)
    :param user_chores: Dictionary of each user and their assigned chores
    """
    for user in user_chores:
        data = {
            'text': '{} chores for <@{}>'.format(name, user),
            'attachments': [],
        }
        for group in user_chores[user]:
            data['attachments'].append({
                'color': '#{}'.format(colors.get(group, '000000')),
                'fields': [
                    {
                        'title': group,
                        'value': '- ' + '\n- '.join(user_chores[user][group]),
                        'short': 'false',
                    },
                ],
            })
        post_to_slack(data)

def get_shared_chores(chores: Dict, chore_group: List) -> List:
    """
    Find chores that are shared and should be assigned to a pool of several users.
    :param chores: All chores
    :param chore_group: List of the categories that should be shared
    :return: A randomized list of chores to be assigned
    """
    shared_chores = []
    for group in chores:
        if group in chore_group:
            for chore in chores[group]:
                shared_chores.append((chore, group))
    return random.sample(shared_chores, len(shared_chores))

def get_user_chores(chores: Dict[str, str]) -> Dict[str, str]:
    """
    The meat of the program. Gets and assigns all the chores as desired.
    :param chores: All chores to assign
    :return: A dictionary of each user and their assigned chores
    """
    user_chores = {}
    # Prepare each user
    for user in config['users']:
        user_chores[user['name']] = {}
    # Randomly assign chores between all users
    for i, chore in enumerate(get_shared_chores(chores, config['shared_categories'])):
        safe_append(user_chores[config['users'][i % len(config['users'])]['name']], chore[1], chore[0])
    # Randomly assign chores between a secondary set of users
    for i, chore in enumerate(get_shared_chores(chores, config['secondary_shared_categories'])):
        safe_append(user_chores[config['secondary_shared_users'][i % len(config['secondary_shared_users'])]], chore[1],
                    chore[0])
    for group in chores:
        # We've already assigned the shared chores- move on
        if group in config['shared_categories']:
            pass
        # Whoever's not in the shared group has these chores on their own,
        # e.g. a second bathroom that's not shared
        elif group in config['secondary_shared_categories']:
            for user in config['users']:
                if user['name'] not in config['secondary_shared_users']:
                    for chore in chores[group]:
                        safe_append(user_chores[user['name']], group, chore)
        else:
            # Chores that need to go to every user individually
            for user in config['users']:
                for chore in chores[group]:
                    safe_append(user_chores[user['name']], group, chore)
    return user_chores

def get_chores(period: str) -> Dict[str, str]:
    """
    Find chores for this time period.
    :param period:
    :return: Dictionary of chores for this time period.
    """
    chores_dict = {}
    for group in config[period]:
        chores_dict.update(group)
    return chores_dict

def bi_weekly_clean():
    if should_run_bi_weekly():
        chores_to_slack('Bi-weekly', get_user_chores(get_chores('bi-weekly')))

def quad_weekly_clean():
    if should_run_quad_weekly():
        chores_to_slack('Quad-weekly', get_user_chores(get_chores('quad-weekly')))

def weekly_clean():
    chores_to_slack('Weekly', get_user_chores(get_chores('weekly')))

def credit_check():
    """
    Calculate whether any users have outstanding dues to pay the head of household, post to Slack.
    """
    for user in config['users']:
        if user.get('credit') and user['credit'] - config['dues'] <= 0:
            data = {
                'text': "<@{}>, you currently don't have enough credit"
                        " for the next rent payment. Please pay the minimum"
                        " amount to <@{}> as soon as possible. {}".format(user['name'], config['payto'],
                                                                          config.get('payments', ''))
            }
            post_to_slack(data)

def run_chores():
    """
    Decide which chores should be run, format them, and post to Slack.
    """
    all_chores = []
    chore_string = ""
    if should_run_quad_weekly():
        all_chores.append(get_user_chores(get_chores('quad-weekly')))
        chore_string += "Quad-Weekly, "
    if should_run_bi_weekly():
        all_chores.append(get_user_chores(get_chores('bi-weekly')))
        chore_string += "Bi-Weekly, "
    all_chores.append(get_user_chores(get_chores('weekly')))
    chore_string += "Weekly"
    all_chores = merge_chores(all_chores)
    chores_to_slack(chore_string, all_chores)

if __name__ == '__main__':
    reload_config()

    print(get_user_chores(get_chores('weekly')))
    raise SystemExit

    sched = BackgroundScheduler()
    sched.start()
    sched.add_job(update, trigger='cron', hour=6)
    sched.add_job(reload_config, trigger='cron', hour=7)
    sched.add_job(get_quote_of_the_day, trigger='cron', day_of_week='sat', hour=8)
    sched.add_job(run_chores, trigger='cron', day_of_week='sat', hour=8)
    sched.add_job(credit_check, trigger='cron', day='27-31', hour=8)

    while True:
        time.sleep(1)
<|endoftext|>


<commit_before>from django.db import models
from datetime import datetime
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from managers import QuestionManager
import enums

class FaqBase(models.Model):
    '''
    Base class for models.

    '''
    created_by = models.ForeignKey(User, null=True, editable=False, related_name="%(class)s_created_by" )
    created_on = models.DateTimeField( _('created on'), default=datetime.now, editable=False,  )
    updated_on = models.DateTimeField( _('updated on'), editable=False )
    updated_by = models.ForeignKey(User, null=True, editable=False )

    class Meta:
        abstract = True

class Question(FaqBase):
    """
    Represents a frequently asked question.

    """

    slug = models.SlugField( max_length=100, help_text="This is a unique identifier that allows your questions to display its detail view, ex 'how-can-i-contribute'", )
    text = models.TextField(_('question'), help_text='The actual question itself.')
    answer = models.TextField( _('answer'), help_text='The answer text.' )
    status = models.IntegerField( choices=enums.QUESTION_STATUS_CHOICES, default=enums.STATUS_INACTIVE, help_text="Only questions with their status set to 'Active' will be displayed. Questions marked as 'Group Header' are treated as such by views and templates that are set up to use them." )
    sort_order = models.IntegerField(_('sort order'), default=0, help_text='The order you would like the question to be displayed.')
    protected = models.BooleanField( default="False", help_text="Set true if this question is only visible by authenticated users." )

    objects = QuestionManager()

    class Meta:
        ordering = ['sort_order', 'created_on', ]

    def __unicode__(self):
        return self.text

    def save(self):
        self.updated_on = datetime.now()
        super(Question, self).save()

    def is_header(self):
        return self.status == enums.STATUS_HEADER

    def is_active(self):
        return self.status == enums.STATUS_ACTIVE
<commit_msg>adding topic assignment for faq questions<commit_after>from django.db import models
from datetime import datetime
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from managers import QuestionManager
import enums

class Topic(models.Model):
    """
    Generic Topics for FAQ question grouping
    """

    name = models.CharField(max_length=150)
    slug = models.SlugField(max_length=150)
    created_on = models.DateTimeField(default=datetime.now)

    class Meta:
        ordering = ['name']

    def __unicode__(self):
        return self.name

class FaqBase(models.Model):
    '''
    Base class for models.

    '''
    created_by = models.ForeignKey(User, null=True, editable=False, related_name="%(class)s_created_by" )
    created_on = models.DateTimeField( _('created on'), default=datetime.now, editable=False,  )
    updated_on = models.DateTimeField( _('updated on'), editable=False )
    updated_by = models.ForeignKey(User, null=True, editable=False )

    class Meta:
        abstract = True

class Question(FaqBase):
    """
    Represents a frequently asked question.

    """

    slug = models.SlugField( max_length=100, help_text="This is a unique identifier that allows your questions to display its detail view, ex 'how-can-i-contribute'", )
    topic = models.ForeignKey(Topic)
    text = models.TextField(_('question'), help_text='The actual question itself.')
    answer = models.TextField( _('answer'), help_text='The answer text.' )
    status = models.IntegerField( choices=enums.QUESTION_STATUS_CHOICES, default=enums.STATUS_INACTIVE, help_text="Only questions with their status set to 'Active' will be displayed. Questions marked as 'Group Header' are treated as such by views and templates that are set up to use them." )
    sort_order = models.IntegerField(_('sort order'), default=0, help_text='The order you would like the question to be displayed.')
    protected = models.BooleanField( default="False", help_text="Set true if this question is only visible by authenticated users." )

    objects = QuestionManager()

    class Meta:
        ordering = ['sort_order', 'created_on', ]

    def __unicode__(self):
        return self.text

    def save(self):
        self.updated_on = datetime.now()
        super(Question, self).save()

    def is_header(self):
        return self.status == enums.STATUS_HEADER

    def is_active(self):
        return self.status == enums.STATUS_ACTIVE
<|endoftext|>


<commit_before>#!/usr/bin/env python

"""Auslesen von Sensorwerte aus Home Assistant zur Visuellen Rückmeldung der Raumqualität über eine im Raum angebrachte Lampe"""

__author__      = "FarbenFroh"

import homeassistant.remote as remote
import configparser
import ast
import time
import logging

#Config
Config = configparser.ConfigParser()
Config.read("config.ini")
logging.basicConfig(format='%(asctime)s;%(message)s', datefmt='%Y.%m.%d;%H:%M:%S', level=logging.INFO, filename='sensor.csv')

#Connect to Home Assistant
api = remote.API(Config.get('HomeAssistant', 'IP'), Config.get('HomeAssistant', 'PW'))

#Create lists for sensor IDs
temperature_ids = []
co2_ids = []
humidity_ids = []

#Global Variable
goodRoom = True

#Get relevant sensor IDs from Home Assistant
entities = remote.get_states(api)
for entity in entities:
    if str(entity).__contains__(Config.get('Sensors', 'Room')) and not str(entity).__contains__("group"):
        #print(entity)
        if str(entity).__contains__("V_TEMP"):
            temperature_ids.append(entity.entity_id)
        elif str(entity).__contains__("V_LEVEL"):
            co2_ids.append(entity.entity_id)
        elif str(entity).__contains__("V_HUM"):
            humidity_ids.append(entity.entity_id)

#Get Avergage State of on list with sensor values
def getStateAvg(api, list):
    i = 0
    sum = 0
    for list_item in list:
        value = remote.get_state(api, list_item)
        sum = sum + float(value.state)
        i = i + 1
    if(i>0):
        avg = sum/i
    else:
        avg = 0
    return avg

#Let the light pulsating to a maximum brightness
def pulsatingLightCall(api, exceeded, bright_max, color):
    #actual brightness
    bright = 1.0
    #when the maximum brigthness is reached
    reachedmax = False
    lamp = Config.get('Sensors', 'Lamp')
    global goodRoom

    #Loop to control the light
    while (exceeded == True):
        if bright <= bright_max and not reachedmax:
            bright = bright + 1
            if (bright == bright_max):
                reachedmax = True
        else:
            if bright == 1:
                exceeded = False
                reachedmax = False
                #Set global variable that one value is out of the defined borders
                goodRoom = False

            bright = bright - 1

        #Call Home Assistant to set the light
        remote.call_service(api, 'light', 'turn_on', {'entity_id': lamp, 'brightness': bright, 'rgb_color': color})
        #Wait 0,1 seconds to make the brightness change smooth
        time.sleep(0.1)

#Call the diferent functions for the values
def setLightColor(api, values):

    #Mimimum temprature
    color = ast.literal_eval(Config.get('Sectors', 'Temp_Min_Color'))
    pulsatingLightCall(api, values['temp_min'], values['temp_bright'], color)

    #Maximum temprature
    color = ast.literal_eval(Config.get('Sectors', 'Temp_Max_Color'))
    pulsatingLightCall(api, values['temp_max'], values['temp_bright'], color)

    #Minimum humidity
    color = ast.literal_eval(Config.get('Sectors', 'Hum_Min_Color'))
    pulsatingLightCall(api, values['hum_min'], values['hum_bright'], color)

    #Maximum humidity
    color = ast.literal_eval(Config.get('Sectors', 'Hum_Max_Color'))
    pulsatingLightCall(api, values['hum_max'], values['hum_bright'], color)

    #Maximum Co2
    color = ast.literal_eval(Config.get('Sectors', 'Co2_Max_Color'))
    pulsatingLightCall(api, values['Co2_max'], values['Co2_bright'], color)

    #When no value border is exceeded set the light to default
    if goodRoom:
        color = ast.literal_eval(Config.get('Sectors', 'Default_Color'))
        remote.call_service(api, 'light', 'turn_on', {'entity_id': Config.get('Sensors', 'Lamp'), 'brightness': 1, 'rgb_color': color})
        time.sleep(10)

#Check that the brightness value is in the range from 0 to 100
def maxBright(value):
    if(value>100):
        value = 100
    elif(value<1):
        value = 1
    return value

#Logging function
#def logging(name):
#    print (name + " : " + str(time.ctime()))

values = {'temp_min':False,'temp_max':False,'temp_bright':0,'hum_min':False,'hum_max':False,'hum_bright':0,'Co2_max':False,'Co2_bright':0}

#Permament loop
run = True
while run:
    goodRoom = True
    tempAvg = getStateAvg(api, temperature_ids)
    if tempAvg < int(Config.get('Sectors', 'Temp_Min')):
        values['temp_bright'] = maxBright((tempAvg - int(Config.get('Sectors', 'Temp_Min'))) * -10)
        if values['temp_min'] == False:
            values['temp_min'] = True
            logging.info("Temp;Min;"+str(values['temp_bright']))
        if values['temp_max'] == True:
            values['temp_max'] = False
    elif tempAvg > int(Config.get('Sectors', 'Temp_Max')):
        values['temp_bright'] = maxBright((tempAvg - int(Config.get('Sectors', 'Temp_Max'))) * 10)
        if values['temp_max'] == False:
            values['temp_max'] = True
            logging.info("Temp;Max;"+str(values['temp_bright']))
        if values['temp_min'] == True:
            values['temp_min'] = False
    elif values['temp_min'] == True or values['temp_max'] == True:
        values['temp_min'] = False
        values['temp_max'] = False
        logging.info("Temp;Normal;0")

    humAvg = getStateAvg(api, humidity_ids)
    if humAvg < int(Config.get('Sectors', 'Hum_Min')):
        values['hum_bright'] = maxBright((humAvg - int(Config.get('Sectors', 'Hum_Min'))) * -5)
        if values['hum_min'] == False:
            values['hum_min'] = True
            logging.info("Hum;Min;"+str(values['hum_bright']))
        if values['hum_max'] == True:
            values['hum_max'] = False
    elif humAvg > int(Config.get('Sectors', 'Hum_Max')):
        values['hum_bright'] = maxBright((humAvg - int(Config.get('Sectors', 'Hum_Max'))) * 5)
        if values['hum_max'] == False:
            values['hum_max'] = True
            logging.info("Hum;Max;"+str(values['hum_bright']))
        if values['hum_min'] == True:
            values['hum_min'] = False
    elif values['hum_min'] == True or values['hum_max'] == True:
        values['hum_min'] = False
        values['hum_max'] = False
        logging.info("Hum;Normal;0")

    Co2Avg =  getStateAvg(api, co2_ids)
    if Co2Avg > int(Config.get('Sectors', 'Co2_Max')):
        values['Co2_bright'] = maxBright((Co2Avg - int(Config.get('Sectors', 'Co2_Max'))) * 0.1)
        if values['Co2_max'] == False:
            values['Co2_max'] = True
            logging.info("Co2;Max;"+str(values['Co2_bright']))
    elif values['Co2_max'] == True:
        values['Co2_max'] = False
        logging.info("Co2;Normal;0")

    logging.debug(values)
    setLightColor(api, values)
<commit_msg>Comments<commit_after>#!/usr/bin/env python

"""Auslesen von Sensorwerte aus Home Assistant zur Visuellen Rückmeldung der Raumqualität über eine im Raum angebrachte Lampe"""

__author__      = "FarbenFroh"

import homeassistant.remote as remote
import configparser
import ast
import time
import logging

#Config
Config = configparser.ConfigParser()
Config.read("config.ini")
logging.basicConfig(format='%(asctime)s;%(message)s', datefmt='%Y.%m.%d;%H:%M:%S', level=logging.INFO, filename='sensor.csv')

#Connect to Home Assistant
api = remote.API(Config.get('HomeAssistant', 'IP'), Config.get('HomeAssistant', 'PW'))

#Create lists for sensor IDs
temperature_ids = []
co2_ids = []
humidity_ids = []

#Global Variable
goodRoom = True

#Get relevant sensor IDs from Home Assistant
entities = remote.get_states(api)
for entity in entities:
    if str(entity).__contains__(Config.get('Sensors', 'Room')) and not str(entity).__contains__("group"):
        #print(entity)
        if str(entity).__contains__("V_TEMP"):
            temperature_ids.append(entity.entity_id)
        elif str(entity).__contains__("V_LEVEL"):
            co2_ids.append(entity.entity_id)
        elif str(entity).__contains__("V_HUM"):
            humidity_ids.append(entity.entity_id)

#Get Avergage State of on list with sensor values
def getStateAvg(api, list):
    i = 0
    sum = 0
    for list_item in list:
        value = remote.get_state(api, list_item)
        sum = sum + float(value.state)
        i = i + 1
    if(i>0):
        avg = sum/i
    else:
        avg = 0
    return avg

#Let the light pulsating to a maximum brightness
def pulsatingLightCall(api, exceeded, bright_max, color):
    #actual brightness
    bright = 1.0
    #when the maximum brigthness is reached
    reachedmax = False
    lamp = Config.get('Sensors', 'Lamp')
    global goodRoom

    #Loop to control the light
    while (exceeded == True):
        if bright <= bright_max and not reachedmax:
            bright = bright + 1
            if (bright == bright_max):
                reachedmax = True
        else:
            if bright == 1:
                exceeded = False
                reachedmax = False
                #Set global variable that one value is out of the defined borders
                goodRoom = False

            bright = bright - 1

        #Call Home Assistant to set the light
        remote.call_service(api, 'light', 'turn_on', {'entity_id': lamp, 'brightness': bright, 'rgb_color': color})
        #Wait 0,1 seconds to make the brightness change smooth
        time.sleep(0.1)

#Call the diferent functions for the values
def setLightColor(api, values):

    #Mimimum temprature
    color = ast.literal_eval(Config.get('Sectors', 'Temp_Min_Color'))
    pulsatingLightCall(api, values['temp_min'], values['temp_bright'], color)

    #Maximum temprature
    color = ast.literal_eval(Config.get('Sectors', 'Temp_Max_Color'))
    pulsatingLightCall(api, values['temp_max'], values['temp_bright'], color)

    #Minimum humidity
    color = ast.literal_eval(Config.get('Sectors', 'Hum_Min_Color'))
    pulsatingLightCall(api, values['hum_min'], values['hum_bright'], color)

    #Maximum humidity
    color = ast.literal_eval(Config.get('Sectors', 'Hum_Max_Color'))
    pulsatingLightCall(api, values['hum_max'], values['hum_bright'], color)

    #Maximum Co2
    color = ast.literal_eval(Config.get('Sectors', 'Co2_Max_Color'))
    pulsatingLightCall(api, values['Co2_max'], values['Co2_bright'], color)

    #When no value border is exceeded set the light to default
    if goodRoom:
        color = ast.literal_eval(Config.get('Sectors', 'Default_Color'))
        remote.call_service(api, 'light', 'turn_on', {'entity_id': Config.get('Sensors', 'Lamp'), 'brightness': 1, 'rgb_color': color})
        time.sleep(10)

#Check that the brightness value is in the range from 0 to 100
def maxBright(value):
    if(value>100):
        value = 100
    elif(value<1):
        value = 1
    return value

#Default values
values = {'temp_min':False,'temp_max':False,'temp_bright':0,'hum_min':False,'hum_max':False,'hum_bright':0,'Co2_max':False,'Co2_bright':0}

#Permament loop
run = True
while run:
    #Variable to show that no value is out of bounderies
    goodRoom = True
    #Get average temperature from sensors
    tempAvg = getStateAvg(api, temperature_ids)
    if tempAvg < int(Config.get('Sectors', 'Temp_Min')):
        values['temp_bright'] = maxBright((tempAvg - int(Config.get('Sectors', 'Temp_Min'))) * -10)
        if values['temp_min'] == False:
            values['temp_min'] = True
            logging.info("Temp;Min;"+str(values['temp_bright']))
        if values['temp_max'] == True:
            values['temp_max'] = False
    elif tempAvg > int(Config.get('Sectors', 'Temp_Max')):
        values['temp_bright'] = maxBright((tempAvg - int(Config.get('Sectors', 'Temp_Max'))) * 10)
        if values['temp_max'] == False:
            values['temp_max'] = True
            logging.info("Temp;Max;"+str(values['temp_bright']))
        if values['temp_min'] == True:
            values['temp_min'] = False
    elif values['temp_min'] == True or values['temp_max'] == True:
        values['temp_min'] = False
        values['temp_max'] = False
        logging.info("Temp;Normal;0")

    #Get average humidity from sensors
    humAvg = getStateAvg(api, humidity_ids)
    if humAvg < int(Config.get('Sectors', 'Hum_Min')):
        values['hum_bright'] = maxBright((humAvg - int(Config.get('Sectors', 'Hum_Min'))) * -5)
        if values['hum_min'] == False:
            values['hum_min'] = True
            logging.info("Hum;Min;"+str(values['hum_bright']))
        if values['hum_max'] == True:
            values['hum_max'] = False
    elif humAvg > int(Config.get('Sectors', 'Hum_Max')):
        values['hum_bright'] = maxBright((humAvg - int(Config.get('Sectors', 'Hum_Max'))) * 5)
        if values['hum_max'] == False:
            values['hum_max'] = True
            logging.info("Hum;Max;"+str(values['hum_bright']))
        if values['hum_min'] == True:
            values['hum_min'] = False
    elif values['hum_min'] == True or values['hum_max'] == True:
        values['hum_min'] = False
        values['hum_max'] = False
        logging.info("Hum;Normal;0")

    #Get average Co2 value from sensors
    Co2Avg =  getStateAvg(api, co2_ids)
    if Co2Avg > int(Config.get('Sectors', 'Co2_Max')):
        values['Co2_bright'] = maxBright((Co2Avg - int(Config.get('Sectors', 'Co2_Max'))) * 0.1)
        if values['Co2_max'] == False:
            values['Co2_max'] = True
            logging.info("Co2;Max;"+str(values['Co2_bright']))
    elif values['Co2_max'] == True:
        values['Co2_max'] = False
        logging.info("Co2;Normal;0")

    logging.debug(values)

    #Set lights calculated by the average values
    setLightColor(api, values)

<|endoftext|>


<commit_before># Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/

from fbuild.builders.c import guess_static
from fbuild.builders import find_program
from fbuild.config import c as c_test
from fbuild.record import Record
from fbuild.path import Path
import fbuild.db

from optparse import make_option
import re

def pre_options(parser):
    group = parser.add_option_group('config options')
    group.add_options((
        make_option('--buildtype', help='The build type',
                    choices=['debug', 'release'], default='debug'),
        make_option('--lua', help='Use the given Lua executable'),
        make_option('--cc', help='Use the given C compiler'),
        make_option('--cflag', help='Pass the given flag to the C++ compiler',
                    action='append', default=[]),
        make_option('--use-color', help='Use colored output',
                    action='store_true'),
        make_option('--release', help='Build in release mode',
                    action='store_true', default=False),
    ))

class Libcut_h(c_test.Test):
    libcut_h = c_test.header_test('libcut.h')

class DynAsmBuilder(fbuild.db.PersistentObject):
    def __init__(self, ctx, *, exe=None, defs=[]):
        self.ctx = ctx
        self.exe = find_program(ctx, exe or ['lua', 'luajit'])
        self.defs = defs

    @fbuild.db.cachemethod
    def translate(self, src: fbuild.db.SRC, dst) -> fbuild.db.DST:
        dst = Path.addroot(dst, self.ctx.buildroot)
        dst.parent.makedirs()
        cmd = [self.exe, 'dynasm/dynasm.lua']
        for d in self.defs:
            cmd.extend(('-D', d))
        cmd.extend(('-o', dst))
        cmd.append(src)
        self.ctx.execute(cmd, 'dynasm', '%s -> %s' % (src, dst), color='yellow')
        return dst

@fbuild.db.caches
def get_target_arch(ctx, c):
    ctx.logger.check('determining target architecture')
    cmd = [c.compiler.cc.exe, '-dumpmachine']
    cmd.extend(c.compiler.flags)
    triple = ctx.execute(cmd, quieter=1)[0].decode('ascii')
    arch = triple.split('-')[0]
    ctx.logger.passed('ok ' + arch)
    return arch

@fbuild.db.caches
def configure(ctx):
    flags = ['-Wall', '-Werror']+ctx.options.cflag
    testflags = []
    defs = []
    kw = {}
    if ctx.options.use_color:
        flags.append('-fdiagnostics-color')

    if ctx.options.release:
        kw['optimize'] = True
        kw['macros'] = ['NDEBUG']
    else:
        kw['debug'] = True
        kw['macros'] = ['DEBUG']

    c = guess_static(ctx, exe=ctx.options.cc, flags=flags, includes=['utf'],
        platform_options=[
            ({'posix'}, {'external_libs+': ['rt']}),
            ({'gcc'}, {'flags+': ['-Wno-maybe-uninitialized']}),
            ({'clang'}, {'flags+': ['-Wno-unknown-warning-option']}),
        ],
        **kw)
    arch = get_target_arch(ctx, c)
    if arch == 'x86_64':
        defs.append('X64')
    elif re.match('i\d86', arch):
        # X86 is implemented in the x86_64.dasc file.
        arch = 'x86_64'
    else:
        raise fbuild.ConfigFailed('unsupported target architecture ' + arch)

    dasm = DynAsmBuilder(ctx, exe=ctx.options.lua, defs=defs)

    if Libcut_h(c).libcut_h:
        ctx.logger.passed('found libcut.h; will build tests')
        tests = True
        testflags.append('-std=gnu11')
    else:
        ctx.logger.failed('cannot find libcut.h; will not build tests')
        tests = False
    return Record(dasm=dasm, c=c, arch=arch, tests=tests, testflags=testflags)

def build(ctx):
    rec = configure(ctx)
    c = rec.c
    dasm = rec.dasm
    src = dasm.translate('src/x86_64.dasc', 'codegen.c')
    rejit = c.build_lib('rejit', Path.glob('src/*.c') + [Path('utf/utf.c')],
        includes=['.', ctx.buildroot])
    c.build_exe('bench', ['bench.c'], includes=['src'], libs=[rejit])
    c.build_exe('ex', ['ex.c'], includes=['src'], libs=[rejit])
    if rec.tests:
        c.build_exe('tst', ['tst.c'], includes=['src'], cflags=rec.testflags,
            libs=[rejit])
<commit_msg>Cleanup<commit_after># Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/

from fbuild.builders.c import guess_static
from fbuild.builders import find_program
from fbuild.config import c as c_test
from fbuild.record import Record
from fbuild.path import Path
import fbuild.db

from optparse import make_option
import re

def pre_options(parser):
    group = parser.add_option_group('config options')
    group.add_options((
        make_option('--buildtype', help='The build type',
                    choices=['debug', 'release'], default='debug'),
        make_option('--lua', help='Use the given Lua executable'),
        make_option('--cc', help='Use the given C compiler'),
        make_option('--cflag', help='Pass the given flag to the C++ compiler',
                    action='append', default=[]),
        make_option('--use-color', help='Use colored output',
                    action='store_true'),
        make_option('--release', help='Build in release mode',
                    action='store_true', default=False),
    ))

class Libcut_h(c_test.Test):
    libcut_h = c_test.header_test('libcut.h')

class DynAsmBuilder(fbuild.db.PersistentObject):
    def __init__(self, ctx, *, exe=None, defs=[]):
        self.ctx = ctx
        self.exe = find_program(ctx, exe or ['lua', 'luajit'])
        self.defs = defs

    @fbuild.db.cachemethod
    def translate(self, src: fbuild.db.SRC, dst) -> fbuild.db.DST:
        dst = Path.addroot(dst, self.ctx.buildroot)
        dst.parent.makedirs()
        cmd = [self.exe, 'dynasm/dynasm.lua']
        for d in self.defs:
            cmd.extend(('-D', d))
        cmd.extend(('-o', dst))
        cmd.append(src)
        self.ctx.execute(cmd, 'dynasm', '%s -> %s' % (src, dst), color='yellow')
        return dst

@fbuild.db.caches
def get_target_arch(ctx, c):
    ctx.logger.check('determining target architecture')
    cmd = [c.compiler.cc.exe, '-dumpmachine']
    cmd.extend(c.compiler.flags)
    triple = ctx.execute(cmd, quieter=1)[0].decode('ascii')
    arch = triple.split('-')[0]
    ctx.logger.passed('ok ' + arch)
    return arch

@fbuild.db.caches
def configure(ctx):
    flags = ['-Wall', '-Werror']+ctx.options.cflag
    testflags = []
    defs = []
    kw = {}
    if ctx.options.use_color:
        flags.append('-fdiagnostics-color')

    if ctx.options.release:
        kw['optimize'] = True
        kw['macros'] = ['NDEBUG']
    else:
        kw['debug'] = True
        kw['macros'] = ['DEBUG']

    c = guess_static(ctx, exe=ctx.options.cc, flags=flags, includes=['utf'],
        platform_options=[
            ({'posix'}, {'external_libs+': ['rt']}),
            ({'gcc'}, {'flags+': ['-Wno-maybe-uninitialized']}),
            ({'clang'}, {'flags+': ['-Wno-unknown-warning-option']}),
        ],
        **kw)
    arch = get_target_arch(ctx, c)
    if arch == 'x86_64':
        defs.append('X64')
    elif re.match('i\d86', arch):
        # X86 is implemented in the x86_64.dasc file.
        arch = 'x86_64'
    else:
        raise fbuild.ConfigFailed('unsupported target architecture ' + arch)

    dasm = DynAsmBuilder(ctx, exe=ctx.options.lua, defs=defs)

    if Libcut_h(c).libcut_h:
        ctx.logger.passed('found libcut.h; will build tests')
        tests = True
        testflags.append('-std=gnu11')
    else:
        ctx.logger.failed('cannot find libcut.h; will not build tests')
        tests = False
    return Record(dasm=dasm, c=c, arch=arch, tests=tests, testflags=testflags)

def build(ctx):
    rec = configure(ctx)
    src = rec.dasm.translate('src/x86_64.dasc', 'codegen.c')
    rejit = rec.c.build_lib('rejit', Path.glob('src/*.c') + [Path('utf/utf.c')],
        includes=['.', ctx.buildroot])
    rec.c.build_exe('bench', ['bench.c'], includes=['src'], libs=[rejit])
    rec.c.build_exe('ex', ['ex.c'], includes=['src'], libs=[rejit])
    if rec.tests:
        rec.c.build_exe('tst', ['tst.c'], includes=['src'], cflags=rec.testflags,
                        libs=[rejit])
<|endoftext|>


<commit_before>#!/usr/bin/env python3.5
# -*- coding: utf-8 -*-
"""create c++ classes automatically"""
import argparse
import sys
import os
######################################################################
SUCCESS = 0
FAIL = 1
AVAILABLE_STYLES = ["llvm", "google", "chromium", "mozilla", "webkit"]
######################################################################

def build_parser():
    ''' define args, return parser
        for info refer to ArgumentParser doc.
    '''
    parser = argparse.ArgumentParser()

    parser.add_argument('class_name')

    access = parser.add_argument_group('Access Modifiers')
    access.add_argument('-b', '--public', nargs='+', action='append')
    access.add_argument('-p', '--private', nargs='+', action='append')
    access.add_argument('-r', '--protected', nargs='+', action='append')

    files = parser.add_argument_group('Files')
    files.add_argument('-o', '--out', nargs='?', default=os.getcwd())
    files.add_argument('-I', '--include', nargs='+')
    files.add_argument('-C', '--conf', nargs='?')

    classes = parser.add_argument_group('Classes')
    classes.add_argument('--parent', nargs='+')
    classes.add_argument('--child', nargs='+')

    other = parser.add_argument_group('Other')
    other.add_argument('--style', nargs='?', choices=AVAILABLE_STYLES,
                       default='webkit', const='webkit')
    other.add_argument('-u', '--using', nargs='+')

    return parser

######################################################################

class Method:
    ''' method info '''
    name = None
    return_type = None
    args = []
    is_virtual = False
    access = None

class Class:
    ''' Class info '''
    name = None
    parents = None
    methods = None
    members = None

class Member:
    ''' member info '''
    type = None
    default_value = None
    name = None

######################################################################

class ClassCreator:
    ''' takes args from parser and constructs files '''
    src = None
    hdr = None

    def __init__(self, args):
        pass

    def create_header_file(self):
        ''' stores string of header file '''
        pass

    def create_source_file(self):
        ''' stores string of source file '''
        pass

    def write_files(self):
        ''' writes src & hdr to out directory '''
        pass

    def stylize_files(self):
        ''' runs clang-format to sylize the file if found (or if style is on) '''
        pass

    def _get_header_guards(self):
        ''' return top and down header guards of class name '''
        self.class_name = '__{}_H__'.format(self.class_name.upper())

        top = '#ifndef {0}\n#define {0}\n'.format(self.class_name)
        down = '\n#endif  /* {} */'.format(self.class_name)

        return top, down

######################################################################

def main(args):
    creator = ClassCreator(args)

    # create
    creator.create_header_file()
    creator.create_source_file()

    # write
    creator.write_files()

    # style
    creator.stylize_files()

    return SUCCESS

if __name__ == '__main__':
    args = build_parser().parse_args()
    sys.exit(main(args))
<commit_msg>update skeleton<commit_after>#!/usr/bin/env python3.5
# -*- coding: utf-8 -*-
"""create c++ classes automatically"""
import argparse
import sys
import os
######################################################################
SUCCESS = 0
FAIL = 1
AVAILABLE_STYLES = ["llvm", "google", "chromium", "mozilla", "webkit"]
######################################################################

def build_parser():
    ''' define args, return parser
        for info refer to ArgumentParser doc.
    '''
    parser = argparse.ArgumentParser()

    parser.add_argument('class_name')

    access = parser.add_argument_group('Access Modifiers')
    access.add_argument('-b', '--public', nargs='+', action='append')
    access.add_argument('-p', '--private', nargs='+', action='append')
    access.add_argument('-r', '--protected', nargs='+', action='append')

    files = parser.add_argument_group('Files')
    files.add_argument('-o', '--out', nargs='?', default=os.getcwd())
    files.add_argument('-I', '--include', nargs='+')
    files.add_argument('-C', '--conf', nargs='?')

    classes = parser.add_argument_group('Classes')
    classes.add_argument('--parent', nargs='+')
    classes.add_argument('--child', nargs='+')

    other = parser.add_argument_group('Other')
    other.add_argument('--style', nargs='?', choices=AVAILABLE_STYLES,
                       default='webkit', const='webkit')
    other.add_argument('-u', '--using', nargs='+')

    return parser

######################################################################

class Method:
    ''' method info '''
    name = None
    return_type = None
    args = []
    is_virtual = False
    access = None

class Variable:
    ''' member info '''
    type = None
    default_value = None
    name = None

######################################################################

class ClassCreator:
    ''' takes args from parser and constructs files '''
    src = None
    hdr = None

    name = None
    parents = None
    methods = None
    variables = None

    def __init__(self, args):
        pass

    def create_header_file(self):
        ''' stores string of header file '''
        pass

    def create_source_file(self):
        ''' stores string of source file '''
        pass

    def write_files(self):
        ''' writes src & hdr to out directory '''
        pass

    def stylize_files(self):
        ''' runs clang-format to sylize the file if found (or if style is on) '''
        pass

    def _get_header_guards(self):
        ''' return top and down header guards of class name '''
        part = '__{}_H__'.format(self.name.upper())

        top = '#ifndef {0}\n#define {0}\n'.format(part)
        down = '\n#endif  /* {} */'.format(part)

        return top, down

    def _create_members(self):
        pass

######################################################################

def main(args):
    creator = ClassCreator(args)

    # create
    creator.create_header_file()
    creator.create_source_file()

    # write
    creator.write_files()

    # style
    creator.stylize_files()

    return SUCCESS

if __name__ == '__main__':
    args = build_parser().parse_args()
    sys.exit(main(args))
<|endoftext|>


<commit_before>#! user/bin/python
#  Raspberry Pi Coordinated Load Carriage Swarm

# Import required modules
from hmc5883l import hmc5883l
from nrf24pihub import NRF24
#from adns9800 import adns9800
import numpy as np
import RPi.GPIO as GPIO
import random as rand
import picamera, cv2, diff_drv, threading, time, string, math,io

# Global data
global heading
global compass
global compass_enable
global mode
global master_hdg
global master_fwd
global master_rot
global reset_watchdog
global radio_payload
global players
global form
global spot
global me

# Initialize sensors
compass = hmc5883l()

# Initialize motor driver
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
drive   = diff_drv.diff_drv(13,11,7,15,16,18,185)

# Initialize laser sensor
#mouse   = adns9800()

# Initialize radio
radio   = NRF24()
pipes = [[0xf0, 0xf0, 0xf0, 0xf0, 0xe1], [0xf0, 0xf0, 0xf0, 0xf0, 0xd2]]
radio.begin(0, 0,22,12) #set CE as GPIO 25, IRQ as GPIO 18
radio_config = radio.read_register(0x00)
radio.write_register(0x00, radio_config | 0x00110000) # Mask TX and RT interrupts
radio.setRetries(15,15)
radio.setPayloadSize(32)
radio.setChannel(0x4c)
radio.setDataRate(NRF24.BR_250KBPS)
radio.setPALevel(NRF24.PA_MAX)
radio.setAutoAck(1)
radio.openWritingPipe(pipes[0])
radio.openReadingPipe(1, pipes[1])
radio.startListening()
radio.stopListening()
radio.printDetails()
radio.startListening()

# Initialize camera
global CAMERA_WIDTH, CAMERA_HEIGHT
camera = picamera.PiCamera()
camera.hflip = True
camera.vflip = True
CAMERA_WIDTH  = 320
CAMERA_HEIGHT = 240
camera.resolution = (CAMERA_WIDTH,CAMERA_HEIGHT)

# Define interrupt callbacks and compass thread
def mot_cb():
    print '  MOTION CALLBACK'
    #TODO what should be done when motion is detected

def msg_cb(channel):
    global cmds
    global radio_payload
    global reset_watchdog
    recv_buffer = []
    radio.read(recv_buffer)
    radio.flush_rx()
    msg = null_char_strip(''.join(chr(i) for i in recv_buffer))

    #Clear IRQ
    radio.write_register(radio.STATUS,
                         radio.read_register(radio.STATUS)| 0b01000000)

    if msg in cmds.keys():
        reset_watchdog = 1
        print '    COMMAND RECEIVED:  ' + msg
        cmds[msg]()
    else:
        radio_payload = msg
        reset_watchdog = 1

def send_msg(payload):
    radio.stopListening()
    radio.write(payload)
    radio.flush_tx()
    radio.startListening()
    time.sleep(1)

def null_char_strip(in_str):
    return in_str.rstrip('\00')

# Define compass callback- get heading continuously
def get_heading(DELTAT):
    global compass
    global compass_enable
    global heading
    while compass_enable == True:
        heading = compass.heading()
        time.sleep(DELTAT)

# Radio commands
def wait():
    global mode
    print '  WAIT'
    drive.coast()

def report_id():
    print '  CARRIER __' + players[0] + '__ REPORTING FOR DUTY'
    send_msg(players[0])
    send_msg('add_id')

def add_id():
    global radio_payload
    if radio_payload not in players:
        players.append(radio_payload)

def update_spot():
    global radio_payload
    global spot
    if radio_payload.find(players[0]) == 0:
        spot = int(radio_payload[-1])

def update_form():
    global radio_payload
    global form
    form = radio_payload

def update_hdg():
    global radio_payload
    global master_hdg
    master_hdg = float(radio_payload)

def update_fwd():
    global radio_payload
    global master_fwd
    master_fwd = float(radio_payload)

def update_rot():
    global radio_payload
    global master_rot
    master_rot = float(radio_payload)

def align():
    global heading
    global master_hdg
    print '  ALIGNING TO HEADING: ' + str(master_hdg) + ' DEGREES'
    while abs(heading - master_hdg) > 10:
        drive.drive(0,10)

def assemble():
    global spot, CAMERA_WIDTH, CAMERA_HEIGHT
    print '  GOING TO ASSEMBLY'

    # Define position offsets
    offsets = [[0,0],[0,16],[16,0],[16,16]]
    target_pos = offsets[spot]

    # Define camera distance scale factor
    SCALE_FACTOR = 1

    # Capture image
    IMAGE        = '/home/pi/ee542-code/images/align.jpg'
    IMAGE_THRESH = '/home/pi/ee542-code/images/align_threshed.jpg'
    IMAGE_MARKED = '/home/pi/ee542-code/images/align_marked.jpg'
    camera.capture(IMAGE)
    img = cv2.imread(IMAGE)

    # Convert img to Hue, Saturation, Value format
    hsv_img = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

    # Define min and max color range
    GREEN_MIN = np.array([25,100,200],np.uint8)
    GREEN_MAX = np.array([80,220,255],np.uint8)

    # Threshold the image - results in b&w graphic where
    #  in-threshold pixels are white and out-of-threshold
    #  pixels are black
    img_threshed = cv2.inRange(hsv_img, GREEN_MIN, GREEN_MAX)

    # Find the circles
    circles = cv2.HoughCircles(img_threshed,cv2.cv.CV_HOUGH_GRADIENT,5,75,param1=100,param2=5,minRadius=0,maxRadius=25)

    # Mark the circles
    for i in circles[0,:]:
        cv2.circle(img,(i[0],i[1]),i[2],(0,255,0),2)
        cv2.circle(img,(i[0],i[1]),2,(0,0,255),3)

    # Save the files back to disk to view later
    cv2.imwrite(IMAGE_THRESHED,img_threshed)
    cv2.imwrite(IMAGE_MARKED,img)

    # Find average x and height of targets
    avg_x = np.average([x[0] for x in circles[0]])
    h = abs(circles[0][0][1] - circles[0][1][1])

    # Determine offsets
    x_offset = target_pos[0] - ((avg_x - CAMERA_WIDTH/2) * SCALE_FACTOR)
    y_offset = target_pos[1] - (h * SCALE_FACTOR)

    # Go to position
    navigate(x_offset,y_offset)
    send_msg(me)

def track():
    global master_fwd
    global master_rot
    print '  TRACKING FWD: ' + str(master_fwd) + ' ROT ' + str(master_rot)
    drive.drive(master_fwd,master_rot)

def navigate(x,y): # In inches
    global heading
    global master_hdg

    if (x == 0) & (y == 0):
        return

    if abs(x) > 6 : # Only adjust for lateral excursions > 6 inches

        master_hdg_mem = master_hdg
        if y > 0 :
            master_hdg = np.tanh(float(y/x)) * 180 / np.pi
        elif (y < 0) & (x < 0):
            master_hdg = np.tanh(float(y/x)) * 180 / np.pi - 90
        else:
            master_hdg = np.tanh(float(y/x)) * 180 / np.pi + 90

        align() # To trajectory heading

        dist = np.sqrt(x^2 + y^2)
        sign = 1

    else: # Just drive to Y
        dist = abs(y)

        if y > 0:
            sign = 1
        else:
            sign = -1

    drivet = dist / 10
    tstart = time.time()

    while time.time() - tstart < drivet:
        drive.drive(10)

    drive.coast()
    master_hdg = master_hdg_mem
    align()

# List of possible radio commands from master
global cmds
cmds = {'wait'        : wait,
        'report_id'   : report_id,
        'add_id'      : add_id,
        'update_spot' : update_spot,
        'update_form' : update_form,
        'update_hdg'  : update_hdg,
        'align'       : align,
        'assemble'    : assemble,
        'update_fwd'  : update_fwd,
        'update_rot'  : update_rot,
        'track'       : track}

def master():
    global mode
    global heading
    global master_hdg
    global master_fwd
    global master_rot
    global players
    global me
    global form
    global radio_payload

    print 'MASTER MODE'

    # While not knocked off by another master:
    master_heading = heading
    while mode == 'master':

        # Wait just a second! Passivate any active bots, establish mastership
        start = time.time()
        while time.time() - start < 1:
            send_msg('wait')

        # Identify the players
        print '  CARRIER IDENTIFICATION'
        players = [me]
        start = time.time()
        while (len(players) < 4) & ((time.time() - start) < 10):
            send_msg('report_id')
        if len(players) == 4:
            form = 'quad'
        else:
            form = 'tri'

        # Update formation geometry
        print '  ASSIGN __' + str(form) + '__ GEOMETRY'
        start = time.time()
        while time.time() - start < 2:
            send_msg(form)
            send_msg('update_form')

        # Perform spot assignments
        print '  PERFORM COORDINATE ASSIGNMENT'
        start = time.time()
        while time.time() - start < 2:
            for x in range(1,len(players)):
                send_msg(players[x] + str(x))
                send_msg('update_spot')

        # 10 sec align to current heading
        print '  ALIGN, PLEASE...'
        start = time.time()
        while time.time() - start < 10:
            master_hdg = heading
            send_msg(str(master_hdg))
            send_msg('update_hdg')
            send_msg('align')

        # Assemble into formation
        print '  ASSEMBLE, PLEASE...'
        num_players = len(players)
        players = [me]
        start = time.time()
        send_msg('assemble')
        while (len(players) < num_players) | (time.time() - start < 10):
            continue

        # Track forward 10 sec
        print '  FWD 10 SEC'
        master_fwd = 10
        master_rot = 0
        start = time.time()
        while time.time() - start < 10:
            send_msg(str(master_fwd))
            send_msg('update_fwd')
            send_msg(str(master_rot))
            send_msg('update_rot')
            send_msg('track')
            track()

        # Track backward 10 sec
        print '  BACKWARD 10 SEC'
        master_fwd = -10
        master_rot = 0
        start = time.time()
        while time.time() - start < 10:
            send_msg(str(master_fwd))
            send_msg('update_fwd')
            send_msg(str(master_rot))
            send_msg('update_rot')
            send_msg('track')
            track()

        # Track forward right 5 sec
        print '  FWD RIGHT 5 SEC'
        master_fwd = 10
        master_rot = 5
        start = time.time()
        while time.time() - start < 5:
            send_msg(str(master_fwd))
            send_msg('update_fwd')
            send_msg(str(master_rot))
            send_msg('update_rot')
            send_msg('track')
            track()

        # Turn 180 deg and start over
        master_hdg = math.fmod(heading +180, 360)
        align()
        continue

    # If knocked off, mode change to slave
    slave()

def slave():
    global mode
    global reset_watchdog
    global radio_payload
    print 'SLAVE MODE'

    # Start watchdog with random timeout between [25,35] interval
    reset_watchdog = 0
    watchdogThread = threading.Thread(target=watchdog,name='watchdogThread', args = (25 + rand.random()*10,))
    watchdogThread.start()

    # In slave mode, wait for radio interrupts
    while mode == 'slave':
        continue

    # If timed out, mode change to master
    master()

def watchdog(t_max):
    global mode
    global reset_watchdog
    t = 25 + rand.random()*10 # 25 to 35 sec timeout
    while t > 0:
        if reset_watchdog == 1:
            reset_watchdog = 0
            t = t_max
        print int(t)
        t -= 1
        time.sleep(1)
    mode = 'master' # Initiate mode change

# Determine own identity - 8 digit hash
me = ''.join([rand.choice(string.ascii_letters + string.digits) for n in xrange(8)])
players = [me]

# Start compass thread at 25 Hz (DELTAT= 0.04 )
compass_enable = True
compassThread = threading.Thread(target=get_heading,name='compassThread', args = ( 0.04, ))
compassThread.start()

# Initialize interrupts
#GPIO.add_event_detect(10, GPIO.FALLING, callback = mot_cb)
GPIO.setup(12,GPIO.IN, pull_up_down = GPIO.PUD_UP)
GPIO.add_event_detect(12, GPIO.FALLING, callback = msg_cb)

# Start out as slave
mode = 'slave'
slave()

<commit_msg>troubleshoot navigation<commit_after>#! user/bin/python
#  Raspberry Pi Coordinated Load Carriage Swarm

# Import required modules
from hmc5883l import hmc5883l
from nrf24pihub import NRF24
#from adns9800 import adns9800
import numpy as np
import RPi.GPIO as GPIO
import random as rand
import picamera, cv2, diff_drv, threading, time, string, math,io

# Global data
global heading
global compass
global compass_enable
global mode
global master_hdg
global master_fwd
global master_rot
global reset_watchdog
global radio_payload
global players
global form
global spot
global me

# Initialize sensors
compass = hmc5883l()

# Initialize motor driver
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
drive   = diff_drv.diff_drv(13,11,7,15,16,18,185)

# Initialize laser sensor
#mouse   = adns9800()

# Initialize radio
radio   = NRF24()
pipes = [[0xf0, 0xf0, 0xf0, 0xf0, 0xe1], [0xf0, 0xf0, 0xf0, 0xf0, 0xd2]]
radio.begin(0, 0,22,12) #set CE as GPIO 25, IRQ as GPIO 18
radio_config = radio.read_register(0x00)
radio.write_register(0x00, radio_config | 0x00110000) # Mask TX and RT interrupts
radio.setRetries(15,15)
radio.setPayloadSize(32)
radio.setChannel(0x4c)
radio.setDataRate(NRF24.BR_250KBPS)
radio.setPALevel(NRF24.PA_MAX)
radio.setAutoAck(1)
radio.openWritingPipe(pipes[0])
radio.openReadingPipe(1, pipes[1])
radio.startListening()
radio.stopListening()
radio.printDetails()
radio.startListening()

# Initialize camera
global CAMERA_WIDTH, CAMERA_HEIGHT
camera = picamera.PiCamera()
camera.hflip = True
camera.vflip = True
CAMERA_WIDTH  = 320
CAMERA_HEIGHT = 240
camera.resolution = (CAMERA_WIDTH,CAMERA_HEIGHT)

# Define interrupt callbacks and compass thread
def mot_cb():
    print '  MOTION CALLBACK'
    #TODO what should be done when motion is detected

def msg_cb(channel):
    global cmds
    global radio_payload
    global reset_watchdog
    recv_buffer = []
    radio.read(recv_buffer)
    radio.flush_rx()
    msg = null_char_strip(''.join(chr(i) for i in recv_buffer))

    #Clear IRQ
    radio.write_register(radio.STATUS,
                         radio.read_register(radio.STATUS)| 0b01000000)

    if msg in cmds.keys():
        reset_watchdog = 1
        print '    COMMAND RECEIVED:  ' + msg
        cmds[msg]()
    else:
        radio_payload = msg
        reset_watchdog = 1

def send_msg(payload):
    radio.stopListening()
    radio.write(payload)
    radio.flush_tx()
    radio.startListening()
    time.sleep(1)

def null_char_strip(in_str):
    return in_str.rstrip('\00')

# Define compass callback- get heading continuously
def get_heading(DELTAT):
    global compass
    global compass_enable
    global heading
    while compass_enable == True:
        heading = compass.heading()
        time.sleep(DELTAT)

# Radio commands
def wait():
    global mode
    print '  WAIT'
    drive.coast()

def report_id():
    print '  CARRIER __' + players[0] + '__ REPORTING FOR DUTY'
    send_msg(players[0])
    send_msg('add_id')

def add_id():
    global radio_payload
    if radio_payload not in players:
        players.append(radio_payload)

def update_spot():
    global radio_payload
    global spot
    if radio_payload.find(players[0]) == 0:
        spot = int(radio_payload[-1])

def update_form():
    global radio_payload
    global form
    form = radio_payload

def update_hdg():
    global radio_payload
    global master_hdg
    master_hdg = float(radio_payload)

def update_fwd():
    global radio_payload
    global master_fwd
    master_fwd = float(radio_payload)

def update_rot():
    global radio_payload
    global master_rot
    master_rot = float(radio_payload)

def align():
    global heading
    global master_hdg
    print '  ALIGNING TO HEADING: ' + str(master_hdg) + ' DEGREES'
    while abs(heading - master_hdg) > 10:
        drive.drive(0,10)

def assemble():
    global spot, CAMERA_WIDTH, CAMERA_HEIGHT
    print '  GOING TO ASSEMBLY'

    # Define position offsets
    offsets = [[0,0],[0,16],[16,0],[16,16]]
    target_pos = offsets[spot]

    # Define camera distance scale factor
    SCALE_FACTOR = 1

    # Capture image
    IMAGE        = '/home/pi/ee542-code/images/align.jpg'
    IMAGE_THRESH = '/home/pi/ee542-code/images/align_threshed.jpg'
    IMAGE_MARKED = '/home/pi/ee542-code/images/align_marked.jpg'
    camera.capture(IMAGE)
    img = cv2.imread(IMAGE)

    # Convert img to Hue, Saturation, Value format
    hsv_img = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

    # Define min and max color range
    GREEN_MIN = np.array([25,100,200],np.uint8)
    GREEN_MAX = np.array([80,220,255],np.uint8)

    # Threshold the image - results in b&w graphic where
    #  in-threshold pixels are white and out-of-threshold
    #  pixels are black
    img_threshed = cv2.inRange(hsv_img, GREEN_MIN, GREEN_MAX)

    # Find the circles
    circles = cv2.HoughCircles(img_threshed,cv2.cv.CV_HOUGH_GRADIENT,5,75,param1=100,param2=5,minRadius=0,maxRadius=25)

    # Mark the circles
    for i in circles[0,:]:
        cv2.circle(img,(i[0],i[1]),i[2],(0,255,0),2)
        cv2.circle(img,(i[0],i[1]),2,(0,0,255),3)

    # Save the files back to disk to view later
    cv2.imwrite(IMAGE_THRESHED,img_threshed)
    cv2.imwrite(IMAGE_MARKED,img)

    # Find average x and height of targets
    avg_x = np.average([x[0] for x in circles[0]])
    h = abs(circles[0][0][1] - circles[0][1][1])

    # Determine offsets
    x_offset = target_pos[0] - ((avg_x - CAMERA_WIDTH/2) * SCALE_FACTOR)
    y_offset = target_pos[1] - (h * SCALE_FACTOR)

    # Go to position
    navigate(x_offset,y_offset)
    send_msg(me)

def track():
    global master_fwd
    global master_rot
    print '  TRACKING FWD: ' + str(master_fwd) + ' ROT ' + str(master_rot)
    drive.drive(master_fwd,master_rot)

def navigate(x,y): # In inches
    global heading
    global master_hdg

    if (x == 0) & (y == 0):
        return

    if abs(x) > 6 : # Only adjust for lateral excursions > 6 inches

        master_hdg_mem = master_hdg
        if y > 0 :
            master_hdg = np.tanh(float(y/x)) * 180 / np.pi
        elif (y < 0) & (x < 0):
            master_hdg = np.tanh(float(y/x)) * 180 / np.pi - 90
        else:
            master_hdg = np.tanh(float(y/x)) * 180 / np.pi + 90

        align() # To trajectory heading

        dist = np.sqrt(x^2 + y^2)
        sign = 1

    else: # Just drive to Y
        dist = abs(y)

        if y > 0:
            sign = 1
        else:
            sign = -1

    drivet = dist / 10
    tstart = time.time()

    while time.time() - tstart < drivet:
        drive.drive(10)

    drive.coast()
    master_hdg = master_hdg_mem
    align()

# List of possible radio commands from master
global cmds
cmds = {'wait'        : wait,
        'report_id'   : report_id,
        'add_id'      : add_id,
        'update_spot' : update_spot,
        'update_form' : update_form,
        'update_hdg'  : update_hdg,
        'align'       : align,
        'assemble'    : assemble,
        'update_fwd'  : update_fwd,
        'update_rot'  : update_rot,
        'track'       : track}

def master():
    global mode
    global heading
    global master_hdg
    global master_fwd
    global master_rot
    global players
    global me
    global form
    global radio_payload

    print 'MASTER MODE'

    # While not knocked off by another master:
    master_heading = heading
    while mode == 'master':

        # Wait just a second! Passivate any active bots, establish mastership
        start = time.time()
        while time.time() - start < 1:
            send_msg('wait')

        # Identify the players
        print '  CARRIER IDENTIFICATION'
        players = [me]
        start = time.time()
        while (len(players) < 4) & ((time.time() - start) < 10):
            send_msg('report_id')
        if len(players) == 4:
            form = 'quad'
        else:
            form = 'tri'

        # Update formation geometry
        print '  ASSIGN __' + str(form) + '__ GEOMETRY'
        start = time.time()
        while time.time() - start < 2:
            send_msg(form)
            send_msg('update_form')

        # Perform spot assignments
        print '  PERFORM COORDINATE ASSIGNMENT'
        start = time.time()
        while time.time() - start < 2:
            for x in range(1,len(players)):
                send_msg(players[x] + str(x))
                send_msg('update_spot')

        # 10 sec align to current heading
        print '  ALIGN, PLEASE...'
        start = time.time()
        while time.time() - start < 10:
            master_hdg = heading
            send_msg(str(master_hdg))
            send_msg('update_hdg')
            send_msg('align')

        # Assemble into formation
        print '  ASSEMBLE, PLEASE...'
        num_players = len(players)
        players = [me]
        start = time.time()
        send_msg('assemble')
        while (len(players) < num_players) | (time.time() - start < 10):
            continue

        # Track forward 10 sec
        print '  FWD 10 SEC'
        master_fwd = 10
        master_rot = 0
        start = time.time()
        while time.time() - start < 10:
            send_msg(str(master_fwd))
            send_msg('update_fwd')
            send_msg(str(master_rot))
            send_msg('update_rot')
            send_msg('track')
            track()

        # Track backward 10 sec
        print '  BACKWARD 10 SEC'
        master_fwd = -10
        master_rot = 0
        start = time.time()
        while time.time() - start < 10:
            send_msg(str(master_fwd))
            send_msg('update_fwd')
            send_msg(str(master_rot))
            send_msg('update_rot')
            send_msg('track')
            track()

        # Track forward right 5 sec
        print '  FWD RIGHT 5 SEC'
        master_fwd = 10
        master_rot = 5
        start = time.time()
        while time.time() - start < 5:
            send_msg(str(master_fwd))
            send_msg('update_fwd')
            send_msg(str(master_rot))
            send_msg('update_rot')
            send_msg('track')
            track()

        # Turn 180 deg and start over
        master_hdg = math.fmod(heading +180, 360)
        align()
        continue

    # If knocked off, mode change to slave
    slave()

def slave():
    global mode
    global reset_watchdog
    global radio_payload
    print 'SLAVE MODE'

    # Start watchdog with random timeout between [25,35] interval
    reset_watchdog = 0
    watchdogThread = threading.Thread(target=watchdog,name='watchdogThread', args = (25 + rand.random()*10,))
    watchdogThread.start()

    # In slave mode, wait for radio interrupts
    while mode == 'slave':
        continue

    # If timed out, mode change to master
    master()

def watchdog(t_max):
    global mode
    global reset_watchdog
    t = 25 + rand.random()*10 # 25 to 35 sec timeout
    while t > 0:
        if reset_watchdog == 1:
            reset_watchdog = 0
            t = t_max
        print int(t)
        t -= 1
        time.sleep(1)
    mode = 'master' # Initiate mode change

# Determine own identity - 8 digit hash
me = ''.join([rand.choice(string.ascii_letters + string.digits) for n in xrange(8)])
players = [me]

# Start compass thread at 25 Hz (DELTAT= 0.04 )
compass_enable = True
compassThread = threading.Thread(target=get_heading,name='compassThread', args = ( 0.04, ))
compassThread.start()

# Initialize interrupts
#GPIO.add_event_detect(10, GPIO.FALLING, callback = mot_cb)
GPIO.setup(12,GPIO.IN, pull_up_down = GPIO.PUD_UP)
GPIO.add_event_detect(12, GPIO.FALLING, callback = msg_cb)

# Start out as slave
mode = 'slave'
slave()

<|endoftext|>


<commit_before># ---------------------------------------------------------#
#   astroNN.models.ApogeeBCNN: Contain ApogeeBCNN Model
# ---------------------------------------------------------#
from astroNN.config import keras_import_manager
from astroNN.models.BayesianCNNBase import BayesianCNNBase
from astroNN.nn.layers import MCDropout, StopGrad, BoolMask
from astroNN.nn.losses import mse_lin_wrapper, mse_var_wrapper
import tensorflow as tf
import numpy as np

keras = keras_import_manager()
regularizers = keras.regularizers
MaxPooling1D, Conv1D, Dense, Flatten, Activation, Input = keras.layers.MaxPooling1D, keras.layers.Conv1D, \
                                                          keras.layers.Dense, keras.layers.Flatten, \
                                                          keras.layers.Activation, keras.layers.Input
Lambda, Add, Subtract, Multiply = keras.layers.Lambda, keras.layers.Add, keras.layers.Subtract, keras.layers.Multiply
concatenate = keras.layers.concatenate
Model = keras.models.Model
RandomNormal = keras.initializers.RandomNormal

# noinspection PyCallingNonCallable
class ApogeeDR14GaiaDR2BCNN(BayesianCNNBase):
    """
    Class for Bayesian convolutional neural network for APOGEE DR14 Gaia DR2

    :History: 2018-Nov-06 - Written - Henry Leung (University of Toronto)
    """

    def __init__(self, lr=0.001, dropout_rate=0.3):
        super().__init__()

        self._implementation_version = '1.0'
        self.initializer = RandomNormal(mean=0.0, stddev=0.05)
        self.activation = 'relu'
        self.num_filters = [2, 4]
        self.filter_len = 8
        self.pool_length = 4
        self.num_hidden = [162, 64]
        self.max_epochs = 100
        self.lr = lr
        self.reduce_lr_epsilon = 0.00005

        self.reduce_lr_min = 1e-8
        self.reduce_lr_patience = 2
        self.l2 = 5e-9
        self.dropout_rate = dropout_rate

        self.input_norm_mode = 3

        self.task = 'regression'

        self.targetname = ['Ks-band fakemag']

    def model(self):
        input_tensor = Input(shape=self._input_shape, name='input')  # training data
        labels_err_tensor = Input(shape=(self._labels_shape,), name='labels_err')

        specmask = np.zeros(self._input_shape[0], dtype=np.bool)
        specmask[:7514] = True  # mask to extract extinction correction apparent magnitude
        spectra = Lambda(lambda x: tf.expand_dims(x, axis=-1))(self.inv_pow_mag(BoolMask(specmask)(input_tensor)))

        magmask = np.zeros(self._input_shape[0], dtype=np.bool)
        magmask[7514] = True  # mask to extract extinction correction apparent magnitude
        # value to denorm magnitude
        mag_mean = tf.constant(self.input_mean[magmask][0], dtype=tf.float32)
        denorm_mag = Lambda(lambda x: tf.add(x, mag_mean))(BoolMask(magmask)(input_tensor))
        inv_pow_mag = Lambda(lambda mag: tf.pow(tf.constant(10., dtype=tf.float32), tf.multiply(-0.2, mag)))(denorm_mag)

        gaia_aux = np.zeros(self._input_shape[0], dtype=np.bool)
        gaia_aux[7514:] = True  # mask to extract data for gaia offset
        gaia_aux_data = BoolMask(gaia_aux)(input_tensor)
        gaia_aux_hidden = MCDropout(self.dropout_rate, disable=self.disable_dropout)(Dense(units=18,
                                                                                kernel_regularizer=regularizers.l2(self.l2),
                                                                                kernel_initializer=self.initializer,
                                                                                activation='tanh')(gaia_aux_data))
        offset = Dense(units=1, kernel_initializer=self.initializer, activation='tanh')(gaia_aux_hidden)

        cnn_layer_1 = Conv1D(kernel_initializer=self.initializer, padding="same", filters=self.num_filters[0],
                             kernel_size=self.filter_len, kernel_regularizer=regularizers.l2(self.l2))(spectra)
        activation_1 = Activation(activation=self.activation)(cnn_layer_1)
        dropout_1 = MCDropout(self.dropout_rate, disable=self.disable_dropout)(activation_1)
        cnn_layer_2 = Conv1D(kernel_initializer=self.initializer, padding="same", filters=self.num_filters[1],
                             kernel_size=self.filter_len, kernel_regularizer=regularizers.l2(self.l2))(dropout_1)
        activation_2 = Activation(activation=self.activation)(cnn_layer_2)
        maxpool_1 = MaxPooling1D(pool_size=self.pool_length)(activation_2)
        flattener = Flatten()(maxpool_1)
        dropout_2 = MCDropout(self.dropout_rate, disable=self.disable_dropout)(flattener)
        layer_3 = Dense(units=self.num_hidden[0], kernel_regularizer=regularizers.l2(self.l2),
                        kernel_initializer=self.initializer)(dropout_2)
        activation_3 = Activation(activation=self.activation)(layer_3)
        dropout_3 = MCDropout(self.dropout_rate, disable=self.disable_dropout)(activation_3)
        layer_4 = Dense(units=self.num_hidden[1], kernel_regularizer=regularizers.l2(self.l2),
                        kernel_initializer=self.initializer)(dropout_3)
        activation_4 = Activation(activation=self.activation)(layer_4)
        fakemag_output = Dense(units=self._labels_shape, activation='softplus', name='fakemag_output')(activation_4)
        fakemag_variance_output = Dense(units=self._labels_shape, activation='linear',
                                        name='fakemag_variance_output')(activation_4)

        # multiplt a pre-determined de-normalization factor, such that fakemag std approx. 1 for Sloan APOGEE population
        _fakemag_denorm = Lambda(lambda x: tf.multiply(x, tf.constant(68, dtype=tf.float32)))(fakemag_output)
        _fakemag_var_denorm = Lambda(lambda x: tf.multiply(x, tf.constant(68, dtype=tf.float32)))(fakemag_variance_output)
        _fakemag_parallax = Multiply()([_fakemag_denorm, inv_pow_mag])

        output = Add(name='output')([_fakemag_parallax, offset])
        variance_output = Lambda(lambda x: tf.log(tf.abs(tf.multiply(x[2], tf.divide(tf.exp(x[0]), x[1])))),
                                 name='variance_output')([fakemag_variance_output, fakemag_output, _fakemag_parallax])

        model = Model(inputs=[input_tensor, labels_err_tensor], outputs=[output, variance_output])
        # new astroNN high performance dropout variational inference on GPU expects single output
        model_prediction = Model(inputs=[input_tensor], outputs=concatenate([_fakemag_denorm, _fakemag_var_denorm]))

        variance_loss = mse_var_wrapper(output, labels_err_tensor)
        output_loss = mse_lin_wrapper(variance_output, labels_err_tensor)

        return model, model_prediction, output_loss, variance_loss
<commit_msg>correctly pass spectra tensor [ci skip]<commit_after># ---------------------------------------------------------#
#   astroNN.models.ApogeeBCNN: Contain ApogeeBCNN Model
# ---------------------------------------------------------#
from astroNN.config import keras_import_manager
from astroNN.models.BayesianCNNBase import BayesianCNNBase
from astroNN.nn.layers import MCDropout, StopGrad, BoolMask
from astroNN.nn.losses import mse_lin_wrapper, mse_var_wrapper
import tensorflow as tf
import numpy as np

keras = keras_import_manager()
regularizers = keras.regularizers
MaxPooling1D, Conv1D, Dense, Flatten, Activation, Input = keras.layers.MaxPooling1D, keras.layers.Conv1D, \
                                                          keras.layers.Dense, keras.layers.Flatten, \
                                                          keras.layers.Activation, keras.layers.Input
Lambda, Add, Subtract, Multiply = keras.layers.Lambda, keras.layers.Add, keras.layers.Subtract, keras.layers.Multiply
concatenate = keras.layers.concatenate
Model = keras.models.Model
RandomNormal = keras.initializers.RandomNormal

# noinspection PyCallingNonCallable
class ApogeeDR14GaiaDR2BCNN(BayesianCNNBase):
    """
    Class for Bayesian convolutional neural network for APOGEE DR14 Gaia DR2

    :History: 2018-Nov-06 - Written - Henry Leung (University of Toronto)
    """

    def __init__(self, lr=0.001, dropout_rate=0.3):
        super().__init__()

        self._implementation_version = '1.0'
        self.initializer = RandomNormal(mean=0.0, stddev=0.05)
        self.activation = 'relu'
        self.num_filters = [2, 4]
        self.filter_len = 8
        self.pool_length = 4
        self.num_hidden = [162, 64]
        self.max_epochs = 100
        self.lr = lr
        self.reduce_lr_epsilon = 0.00005

        self.reduce_lr_min = 1e-8
        self.reduce_lr_patience = 2
        self.l2 = 5e-9
        self.dropout_rate = dropout_rate

        self.input_norm_mode = 3

        self.task = 'regression'

        self.targetname = ['Ks-band fakemag']

    def model(self):
        input_tensor = Input(shape=self._input_shape, name='input')  # training data
        labels_err_tensor = Input(shape=(self._labels_shape,), name='labels_err')

        specmask = np.zeros(self._input_shape[0], dtype=np.bool)
        specmask[:7514] = True  # mask to extract extinction correction apparent magnitude
        spectra = Lambda(lambda x: tf.expand_dims(x, axis=-1))(BoolMask(specmask)(input_tensor))

        magmask = np.zeros(self._input_shape[0], dtype=np.bool)
        magmask[7514] = True  # mask to extract extinction correction apparent magnitude
        # value to denorm magnitude
        mag_mean = tf.constant(self.input_mean[magmask][0], dtype=tf.float32)
        denorm_mag = Lambda(lambda x: tf.add(x, mag_mean))(BoolMask(magmask)(input_tensor))
        inv_pow_mag = Lambda(lambda mag: tf.pow(tf.constant(10., dtype=tf.float32), tf.multiply(-0.2, mag)))(denorm_mag)

        gaia_aux = np.zeros(self._input_shape[0], dtype=np.bool)
        gaia_aux[7514:] = True  # mask to extract data for gaia offset
        gaia_aux_data = BoolMask(gaia_aux)(input_tensor)
        gaia_aux_hidden = MCDropout(self.dropout_rate, disable=self.disable_dropout)(Dense(units=18,
                                                                                kernel_regularizer=regularizers.l2(self.l2),
                                                                                kernel_initializer=self.initializer,
                                                                                activation='tanh')(gaia_aux_data))
        offset = Dense(units=1, kernel_initializer=self.initializer, activation='tanh')(gaia_aux_hidden)

        cnn_layer_1 = Conv1D(kernel_initializer=self.initializer, padding="same", filters=self.num_filters[0],
                             kernel_size=self.filter_len, kernel_regularizer=regularizers.l2(self.l2))(spectra)
        activation_1 = Activation(activation=self.activation)(cnn_layer_1)
        dropout_1 = MCDropout(self.dropout_rate, disable=self.disable_dropout)(activation_1)
        cnn_layer_2 = Conv1D(kernel_initializer=self.initializer, padding="same", filters=self.num_filters[1],
                             kernel_size=self.filter_len, kernel_regularizer=regularizers.l2(self.l2))(dropout_1)
        activation_2 = Activation(activation=self.activation)(cnn_layer_2)
        maxpool_1 = MaxPooling1D(pool_size=self.pool_length)(activation_2)
        flattener = Flatten()(maxpool_1)
        dropout_2 = MCDropout(self.dropout_rate, disable=self.disable_dropout)(flattener)
        layer_3 = Dense(units=self.num_hidden[0], kernel_regularizer=regularizers.l2(self.l2),
                        kernel_initializer=self.initializer)(dropout_2)
        activation_3 = Activation(activation=self.activation)(layer_3)
        dropout_3 = MCDropout(self.dropout_rate, disable=self.disable_dropout)(activation_3)
        layer_4 = Dense(units=self.num_hidden[1], kernel_regularizer=regularizers.l2(self.l2),
                        kernel_initializer=self.initializer)(dropout_3)
        activation_4 = Activation(activation=self.activation)(layer_4)
        fakemag_output = Dense(units=self._labels_shape, activation='softplus', name='fakemag_output')(activation_4)
        fakemag_variance_output = Dense(units=self._labels_shape, activation='linear',
                                        name='fakemag_variance_output')(activation_4)

        # multiplt a pre-determined de-normalization factor, such that fakemag std approx. 1 for Sloan APOGEE population
        _fakemag_denorm = Lambda(lambda x: tf.multiply(x, tf.constant(68, dtype=tf.float32)))(fakemag_output)
        _fakemag_var_denorm = Lambda(lambda x: tf.multiply(x, tf.constant(68, dtype=tf.float32)))(fakemag_variance_output)
        _fakemag_parallax = Multiply()([_fakemag_denorm, inv_pow_mag])

        output = Add(name='output')([_fakemag_parallax, offset])
        variance_output = Lambda(lambda x: tf.log(tf.abs(tf.multiply(x[2], tf.divide(tf.exp(x[0]), x[1])))),
                                 name='variance_output')([fakemag_variance_output, fakemag_output, _fakemag_parallax])

        model = Model(inputs=[input_tensor, labels_err_tensor], outputs=[output, variance_output])
        # new astroNN high performance dropout variational inference on GPU expects single output
        model_prediction = Model(inputs=[input_tensor], outputs=concatenate([_fakemag_denorm, _fakemag_var_denorm]))

        variance_loss = mse_var_wrapper(output, labels_err_tensor)
        output_loss = mse_lin_wrapper(variance_output, labels_err_tensor)

        return model, model_prediction, output_loss, variance_loss
<|endoftext|>