text:
# For directory management
import sys
sys.path.insert(0, '../')

# Imports firebase
import pyrebase
from config import config

# Importing required libraries for scraping
import ssl
import re
import requests
from multiprocessing import Pool
from multiprocessing import Process
from bs4 import BeautifulSoup as BS

# Importing required libraries for wordprocessing
from datetime import datetime as dt
from pytz import timezone
import pytz
import time
from time import mktime
import pandas as pd
import numpy as np
import json

# Forming JSON objects
import uuid

class Article:
    def __init__ (self, header, articleurl):
        self.header = header
        self.articleurl = articleurl
        self.articlecontent = ""

    def get_header(self):
        return self.header

    def get_articleurl(self):
        return self.articleurl

    def get_articlecontent(self):
        return self.articlecontent

    def store_articlecontent(self, articlecontent):
        self.articlecontent = articlecontent

def fetch_latest_articles(homepage):
    try:
        r = requests.get(homepage, timeout=10)
        homepage_html = BS(r.content, "lxml")
        article_headers = [re.sub('\t', '', re.sub('\n', '', tag.text)) for tag in homepage_html.find_all("a", {"class": "post-block__title__link"})]
        article_href = [tag['href'] for tag in homepage_html.find_all("a", {"class": "post-block__title__link"})]
        return article_headers, article_href
    except:
        print("Found an error while getting latest articles' URL!")

def fetch_article_content(articleobj):
    try:
        r = requests.get(articleobj.get_articleurl(), timeout=10)
        article_html = BS(r.content, "lxml")
        # Remove embedded content eg. tweets, videos
        for div in article_html.find_all("div", {'class':'embed'}):
            div.decompose()
        article_content = [para.text for para in (article_html.find_all("div", {"class": "article-content"})[0]).find_all("p")]
        article_prose = ''.join(article_content)
        articleobj.store_articlecontent(article_prose)
        return articleobj
    except:
        print("Found an error while getting article's content!")

if __name__ == '__main__':
    # Instantiates a firebase client
    firebase = pyrebase.initialize_app(config)
    db = firebase.database()
    utc = pytz.utc
    fmt = '%Y-%m-%dT%H:%M:%SZ'
    curr_time = dt.utcnow()

    # News website
    homepage = "https://techcrunch.com/"

    with Pool(6) as pool:
        print("Started Pooling Process...")

        article_objs = []
        article_details = fetch_latest_articles(homepage)
        for article in range(len(article_details[0])):
            article_objs.append(Article(article_details[0][article], article_details[1][article]))

        # test_obj = article_objs[]
        pool1 = pool.map(fetch_article_content, article_objs)
        # print(pool1[1].get_articlecontent())

    all_articles = []
    headers = {'content-type': 'application/json'}
    for article in pool1[:2]:
        # try:
            data = {
                'articles': [
                    {
                        'text': article.get_articlecontent()
                    }
                ],
                'summary_length_words': 60
            }
            response = requests.post(
                url = "https://coherent-summarization-service.staging.agolo.com/summarization",
                data = json.dumps(data),
                headers=headers
            )
            # response = json.response.sentences
            # print(response.content)
            content = json.loads(response.content)
            print(content)
            summary = ' '.join(content['sentences'])
            print(summary)

            # Build Article Json Object
            article_data = {
                'mainText': article.get_header() + "... " + summary,
                'redirectionUrl': article.get_articleurl(),
                'titleText': article.get_header(),
                'uid': uuid.uuid1().__str__(),
                'updateDate': dt(dt.utcnow().year, dt.utcnow().month, dt.utcnow().day, dt.utcnow().hour, dt.utcnow().minute, dt.utcnow().second, tzinfo=pytz.utc).strftime(fmt)
            }
            print(type(article_data))
            print(article_data)
            all_articles.append(article_data)
        # except:
        #     print("Error in calling API!")
    db.child("technology").set(all_articles)

    print("Done with scraping and pushing to Firebase!")


text:
from flask import Flask, jsonify, redirect, request, url_for
from flask_cors import CORS
import config
import requests
import json
import os
import time
from textblob import TextBlob
import numpy as np
import pandas as pd
import re
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')
import praw
import geocoder
from datetime import datetime
import urllib

# configuration
DEBUG = True

# instantiate the app
app = Flask(__name__)
app.config.from_object(__name__)
app.config['TESTING'] = True

# enable CORS
CORS(app, resources={r'/*': {'origins': '*'}})

#Getting data from TWITTER
def auth():
    return os.environ.get("BEARER_TOKEN")

def create_url(query):
    tweet_fields = "tweet.fields=public_metrics,created_at,geo,referenced_tweets,text,author_id,id,in_reply_to_user_id"
    max_results = "max_results=100"
    user_fields = "user.fields=profile_image_url"
    url = "https://api.twitter.com/2/tweets/search/recent?query={}&{}&{}&{}".format(
        query, tweet_fields, user_fields ,max_results
        )
    return url

def create_id_url(query):

    tweet_fields = "tweet.fields=public_metrics,created_at,geo,lang,referenced_tweets,text,author_id,in_reply_to_user_id"
    user_fields = "user.fields=profile_image_url"
    url = "https://api.twitter.com/2/tweets?ids={}&{}&{}".format(
        query, tweet_fields, user_fields
        )
    return url

def create_users_url(query):

    user_fields= "user.fields=location,name,profile_image_url,public_metrics,username,verified"
    url = "https://api.twitter.com/2/users?ids={}&{}".format(
        query, user_fields
    )
    return url

def create_headers(bearer_token):
    headers = {"Authorization": config.bearer_token}
    return headers

def connect_to_endpoint(url, headers):
    response = requests.request("GET", url, headers=headers)
    print(response.status_code)
    if response.status_code != 200:
        raise Exception(response.status_code, response.text)
    return response.json()

@app.route('/showinfo', methods=['GET', 'POST'])
def showinfo():
    d = request.json
    print(d)

    #Reddit API call, time displayed in unix
    reddit_data = reddit_api(d["query"])

    if len(reddit_data) != 0:
        try:
            piechartreddit = reddit_piechart(reddit_data)
            linechartreddit = reddit_linechart(reddit_data)
            reddit_data = sorted(reddit_data, key = lambda i: i['upvotes'],reverse=True)
            engagementreddit = reddit_engagement(reddit_data)
            toppostsreddit = reddit_top_posts(reddit_data)
            topusersreddit = reddit_top_users(reddit_data)
            wordcloudreddit = reddit_wordcloud(reddit_data)
        except Exception as e:
            print(e)

    else:
        print("No Reddit data")
        piechartreddit = []
        linechartreddit = {}
        engagementreddit = {}
        toppostsreddit = []
        topusersreddit = []
        wordcloudreddit = []

    unencoded_query = str(d["query"])

    unavailable_chars = ['$', '*', "'", '&', "‘"]

    for i in unavailable_chars :
        unencoded_query = unencoded_query.replace(i, '')

    query = urllib.parse.quote(unencoded_query)

    #Create the token to get acess to the Twitter
    bearer_token = auth()
    headers = create_headers(bearer_token)

    #API call to get back a dictionary with 10 api call without any duplicates
    try:
        json_response = api_caller(query, headers)
        print(json_response)

    except Exception as e:
        print(e)
        json_response = {"data": "No data"}

    # New call to the the Twitter API that uses the ID of the retweeted tweets and adds the data of the original tweets to the dictionary
    #The create_id_url creates the url that is used to call the api with.

    if json_response["data"] != "No data":
        ids = extract_retweets(json_response)
        if len(ids) > 0:
            url_ids = create_id_url(ids)
            json_response2 = connect_to_endpoint(url_ids, headers)
            for item in json_response2["data"]:
                json_response["data"].append(item)

        json_response["data"] = sorted(json_response["data"], key = lambda i: i['public_metrics']["retweet_count"],reverse=True)

        json_response3 = extract_usernames(json_response, headers)

        for i in range(len(json_response["data"])):
            json_response3[i]["public_metrics_user"] = json_response3[i].pop("public_metrics")
            json_response3[i]["author_id"] = json_response3[i].pop("id")
            json_response["data"][i].update(json_response3[i])

        #Create all of the data that is going to be displayed in the frontend from the json_response
        barchart = create_barchart(json_response)
        linechart = create_linechart(json_response)
        topposts = create_topposts(json_response)
        topusers = create_topusers(json_response)
        activity = create_activity(json_response)
        links = create_links(json_response)
        nodes = create_nodes(links)
        geochart = create_geochart(json_response)
        links = create_links(json_response)
        nodes = create_nodes(links)
        alltext = all_text(json_response)

        json_response["data"] = {d["query"]: {"barchart": barchart, "linechart": linechart, "topposts": topposts, "topusers": topusers,
        "activity": activity, "query": d["query"], "nodes": nodes, "links": links, "geochart": geochart, "alltext": alltext,"engagementreddit": engagementreddit, "piechartreddit": piechartreddit, "linechartreddit":linechartreddit,
        "toppostsreddit": toppostsreddit, "topusersreddit": topusersreddit, "wordcloudreddit": wordcloudreddit}}

        sentiment = show_tweets_text_sentiment(json_response)

        json_response["data"][d["query"]]["sentiment"] = sentiment

    return json.dumps(json_response)

#The fuction api_caller is a fuction that is used to call the api 10 times and add the responses to the json_response
#We use the time libery to avoid getting the same json response back from the api, so it waits 1 second between every api call
def api_caller(query, headers):
    url = create_url(query)
    json_response = connect_to_endpoint(url, headers)

    time.time()
    count = 0
    if "data" in json_response:
        while True:
            api_call = connect_to_endpoint(url, headers)

            for item in api_call["data"]:
                if item["id"] not in json_response["data"]:
                    json_response["data"].append(item)

            time.sleep(2)
            count += 1
            print ("tick")

            if count == 2:
                count = 0
                break
        json_response_no_duplicates = remove_duplicates(json_response)

    else:
        json_response_no_duplicates = {"data": "No data"}

    return json_response_no_duplicates

#Function for removing the duplicate responses when calling the api 10 times. When searching for a query that is popular you get few duplicates from the api.
#Searching for a query that is not popular you will get many duplicates often the same from all 10 api calls.
#We use a empty dictionary that we add to and if the same value gets stored in the same key it will just be overwritten so there will be no duplicates
def remove_duplicates(json_response):
    response_map = {}
    for i in range(len(json_response["data"])):
        key = json_response["data"][i]["id"]
        value = json_response["data"][i]
        response_map[key] = value

    json_response_no_duplicates = {"data":[]}
    for value in response_map.values():
        json_response_no_duplicates["data"].append(value)

    return json_response_no_duplicates

#Function for extracting the data about the orginal tweets that was retweeted.
#The reasoning behind this is because the twitter search api returns alot of retweets of an orignal tweet.
#And when the api returns a retweet you only get the retweets not the likes, quotes or the replies of the orginal tweet.
#So we call the api for the orignal tweets that we extract from the retweets.
def extract_retweets(json_response):
    id_list = []
    joined_string = []
    tweet_dict = json_response["data"]
    for i in range(len(tweet_dict)):
        if "referenced_tweets" in tweet_dict[i]:
            if tweet_dict[i]["referenced_tweets"][0]["type"] == "retweeted":
                if tweet_dict[i]["referenced_tweets"][0]["id"] not in id_list:
                    id_list.append(tweet_dict[i]["referenced_tweets"][0]["id"])
                    if len(id_list) == 100:
                        break
    if len(id_list) > 0:
        joined_string = ",".join(id_list)

    return joined_string

#Function for extracting all off the usernames and calling the API for every 100 tweet.
#Returning all of the user data that is missing from the first API call.
#With this function we get the location and stats like how many followers a user has.xz z
def extract_usernames(json_response, headers):
    author_id_list = []
    tweet_dict = json_response["data"]

    for i in range(len(tweet_dict)):
        author_id_list.append(tweet_dict[i]["author_id"])

    url_list = []
    for i in range(0, len(author_id_list), 100):
        chunk = author_id_list[i:i + 100]
        joined_string = ",".join(chunk)
        url_users_ids = create_users_url(joined_string)
        url_list.append(url_users_ids)

    time.time()
    count = 0
    json_response2 = connect_to_endpoint(url_list[0], headers)

    while True:
        if len(url_list) == 1:
            break
        for i in range(len(url_list)-1):
            api_call = connect_to_endpoint(url_list[i+1], headers)
            for item in api_call["data"]:
                json_response2["data"].append(item)

        time.sleep(1)
        count += 1
        print("tick")
        if count == len(url_list)-1:
            count = 0
            break

    return json_response2["data"]

#Function to extract the total likes, retweets, replies and quotes. The API return the total retweets of the original tweet is a user has retweeted it.
#So the function does not count the retweets of a retweet. Only the retweets of the orignal tweet
def create_barchart(json_response):
    tweets = json_response["data"]
    total_retweets = 0
    total_likes = 0
    total_replies = 0
    total_quotes = 0

    for i in range(len(tweets)):
        if "referenced_tweets" in tweets[i]:
              if tweets[i]['referenced_tweets'][0]["type"] != "retweeted":
                  total_retweets += tweets[i]['public_metrics']["retweet_count"]
                  total_likes += tweets[i]['public_metrics']["like_count"]
                  total_replies += tweets[i]['public_metrics']["reply_count"]
                  total_quotes += tweets[i]['public_metrics']["quote_count"]
        else:
              total_retweets += tweets[i]['public_metrics']["retweet_count"]
              total_likes += tweets[i]['public_metrics']["like_count"]
              total_quotes += tweets[i]['public_metrics']["quote_count"]
              total_replies += tweets[i]['public_metrics']["reply_count"]

    barchartlist = [['Likes', total_likes], ['Retweeets', total_retweets],['Replies', total_replies],['Quotes',total_quotes]]

    return barchartlist

#Function to make a list that is needed to display the areachart
def create_linechart(json_response):
    tweets = json_response["data"]
    allDates = []
    finalDates = {}

    for i in range(len(tweets)):
        element = tweets[i]["created_at"]
        allDates.append(element)

    for i in range(len(tweets)):
        allDates[i] = allDates[i].replace(".000Z", "")

    allDates.sort()
    allDates = allDates[7:]

    for i in range(len(allDates)):
        finalDates[allDates[i]]=i+1

    return finalDates

#Function that returns the dates from when a person retweets a tweet
def create_retweet_linechart(json_response):
    tweets = json_response["data"]
    allDates = []
    finalDates = []

    for i in range(len(tweets)):
        if "referenced_tweets" in tweets[i]:
              if tweets[i]['referenced_tweets'][0]["type"] == "retweeted":
                    element = tweets[i]["created_at"]
                    allDates.append(element)

    for i in range(len(tweets)):
        allDates[i] = allDates[i].replace(".000Z", "")

    allDates.sort()
    allDates = allDates[5:]

    for i in range(len(allDates)):
        finalDates.append([allDates[i],i+1])

    return finalDates

#Function the extract the top 3 post and returns a dictonary with all the data needed to display as a tweet
def create_topposts(json_response):
    tweets = json_response["data"]
    topposts = []
    for i in range(len(tweets)):
        if "referenced_tweets" not in tweets[i]:
            date = format_date(tweets[i]["created_at"])
            topposts.append({"author_id": tweets[i]["author_id"], "retweets": tweets[i]['public_metrics']["retweet_count"], "likes": tweets[i]['public_metrics']["like_count"], "text": tweets[i]['text'],
            "username": tweets[i]["username"], "img": tweets[i]["profile_image_url"], "date": date, "followers": tweets[i]['public_metrics_user']["followers_count"], "verified": tweets[i]["verified"], "id": tweets[i]["id"]})
            if len(topposts) == 3:
                break

    return topposts

#Maybe add functionality that returns day and month like 13 Feb...
def format_date(timestamp):
    ts = time.strptime(timestamp[:19], "%Y-%m-%dT%H:%M:%S")
    s = time.strftime("%m/%d/%Y", ts)
    return s

#Function for extracting the top 9 users with the most followers with a check that is not added
def create_topusers(json_response):
    tweets = json_response["data"]
    topusers = []
    for i in range(len(tweets)):
        if tweets[i]["username"] not in topusers:
            topusers.append({"username": tweets[i]["username"], "img": tweets[i]["profile_image_url"], "followers": tweets[i]['public_metrics_user']["followers_count"], "verified": tweets[i]["verified"]})
            if len(topusers) == 9:
                break
    sorted_topusers = sorted(topusers, key = lambda i: i['followers'],reverse=True)
    return sorted_topusers

#Function to extact the data displayed in the yellow header. Returning a dictionary with the total posts, users and engagement
#Users is only users that is posting something not a user that is retweeting. Total posts is the total tweets, replies and quotes.
#Engangement is likes and retweets
def create_activity(json_response):
    activity = {}
    tweets = json_response["data"]
    user_ids = []

    engagement = 0
    total_posts = 0
    for i in range(len(tweets)):
        if "referenced_tweets" in tweets[i]:
              if tweets[i]['referenced_tweets'][0]["type"] != "retweeted":
                  engagement += tweets[i]['public_metrics']["retweet_count"]
                  engagement += tweets[i]['public_metrics']["like_count"]
                  total_posts += 1
                  if tweets[i]["author_id"] not in user_ids:
                      user_ids.append(tweets[i]["author_id"])
        else:
              engagement += tweets[i]['public_metrics']["retweet_count"]
              engagement += tweets[i]['public_metrics']["like_count"]
              total_posts += 1
              if tweets[i]["author_id"] not in user_ids:
                      user_ids.append(tweets[i]["author_id"])

    activity["posts"] = total_posts
    activity["users"] = len(user_ids)
    activity["engagement"] = engagement

    return activity

def create_links(json_response):

    links = []

    tweets = json_response["data"]
    for i in range(len(tweets)):
        if "referenced_tweets" in tweets[i]:
            if tweets[i]['referenced_tweets'][0]["type"] == "retweeted":
                text = tweets[i]['text']
                idxAt = text.find('@')
                idxCo = text.find(':')
                followers = tweets[i]['public_metrics_user']['followers_count']

                if followers <= 10000:
                    size = 3
                elif followers <= 50000:
                    size = 5
                elif followers <= 100000:
                    size = 7
                elif followers <= 1000000:
                    size = 10
                elif followers > 1000000:
                    size = 13

                links.append({'source': text[idxAt+1:idxCo], 'target': tweets[i]['username'], 'size':size})

            elif tweets[i]['referenced_tweets'][0]["type"] == "replied_to":
                text = tweets[i]['text']
                idxAt = text.find('@')
                idxS = text.find(' ')
                followers = tweets[i]['public_metrics_user']['followers_count']

                if followers <= 10000:
                    size = 3
                elif followers <= 50000:
                    size = 5
                elif followers <= 100000:
                    size = 7
                elif followers <= 1000000:
                    size = 10
                elif followers > 1000000:
                    size = 13

                links.append({'source': text[idxAt+1:idxS], 'target': tweets[i]['username'], 'size':size})

    return links

def create_nodes(links):
    nodes = []
    for i in range(len(links)):
        if links[i]['source'] not in nodes:
            nodes.append({"id":links[i]['source'], 'size':links[i]['size']})

        if links[i]['target'] not in nodes:
            nodes.append({"id":links[i]['target'], 'size':links[i]['size'] })
    return nodes

#Legg inn en error catcher her for geochart kommer ofte feil når det er en query med lite resultater
def create_geochart(json_response):
    all_locations = []
    tweets = json_response["data"]
    for tweet in tweets:
        if "location" in tweet:
            all_locations.append(tweet["location"])
            if len(all_locations) == 99:
                break

    all_countries = []

    try:
        g = geocoder.mapquest(all_locations, method='batch', key=config.mapquest_key)
        for result in g:
            all_countries.append(str(result.country))

        geochart = dict((x,all_countries.count(x)) for x in set(all_countries))
    except:
        geochart = {}

    return geochart

def all_text(json_response):
    tweets = json_response["data"]
    allText = []
    for i in range(len(tweets)):
        allText.append({"tweets_text": tweets[i]["text"]})
    return allText

#  Print tweet text
def show_tweets_text_sentiment(json_response):

    tweets = json_response["data"]

    textTweets=[]
    for i, (k,v) in enumerate(tweets.items()):
        for i in range(len(tweets[k]["alltext"])):
            textTweets.append(tweets[k]["alltext"][i]["tweets_text"])

    # Create a dataframe with a column called Tweets
    df = pd.DataFrame(columns=['Tweets'])
    for tweet in textTweets:
        cleantweet = cleanTxt(tweet)
        df = df.append({"Tweets": cleantweet}, ignore_index=True)
    # Show  rows of data

    # Create two new columns 'Subjectivity' & 'Polarity'
    df['Subjectivity'] = df['Tweets'].apply(getSubjectivity)
    df['Polarity'] = df['Tweets'].apply(getPolarity)
    df['Analysis'] = df['Polarity'].apply(getAnalysis)
    pd.set_option('display.max_rows', df.shape[0]+1)
    dictionaryObject = df.to_dict()

    sentiment = {"Positive": 0, "Negative": 0, "Neutral": 0}

    analysis = dictionaryObject["Analysis"]

    for i in range(len(analysis)):
        if analysis[i] == "Positive":
            sentiment["Positive"] += 1
        elif analysis[i] == "Negative":
            sentiment["Negative"] += 1
        else:
            sentiment["Neutral"] += 1

    return sentiment

# Create a function to clean the tweets
def cleanTxt(text):
    text = re.sub('@[A-Za-z0–9]+', '', text) #Removing @mentions
    text = re.sub('#', '', text) # Removing '#' hash tag
    text = re.sub('RT[\s]+', '', text) # Removing RT
    text = re.sub('https?:\/\/\S+', '', text) # Removing hyperlink

    return text

# A function to get the subjectivity
def getSubjectivity(text):
   return TextBlob(text).sentiment.subjectivity

# A function to get the polarity
def getPolarity(text):
   return  TextBlob(text).sentiment.polarity

# function to compute negative (-1), neutral (0) and positive (+1) analysis
def getAnalysis(score):
    if score < 0:
        return 'Negative'
    elif score == 0:
        return 'Neutral'
    else:
        return 'Positive'

def reddit_api(query):
    reddit_data = []
    #Reddit API call, time displayed in unix
    reddit = praw.Reddit(
    client_id=config.client_id,
    client_secret=config.client_secret,
    user_agent="my user agent")

    for submission in reddit.subreddit("all").search(query, limit=100):
        try:
            reddit_data.append({"author": str(submission.author.name), "title": str(submission.title),"name": str(submission.name), "upvote_ratio": submission.upvote_ratio, "upvotes": submission.ups,
            "url": str(submission.permalink), "created_at": str(submission.created_utc), "subreddit": str(submission.subreddit), "number_of_comments": str(submission.num_comments),
            "post_karma": submission.author.link_karma, "comment_karma": submission.author.comment_karma, "icon_img": submission.author.icon_img})
        except:
            print("User suspended")

    print(reddit_data)
    return reddit_data

def reddit_piechart(reddit_data):
    ratio_sum = 0
    for i in range(len(reddit_data)):
        ratio_sum += reddit_data[i]["upvote_ratio"]

    upvote_ratio = round(ratio_sum/len(reddit_data),2)

    downvote_ratio = round(1-upvote_ratio,2)

    ratio = [["Upvote Percentage", upvote_ratio*100], ["Downvote Percentage", downvote_ratio*100]]

    return ratio

def reddit_wordcloud(reddit_data):
    wordcloud = {}
    for i in range(len(reddit_data)):
        subreddit = reddit_data[i]["subreddit"]
        if subreddit not in wordcloud:
            wordcloud[subreddit] = 1
        else:
            wordcloud[subreddit] += 1

    wordcloud_list = []
    for value in wordcloud.keys():
        if wordcloud[value]>1:
            if wordcloud[value] <= 3:
                wordcloud_list.append({"subreddit": value, "value": 1})
            elif wordcloud[value] <= 6:
                wordcloud_list.append({"subreddit": value, "value": 2})
            elif wordcloud[value] <= 10:
                wordcloud_list.append({"subreddit": value, "value": 3})
            elif wordcloud[value] <= 20:
                wordcloud_list.append({"subreddit": value, "value": 4})
            else:
                wordcloud_list.append({"subreddit": value, "value": 5})

    return wordcloud_list

def reddit_linechart(reddit_data):
    allDates = []
    finalDates = {}

    for i in range(len(reddit_data)):
        timestamp = reddit_data[i]["created_at"]

        timestamp = timestamp.replace(".0", "")

        allDates.append(datetime.utcfromtimestamp(int(timestamp)).strftime('%Y-%m-%dT%H:%M:%S'))

    allDates.sort()

    for i in range(len(allDates)):
        finalDates[allDates[i]]=i+1
    return finalDates

def reddit_top_posts(reddit_data):
    top_posts = []
    for i in range(len(reddit_data)):
        top_post = {}
        top_post["title"] = reddit_data[i]["title"]
        top_post["url"] = reddit_data[i]["url"]
        top_post["title"] = reddit_data[i]["title"]
        top_post["author"] = reddit_data[i]["author"]
        top_post["upvotes"] = reddit_data[i]["upvotes"]
        top_post["icon_img"] = reddit_data[i]["icon_img"]
        top_post["subreddit"] = reddit_data[i]["subreddit"]
        top_post["number_of_comments"] = reddit_data[i]["number_of_comments"]
        timestamp = reddit_data[i]["created_at"]
        timestamp = timestamp.replace(".0", "")
        top_post["created_at"]= datetime.utcfromtimestamp(int(timestamp)).strftime('%Y-%m-%d')
        top_posts.append(top_post)
        if len(top_posts) == 3:
            break

    return top_posts

def reddit_top_users(reddit_data):
    reddit_data = sorted(reddit_data, key = lambda i: i['post_karma'],reverse=True)
    top_users = []
    for i in range(len(reddit_data)):
        top_user = {}
        top_user["author"] = reddit_data[i]["author"]
        top_user["post_karma"] = reddit_data[i]["post_karma"]
        top_user["comment_karma"] = reddit_data[i]["comment_karma"]
        top_user["icon_img"] = reddit_data[i]["icon_img"]
        if top_user not in top_users:
            top_users.append(top_user)
            if len(top_users) == 9:
                break

    return top_users

def reddit_engagement(reddit_data):
    engagement = {}

    user_ids = []
    upvotes = 0

    for i in range(len(reddit_data)):
        upvotes += reddit_data[i]["upvotes"]
        if reddit_data[i]["author"] not in user_ids:
            user_ids.append(reddit_data[i]["author"])

    engagement["posts"] = len(reddit_data)
    engagement["users"] = len(user_ids)
    engagement["engagement"] = upvotes

    return  engagement

if __name__ == '__main__':
    app.run(debug=True)
"export FLASK_DEBUG=ON"

ext: py

reason: import numpy


text:
# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE.md file in the project root
# for full license information.
# ==============================================================================

import os
import numpy as np
import cntk as C
import pytest
from cntk.ops.tests.ops_test_utils import cntk_device
from itertools import product

#############
#helpers
#############
def verify_no_input(model, tmpdir, name):
    filename = os.path.join(str(tmpdir), name + R'.onnx')
    model.save(filename, format=C.ModelFormat.ONNX)

    loaded_model = C.Function.load(filename, format=C.ModelFormat.ONNX)
    assert model.shape == loaded_model.shape

    o = model.eval()
    o_ = loaded_model.eval()
    assert np.allclose(o_, o)

def verify_one_input(model, data, tmpdir, name, device=None):
    filename = os.path.join(str(tmpdir), name + R'.onnx')
    model.save(filename, format=C.ModelFormat.ONNX)

    loaded_model = C.Function.load(filename, format=C.ModelFormat.ONNX)
    assert model.shape == loaded_model.shape

    if device:
        o0 = model.eval({model.arguments[0]:data}, device=device)
        o1 = loaded_model.eval({loaded_model.arguments[0]:data}, device=device)
    else:
        o0 = model.eval({model.arguments[0]:data})
        o1 = loaded_model.eval({loaded_model.arguments[0]:data})

    if (type(o0) is list):
        o0 = o0[0]
    if (type(o1) is list):
        o1 = o1[0]

    assert np.allclose(o0, o1)

def verify_two_input(model, data1, data2, tmpdir, name):
    filename = os.path.join(str(tmpdir), name + R'.onnx')
    model.save(filename, format=C.ModelFormat.ONNX)

    loaded_model = C.Function.load(filename, format=C.ModelFormat.ONNX)
    assert model.shape == loaded_model.shape

    o0 = model.eval({model.arguments[0]:data1, model.arguments[1]:data2})
    o1 = loaded_model.eval({loaded_model.arguments[0]:data1, loaded_model.arguments[1]:data2})

    assert np.allclose(o0, o1)

#Shared Test Configs
DType_Config = (np.float32, np.float16)

#Abs
@pytest.mark.parametrize("dtype", DType_Config)
def test_Abs(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        shape = (4, 5)
        data = np.random.rand(*shape).astype(dtype)

        model = C.abs(data)
        verify_no_input(model, tmpdir, 'Abs_0')

        x = C.input_variable(shape)
        model = C.abs(x)

        verify_one_input(model, data, tmpdir, 'Abs_1')

#Add
@pytest.mark.parametrize("dtype", DType_Config)
def test_Add(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        shape = (4, 5)
        data1 = np.random.rand(*shape).astype(dtype)
        data2 = np.random.rand(*shape).astype(dtype)
        model = C.plus(data1, data2)
        verify_no_input(model, tmpdir, 'Add_0')

        x = C.input_variable(shape)
        model = C.plus(x, data2)

        verify_one_input(model, data1, tmpdir, 'Add_1')

        y = C.input_variable(shape)
        model = C.plus(x, y)

        verify_two_input(model, data1, data2, tmpdir, 'Add_2')

#And
def test_And(tmpdir):
    pytest.skip('Need to support new ONNX spec.')
    data1 = np.asarray([[1, 1, 0, 0],[1, 1, 1, 1]], dtype)
    data2 = np.asarray([1, 0, 1, 0], dtype)

    model = C.element_and(data1, data2)
    verify_no_input(model, tmpdir, 'And_0')

    x = C.input_variable(np.shape(data1))
    y = C.input_variable(np.shape(data2))

    model = C.element_and(x, data2)
    verify_one_input(model, data1, tmpdir, 'And_1')

    model = C.element_and(x, y)
    verify_two_input(model, data1, data2, tmpdir, 'And_2')

#Or
def test_Or(tmpdir):
    pytest.skip('Need to support new ONNX spec.')
    data1 = np.asarray([[1, 1, 0, 0],[1, 1, 1, 1]], np.float32)
    data2 = np.asarray([1, 0, 1, 0], np.float32)

    model = C.element_or(data1, data2)
    verify_no_input(model, tmpdir, 'Or_0')

    x = C.input_variable(np.shape(data1))
    y = C.input_variable(np.shape(data2))

    model = C.element_or(x, data2)
    verify_one_input(model, data1, tmpdir, 'Or_1')

    model = C.element_or(x, y)
    verify_two_input(model, data1, data2, tmpdir, 'Or_2')

#Xor
def test_Xor(tmpdir):
    pytest.skip('Need to support new ONNX spec.')
    data1 = np.asarray([[1, 1, 0, 0],[1, 1, 1, 1]], np.float32)
    data2 = np.asarray([1, 0, 1, 0], np.float32)

    model = C.element_xor(data1, data2)
    verify_no_input(model, tmpdir, 'Xor_0')

    x = C.input_variable(np.shape(data1))
    y = C.input_variable(np.shape(data2))

    model = C.element_xor(x, data2)
    verify_one_input(model, data1, tmpdir, 'Xor_1')

    model = C.element_xor(x, y)
    verify_two_input(model, data1, data2, tmpdir, 'Xor_2')

#Not
@pytest.mark.parametrize("dtype", DType_Config)
def test_Not(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data1 = np.asarray([[1, 1, 0, 0],[1, 1, 1, 1]]).astype(dtype)

        model = C.element_not(data1)
        verify_no_input(model, tmpdir, 'Not_0')

        x = C.input_variable(np.shape(data1))

        model = C.element_not(x)
        verify_one_input(model, data1, tmpdir, 'Not_1')

#ArgMax
@pytest.mark.parametrize("dtype", DType_Config)
def test_ArgMax(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        shape = (4, 5)
        data = np.random.rand(*shape).astype(dtype)
        model = C.argmax(data, 0)

        verify_no_input(model, tmpdir, 'ArgMax_0')

        x = C.input_variable(shape)
        model = C.argmax(x, 0)
        verify_one_input(model, data, tmpdir, 'ArgMax_1')

#ArgMin
@pytest.mark.parametrize("dtype", DType_Config)
def test_ArgMin(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        shape = (4, 5)
        data = np.random.rand(*shape).astype(dtype)
        model = C.argmin(data, 0)

        verify_no_input(model, tmpdir, 'ArgMin_0')

#AveragePool
@pytest.mark.parametrize("dtype", DType_Config)
def test_AveragePool(tmpdir, dtype, device_id):
    if device_id == -1 and dtype == np.float16:
        pytest.skip('Test is skipped on CPU with float16 data')
    device = cntk_device(device_id)
    with C.default_options(dtype=dtype):
        img = np.reshape(np.arange(16, dtype = dtype), [1, 4, 4])
        x = C.input_variable(img.shape)
        model = C.pooling(x, C.AVG_POOLING, (2,2), (2,2))

        verify_one_input(model, img, tmpdir, 'AveragePool_1', device)

#BatchNormalization
@pytest.mark.parametrize("dtype", DType_Config)
def test_BatchNormalization(tmpdir, dtype):
    if (dtype == np.float16):
        pytest.skip("TO BE FIXED")
    with C.default_options(dtype = dtype):
        sample = [  # 5 samples having 4 classes
            [1, 1, 2, 3],
            [0, 0, 0, 0],
            [3, 3, 4, 4],
            [1000, 1000, 1000, 1000],
            [10000, 10000, 10000, 10000]]

        epsilon = 0.00001

        t = np.asarray(sample, dtype=dtype).reshape(-1,1)
        mean = 1
        var = 2
        init_scale = 3
        init_bias = 4

        scale        = C.Parameter(init=np.asarray([init_scale], dtype=dtype), dtype=dtype)
        bias         = C.Parameter(init=np.asarray([init_bias], dtype=dtype), dtype=dtype)
        run_mean     = C.ops.constant(mean, shape=(1), dtype=dtype)
        run_variance = C.ops.constant(var,  shape=(1), dtype=dtype)
        run_count    = C.ops.constant(0,               dtype=dtype)

        a = C.input_variable(shape=(1), dtype=dtype, needs_gradient=False, name='a')

        op_node = C.batch_normalization(a, scale, bias, run_mean, run_variance, running_count=run_count, spatial=False,
            epsilon=epsilon)

        verify_one_input(op_node, t, tmpdir, 'BatchNormalization')

#Cast
Cast_Type_Config = (np.float64, np.float32, np.float16)
@pytest.mark.parametrize("from_type", Cast_Type_Config)
@pytest.mark.parametrize("to_type", Cast_Type_Config)
def test_Cast(tmpdir, from_type, to_type):
    test_name = "cast_" + from_type.__name__ + "_to_" + to_type.__name__
    shape = (3, 10, 15)
    input_var = C.input_variable(shape, dtype = from_type, name='features')
    model = C.cast(input_var, dtype=to_type)
    data = np.random.rand(*shape).astype(from_type)
    verify_one_input(model, data, tmpdir, test_name)

# Ceil
@pytest.mark.parametrize("dtype", DType_Config)
def test_Ceil(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.asarray([0.2, 1.3, 4., 5.5, 0.0], dtype)
        model = C.ceil(data)

        verify_no_input(model, tmpdir, 'ceil_0')

        x = C.input_variable(data.shape)

        model = C.ceil(x)

        verify_one_input(model, data, tmpdir, 'ceil_1')

#Clip
@pytest.mark.parametrize("dtype", DType_Config)
def test_Clip(tmpdir, dtype):
    if (dtype == np.float16):
        pytest.skip("TO BE FIXED")
    with C.default_options(dtype = dtype):
        data = np.asarray([0.2, 1.3, 4., 5.5, 0.0], dtype)
        min_v = 2
        max_v = 4
        model = C.clip(data, min_v, max_v)

        verify_no_input(model, tmpdir, 'clip_0')

        x = C.input_variable(data.shape)

        model = C.clip(x, min_v, max_v)

        verify_one_input(model, data, tmpdir, 'clip_1')

#Concat
@pytest.mark.parametrize("dtype", DType_Config)
def test_Concat(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data1 = np.asarray([[[1, 2], [4, 5]]], dtype=dtype)
        x = C.constant(value=data1)
        # create 3x2 matrix in a sequence of length 1 in a batch of one sample
        data2 = np.asarray([[[10, 20],
                             [30, 40],
                             [50, 60]]],dtype=dtype)
        y = C.constant(value=data2)

        # splice both inputs on axis=0 returns a 5x2 matrix
        model = C.splice(x, y, axis=1)

        verify_no_input(model, tmpdir, 'Concat_0')

        x = C.input_variable(data1.shape)

        model = C.splice(x, y, axis=1)

        verify_one_input(model, data1, tmpdir, 'Concat_1')

@pytest.mark.parametrize("dtype", DType_Config)
def test_ConvTranspose(tmpdir, dtype, device_id):
    if device_id == -1 and dtype == np.float16:
        pytest.skip('Test is skipped on CPU with float16 data')
    device = cntk_device(device_id)
    with C.default_options(dtype=dtype):
        # Keep the shapes below as they are, because this tests an earlier bug.
        input_shape = (48, 16, 16)
        img = np.reshape(np.arange(np.prod(input_shape), dtype = dtype), input_shape)

        x = C.input_variable(input_shape)

        kernel_shape = (48, 32, 3, 3) # For convolution_transpose the shape is (I x O x W x H)
        kernel = C.constant(value = np.ones(shape=(kernel_shape), dtype = dtype))

        conv_trans_model = C.convolution_transpose(kernel, x, strides=(2, 2), output_shape=(32, 32, 32), auto_padding = [False, True, True])

        verify_one_input(conv_trans_model, img, tmpdir, 'ConvTranspose_0', device)

# DepthToSpace
@pytest.mark.parametrize("dtype", DType_Config)
def test_DepthToSpace(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        num_channels = 9
        block_size = 3
        image_shape = (4, 5)
        input_val = np.array(np.reshape(range(num_channels), (num_channels, 1, 1)), dtype=dtype)
        input_val = np.tile(input_val, (1,) + image_shape)
        input_val.shape = (1,) + input_val.shape
        img = C.input_variable((num_channels,) + image_shape, dtype=dtype)
        model = C.depth_to_space(img, block_size)

        verify_one_input(model, input_val, tmpdir, 'DepthToSpace')

#Div
def test_Div(tmpdir):
    pytest.skip('Need to support new ONNX spec.')
    def run_div_test(shape1, shape2, tmpdir):
        broadcast = 'no_broadcast'
        if (shape1 != shape2):
            broadcast = 'with_broadcast'

        data1 = np.random.rand(*shape1).astype(np.float32)
        data2 = np.random.rand(*shape2).astype(np.float32)

        x = C.input_variable(shape1)
        y = C.input_variable(shape2)

        model = C.element_divide(data1, data2)
        verify_no_input(model, tmpdir, 'Div_' + broadcast + '_d1d2')

        model = C.element_divide(x, data2)
        verify_one_input(model, data1, tmpdir, 'Div_' + broadcast + '_xd2')

        model = C.element_divide(data1, y)
        verify_one_input(model, data2, tmpdir, 'Div_' + broadcast + '_d1y')

        model = C.element_divide(x, y)
        verify_two_input(model, data1, data2, tmpdir, 'Div_' + broadcast + '_xy')

    shape1 = (2, 3, 4, 5)
    shape2 = shape1
    # without broadcast
    run_div_test(shape1, shape2, tmpdir)

    # with broadcast
    shape2 = (1, 3, 1, 1)
    run_div_test(shape1, shape2, tmpdir)

#Dropout
@pytest.mark.parametrize("dtype", DType_Config)
def test_Dropout(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.asarray([[10, 20],[30, 40],[50, 60]], dtype=dtype)
        model = C.dropout(data, 0.5)
        verify_no_input(model, tmpdir, 'Dropout_0')

        x = C.input_variable(data.shape)
        model = C.dropout(x, 0.5)
        verify_one_input(model, data, tmpdir, 'Dropout_1')

#Elu
@pytest.mark.parametrize("dtype", DType_Config)
def test_Elu(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.asarray([[-1, -0.5, 0, 1, 2]], dtype=dtype)
        model = C.elu(data)
        verify_no_input(model, tmpdir, 'Elu_0')

        x1 = C.input_variable(data.shape)
        model = C.elu(x1)
        verify_one_input(model, data, tmpdir, 'Elu_1')

        x2 = C.input_variable(data.shape)
        model = C.elu(x2, alpha=2.0)
        verify_one_input(model, data, tmpdir, 'Elu_2')

#Equal
@pytest.mark.parametrize("dtype", DType_Config)
def test_Equal(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data0 = np.asarray([41., 42., 43.], dtype=dtype)
        data1 = np.asarray([42., 42., 42.], dtype=dtype)
        model = C.equal(data0, data1)
        verify_no_input(model, tmpdir, 'Equal_0')

#Exp
@pytest.mark.parametrize("dtype", DType_Config)
def test_Exp(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.asarray([0., 1.], dtype=dtype)
        model = C.exp(data)
        verify_no_input(model, tmpdir, 'Exp_0')

        x = C.input_variable(data.shape)
        model = C.exp(x)
        verify_one_input(model, data, tmpdir, 'Exp_1')

#Flatten
@pytest.mark.parametrize("dtype", DType_Config)
def test_Flatten(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        shape = (2, 3, 4, 5)
        data = np.reshape(np.arange(np.prod(shape), dtype = dtype), shape)
        model = C.flatten(data, 1)
        verify_no_input(model, tmpdir, 'Flatten_0')

        x = C.input_variable(data.shape)
        model = C.flatten(x, 1)
        verify_one_input(model, data, tmpdir, 'Flatten_1')

#Floor
@pytest.mark.parametrize("dtype", DType_Config)
def test_Floor(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.asarray([0.2, 1.3, 4., 5.5, 0.0], dtype=dtype)
        model = C.floor(data)
        verify_no_input(model, tmpdir, 'Floor_0')

        x = C.input_variable(data.shape)
        model = C.floor(x)
        verify_one_input(model, data, tmpdir, 'Floor_1')

#Gather
@pytest.mark.parametrize("dtype", DType_Config)
def test_Gather(tmpdir, dtype):
    if (dtype == np.float16):
        pytest.skip("TO BE FIXED")
    with C.default_options(dtype = dtype):
        c = np.asarray([[[0],[1]],[[4],[5]]]).astype(dtype)
        x = C.input_variable((2,1))
        d = np.arange(12).reshape(6,2).astype(dtype)
        y = C.constant(d)
        model = C.gather(y, x)
        verify_one_input(model, c, tmpdir, 'Gather_1')

#Gather
@pytest.mark.parametrize("dtype", DType_Config)
def test_Gather_With_Axis(tmpdir, dtype):
    if (dtype == np.float16):
        pytest.skip("TO BE FIXED")
    with C.default_options(dtype = dtype):
        data = np.asarray( [[ [111, 112], [121, 122], [131, 132], ],[ [211, 212], [221, 222], [231, 232], ]]).astype(dtype)
        indices = np.asarray([[0, 1, 1], [1, 1, 1]])
        x = C.input_variable(np.shape(data))
        y = C.input_variable(np.shape(indices))
        axis = 1
        model = C.gather(data, y, axis)
        verify_one_input(model, indices, tmpdir, 'Gather_With_Axis_1')

#Greater
@pytest.mark.parametrize("dtype", DType_Config)
def test_Greater(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        model = C.greater([41., 42., 43.], [42., 42., 42.])
        verify_no_input(model, tmpdir, 'Greater_0')

#GRU
@pytest.mark.parametrize("dtype", DType_Config)
def test_GRU(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        def MakeGRUNameFromConfig(backward, initial_state, activition):
            model_name = 'GRU.' + activition.__name__
            if (initial_state != 0):
                model_name += '.initial'
            if (backward):
                model_name += '.backward'
            else:
                model_name += '.forward'
            return model_name

        direction_options = [False, True]
        activation_options = [C.tanh]
        initial_state_options = [0]

        input_dim = 2
        cell_dim = 3
        batch_size = 1
        sequence_len = 5

        for config in list(product(direction_options, initial_state_options, activation_options)):
            model_filename = MakeGRUNameFromConfig(*config)
            print(model_filename)
            backward, initial_state, activation =  config

            x = C.input_variable(input_dim, dynamic_axes=[C.Axis.default_batch_axis(), C.Axis('sequenceAxis')])
            GRUModel = C.layers.Recurrence(C.layers.GRU(cell_dim,
                                                        activation = activation),
                                           initial_state = initial_state,
                                           go_backwards=backward)(x)
            data = np.random.uniform(low=0.0, high=1.0, size=(batch_size, sequence_len, input_dim)).astype('f')
            verify_one_input(GRUModel, data, tmpdir, model_filename)

#Hardmax
@pytest.mark.parametrize("dtype", DType_Config)
def test_Hardmax(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.asarray([1., 1., 2., 3.], dtype=dtype)
        model = C.hardmax(data)
        verify_no_input(model, tmpdir, 'Hardmax_0')

#HardSigmiod
@pytest.mark.parametrize("dtype", DType_Config)
def test_HardSigmiod(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        shape = (2,3)
        x = C.input_variable(shape=shape, dtype=dtype)
        alpha = 1.2
        beta = 2.5
        model = C.hard_sigmoid(x, alpha, beta, 'hardSigmoid')

        data = np.random.rand(*shape).astype(dtype)
        verify_one_input(model, data, tmpdir, 'HardSigmoid_1')

#ImageScaler
@pytest.mark.parametrize("dtype", DType_Config)
def test_ImageScaler(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        input_height = 32
        input_width = 32
        channels = 3
        image = np.ones([channels, input_height, input_width]).astype(dtype)
        scalar = 1.5
        bias = [10, 20, 30]

        model = C.image_scaler(image, scalar, bias);
        verify_no_input(model, tmpdir, 'ImageScaler_0')

        x = C.input_variable(np.shape(image))
        model = C.image_scaler(x, scalar, bias);
        verify_one_input(model, image, tmpdir, 'ImageScaler_1')

#LayerNormalization
@pytest.mark.parametrize("dtype", DType_Config)
def test_LayerNormalization(tmpdir, dtype):
    if (dtype == np.float16):
        pytest.skip("TO BE FIXED")

    # This test point tests the LayerNormalization round trip with defaultepsilon. We loose always the epsilon value when
    # exporting to ONNX (because ONNX MeanVarianceNormalization does not have an epsilon attribute). When loading back
    # from ONNX, CNTK always uses the default eposilon value (0.00001). That's why test below has the default epsilon
    # value. It is not expected to pass with any other epsilon value until something changes.
    with C.default_options(dtype = dtype):
        test_shapes = [(3, 5, 7), (10, ), (20, 31)]
        for shape in test_shapes:
            data = np.reshape(np.arange(np.prod(shape), dtype = dtype), shape)
            input_operand = C.input_variable(shape=shape)
            model0 = C.layers.LayerNormalization(initial_scale=1, initial_bias=2, epsilon=0.00001)(input_operand)
            verify_one_input(model0, data, tmpdir, 'LayerNorm_0')

        # This test point tests especially with epsilon = 0, because that creates a graph with
        # different number of ops. However, we don't expect the numbers to match in round trip
        # because we only support default epislon (0.00001) when loading from ONNX. Therefore,
        # this is just a load/save test.
        model1 = C.layers.LayerNormalization(epsilon=0.0)(input_operand)
        filename = os.path.join(str(tmpdir), R'LayerNorm_1.onnx')
        model1.save(filename, format=C.ModelFormat.ONNX)
        loaded_model = C.Function.load(filename, format=C.ModelFormat.ONNX)
        assert model1.shape == loaded_model.shape

#LeakyRelu
@pytest.mark.parametrize("dtype", DType_Config)
def test_LeakyRelu(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.asarray([[-1, -0.5, 0, 1, 2]], dtype=dtype)
        model = C.leaky_relu(data)
        verify_no_input(model, tmpdir, 'LeakyRelu_0')

#Less
@pytest.mark.parametrize("dtype", DType_Config)
def test_Less(tmpdir, dtype):
    if (dtype == np.float16):
        pytest.skip("TO BE FIXED")

    with C.default_options(dtype = dtype):
        data0 = np.asarray([41., 42., 43.], dtype=dtype)
        data1 = np.asarray([42., 42., 42.], dtype=dtype)

        model = C.less(data0, data1)
        verify_no_input(model, tmpdir, 'Less_0')

#Log
@pytest.mark.parametrize("dtype", DType_Config)
def test_Log(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.asarray([1., 2.], dtype=dtype)
        model = C.log(data)
        verify_no_input(model, tmpdir, 'Log_0')

#LogSoftmax
@pytest.mark.parametrize("dtype", DType_Config)
def test_LogSoftmax(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        model = C.log_softmax(np.array([[1, 1, 2, 3]]).astype(dtype))
        verify_no_input(model, tmpdir, 'LogSoftmax_0')

#LRN
@pytest.mark.parametrize("dtype", DType_Config)
def test_LRN(tmpdir, dtype, device_id):
    if device_id == -1 and dtype == np.float16:
        pytest.skip('Test is skipped on CPU with float16 data, because it uses convolution.')
    device = cntk_device(device_id)
    with C.default_options(dtype=dtype):
        img_shape = (64, 32, 32)
        img = np.asarray(np.random.uniform(-1, 1, img_shape), dtype=dtype)
        x_r = C.input_variable(shape=img_shape, dtype=dtype)
        model = C.local_response_normalization(x_r, 2, 1.0, 0.0001, 0.75)
        verify_one_input(model, img, tmpdir, 'LRN_1', device)

#LSTM
@pytest.mark.parametrize("dtype", DType_Config)
def test_LSTM(tmpdir, dtype):

    with C.default_options(dtype = dtype):
        def CreateLSTMModel(activation,
                            peepholes,
                            self_stabilization,
                            cell_dim,
                            initial_state):
            return C.layers.Sequential([
                C.layers.Recurrence(C.layers.LSTM(cell_dim,
                                                  use_peepholes = peepholes,
                                                  activation = activation,
                                                  enable_self_stabilization = self_stabilization),
                                    initial_state = initial_state)
                ])

        def MakeLSTMNameFromConfig(use_peepholes, enable_self_stabilization, initial_state, activition):
            model_name = 'LSTM.' + activition.__name__
            if (use_peepholes):
                model_name += '.peephole'
            if(enable_self_stabilization):
                model_name += '.stabilize'
            if (initial_state != 0):
                model_name += '.initial'
            return model_name

        # lstm attributes
        use_peepholes_options = [False]
        enable_self_stabilization_options = [False]
        activation_options = [C.tanh]

        #Recurrence attributes
        initial_state_options = [0, 0.23]

        input_dim = 2
        cell_dim = 3
        batch_size = 1
        sequence_len = 5

        for config in list(product(use_peepholes_options, enable_self_stabilization_options,
                                   initial_state_options, activation_options)):
            model_filename = MakeLSTMNameFromConfig(*config)
            use_peepholes, enable_self_stabilization, initial_state, activation =  config

            x = C.input_variable(input_dim, dynamic_axes=[C.Axis.default_batch_axis(), C.Axis('sequenceAxis')])
            LSTMmodel = CreateLSTMModel(peepholes = use_peepholes,
                                        activation = activation,
                                        initial_state = initial_state,
                                        cell_dim = cell_dim,
                                        self_stabilization = enable_self_stabilization)(x)
            data = np.random.uniform(low=0.0, high=1.0, size=(batch_size, sequence_len, input_dim)).astype('f')
            verify_one_input(LSTMmodel, data, tmpdir, model_filename)

#MatMul
@pytest.mark.parametrize("dtype", DType_Config)
def test_MatMul(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data0 = np.asarray([[1,2],[3,4]], dtype=dtype)
        data1 = np.asarray([[5],[6]], dtype=dtype)
        model = C.times(data0, data1)
        verify_no_input(model, tmpdir, 'MatMul_0')

#Max
@pytest.mark.parametrize("dtype", DType_Config)
def test_Max(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data0 = np.asarray([1., 1., 1., 1.], dtype=dtype)
        data1 = np.asarray([0.5, 0.25, 0.125, 0.], dtype=dtype)
        model = C.element_max(data0, data1)
        verify_no_input(model, tmpdir, 'Max_0')

#MaxPool
@pytest.mark.parametrize("dtype", DType_Config)
def test_MaxPool(tmpdir, dtype, device_id):
    if device_id == -1 and dtype == np.float16:
        pytest.skip('Test is skipped on CPU with float16 data')
    device = cntk_device(device_id)
    with C.default_options(dtype=dtype):
        img = np.reshape(np.arange(16, dtype = dtype), [1, 4, 4])
        x = C.input_variable(img.shape)
        model = C.pooling(x, C.MAX_POOLING, (2,2), (3,3))
        verify_one_input(model, img, tmpdir, 'MaxPool_1', device)

#MaxRoiPool
@pytest.mark.parametrize("dtype", DType_Config)
def test_MaxRoiPool(tmpdir, dtype):
    pytest.skip('MaxRoiPool is failing with ONNX shape inference (input rois). RuntimeError: [ShapeInferenceError] RoIs tensor must have 2 dimensions')
    with C.default_options(dtype = dtype):
        input_map = [[[1., 2., 3.],       # (1, 3, 3) input operand (conv feature map)
               [4., 5., 6.],
               [7., 8., 9.]]]
        input_rois = [[1, 1, 2, 2]]

        conv_input = np.asarray(input_map, dtype=dtype)
        roi_input = np.asarray(input_rois, dtype=dtype)

        a = C.input_variable(shape=conv_input.shape,
                    dtype=dtype,
                    needs_gradient=True,
                    name='a')

        b = C.input_variable(shape=roi_input.shape,
                    dtype=dtype,
                    needs_gradient=False,
                    name='b')

        # adding batch and sequence axis
        conv_input.shape     = (1,) + conv_input.shape
        roi_input.shape      = (1,) + roi_input.shape

        model = C.roipooling(a, b, C.MAX_POOLING, (3,3), 1.)

        verify_two_input(model, conv_input, roi_input, tmpdir, 'MaxRoiPool_1')

#Mean
@pytest.mark.parametrize("dtype", DType_Config)
def test_Mean(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        in1 = C.input_variable((4,))
        in2 = C.input_variable((4,))
        model = C.mean([in1, in2])

        in1_data = np.asarray([[1., 2., 3., 4.]], dtype = dtype)
        in2_data = np.asarray([[0., 5., -3., 2.]], dtype = dtype)

        verify_two_input(model, in1_data, in2_data, tmpdir, 'Mean_2')

#MeanVarianceNormalization
@pytest.mark.parametrize("dtype", DType_Config)
def test_MeanVarianceNormalization(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        shape = (3, 5, 7)
        data = np.reshape(np.arange(np.prod(shape), dtype = dtype), shape)

        input_operand = C.input_variable(shape=shape)

        model0 = C.mean_variance_normalization(input_operand, use_stats_across_channels=False, do_variance_scaling=True)
        verify_one_input(model0, data, tmpdir, 'MVN_0')

        model1 = C.mean_variance_normalization(input_operand, use_stats_across_channels=False, do_variance_scaling=False)
        verify_one_input(model1, data, tmpdir, 'MVN_1')

        model2 = C.mean_variance_normalization(input_operand, use_stats_across_channels=True, do_variance_scaling=True)
        verify_one_input(model2, data, tmpdir, 'MVN_2')

        # The test below tests the round trip with epsilon. We loose always the epsilon value when exporting to ONNX
        # (because ONNX MeanVarianceNormalization does not have an epsilon attribute). When loading back from ONNX, CNTK
        # always uses the default eposilon value (0.00001). That's why test below has the default epsilon value. It is
        # not expected to pass with any other epsilon value until something changes.
        model3 = C.mean_variance_normalization(input_operand, epsilon=0.00001, use_stats_across_channels=False, do_variance_scaling=True)
        verify_one_input(model3, data, tmpdir, 'MVN_3')

#Min
@pytest.mark.parametrize("dtype", DType_Config)
def test_Min(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data0 = np.asarray([1., 1., 1., 1.], dtype=dtype)
        data1 = np.asarray([0.5, 0.25, 0.125, 0.], dtype=dtype)
        model = C.element_min(data0, data1)
        verify_no_input(model, tmpdir, 'Min_0')

#Mul
@pytest.mark.parametrize("dtype", DType_Config)
def test_Mul(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data0 = np.asarray([1., 1., 1., 1.], dtype=dtype)
        data1 = np.asarray([0.5, 0.25, 0.125, 0.], dtype=dtype)
        model = C.element_times(data0, data1)
        verify_no_input(model, tmpdir, 'ElementTimes_0')

#Neg
@pytest.mark.parametrize("dtype", DType_Config)
def test_Neg(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data0 = np.asarray([1., -1., -2., 1.], dtype=dtype)
        model = C.negate(data0)
        verify_no_input(model, tmpdir, 'Neg_0')

#OptimizedRNNStack
OPTIM_RNN_STACK_CONFIGS = ((True, 1, 2, 3, 'lstm'), (False, 1, 4, 8, 'lstm'),
                           (True, 2, 2, 3, 'lstm'), (True, 2, 4, 8, 'lstm'), (True, 2, 6, 8, 'lstm'),
                           (True, 4, 2, 3, 'lstm'), (False, 2, 2, 3, 'lstm'), (False, 2, 6, 8, 'lstm'), (False, 4, 4, 8, 'lstm'),
                           (True, 1, 2, 3, 'rnnReLU'), (True, 4, 4, 8, 'rnnReLU'), (False, 2, 6, 8, 'rnnReLU'),
                           (True, 4, 2, 3, 'rnnTanh'), (False, 2, 2, 3, 'rnnTanh'), (True, 1, 2, 3, 'rnnTanh'))
@pytest.mark.parametrize("bidirectional, num_layers, input_size, hidden_size, recurrent_op", OPTIM_RNN_STACK_CONFIGS)
def test_OptimizedRNNStack(bidirectional, num_layers, input_size, hidden_size, recurrent_op, tmpdir, device_id):
    pytest.skip('Need to support new ONNX spec.')
    if device_id == -1:
        pytest.skip('Test only runs on GPU')
    dev = cntk_device(device_id)
    from _cntk_py import constant_initializer
    model_filename = 'optimized_rnn_stack_' + ('bi' if bidirectional else 'uni') + '_layers' + str(num_layers) + '_inp' + str(input_size) + '_hid' + str(hidden_size)
    W = C.parameter((C.InferredDimension, input_size), constant_initializer(0.1), device=dev)
    x = C.sequence.input_variable(shape=(input_size,))
    s = np.asarray(np.random.uniform(-1, 1, (5,input_size)), dtype=np.float32)
    f = C.optimized_rnnstack(x, W, hidden_size, num_layers, bidirectional=bidirectional, recurrent_op=recurrent_op, name='MyRnnStack')
    f.parameters[0].value = np.reshape(np.arange(np.prod(f.parameters[0].value.shape), dtype=np.float32), f.parameters[0].value.shape)
    verify_one_input(f, s, tmpdir, model_filename)

#Pad
@pytest.mark.parametrize("dtype", DType_Config)
def test_Pad(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        shape = (4, 5)
        data = np.random.rand(*shape).astype(dtype)

        model = C.pad(data, pattern=[(1,1),(2,2)], mode=C.ops.CONSTANT_PAD, constant_value=1)
        verify_no_input(model, tmpdir, 'Pad_0')

        x = C.input_variable(shape)
        model = C.pad(x, pattern=[(1,1),(2,2)], mode=C.ops.REFLECT_PAD)

        verify_one_input(model, data, tmpdir, 'Pad_1')

#PRelu
#def test_PRelu(tmpdir):
#    data = np.asarray([[-1, -0.5, 0, 1, 2]])
#    alpha = C.constant(value=[[0.5, 0.5, 0.5, 0.5, 0.5]])
#    model = C.param_relu(alpha, data)
#    verify_no_input(model, tmpdir, 'PRelu_0')

#Pow
@pytest.mark.parametrize("dtype", DType_Config)
def test_Pow(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        model = C.pow(np.array([1, 2, -2]).astype(dtype), np.array([3, -2, 3]).astype(dtype))
        verify_no_input(model, tmpdir, 'Pow_0')

#Reciprocal
@pytest.mark.parametrize("dtype", DType_Config)
def test_Reciprocal(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        model = C.reciprocal(np.array([-1/3, 1/5, -2, 3]).astype(dtype))
        verify_no_input(model, tmpdir, 'Reciprocal_0')

@pytest.mark.parametrize("dtype", DType_Config)
def test_ReduceL1(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.array([[[1,2], [3,4]],[[5,6], [7,8]],[[9,10], [11,12]]], dtype=dtype)
        model = C.reduce_l1(data, 1)
        verify_no_input(model, tmpdir, 'ReduceL1_0')

        x = C.input_variable(np.shape(data))
        model = C.reduce_l1(x, 1)
        verify_one_input(model, data, tmpdir, 'ReduceL1_1')

@pytest.mark.parametrize("dtype", DType_Config)
def test_ReduceL2(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.array([[[1,2], [3,4]],[[5,6], [7,8]],[[9,10], [11,12]]], dtype=dtype)
        model = C.reduce_l2(data, 0)
        verify_no_input(model, tmpdir, 'ReduceL2_0')

@pytest.mark.parametrize("dtype", DType_Config)
def test_ReduceSumSquare(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.array([[[1,2], [3,4]],[[5,6], [7,8]],[[9,10], [11,12]]], dtype=dtype)
        model = C.reduce_sum_square(data, 0)
        verify_no_input(model, tmpdir, 'ReduceSumSquare_0')

#ReduceLogSum
@pytest.mark.parametrize("dtype", DType_Config)
def test_ReduceLogSum(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.array([[[5,1], [20,2]],[[30,1], [40,2]],[[55,1], [60,2]]], dtype=dtype)
        model = C.reduce_log_sum_exp(data, axis=0)

    verify_no_input(model, tmpdir, 'ReduceLogSum_0')

#ReduceMax
@pytest.mark.parametrize("dtype", DType_Config)
def test_ReduceMax(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.array([[[5,1], [20,2]],[[30,1], [40,2]],[[55,1], [60,2]]], dtype=dtype)
        model = C.reduce_max(data, 0)
        verify_no_input(model, tmpdir, 'ReduceMax_0')

#ReduceMean
@pytest.mark.parametrize("dtype", DType_Config)
def test_ReduceMean(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.array([[[5,1], [20,2]],[[30,1], [40,2]],[[55,1], [60,2]]], dtype=dtype)
        model = C.reduce_mean(data, 0)
        verify_no_input(model, tmpdir, 'ReduceMean_0')

#ReduceMin
@pytest.mark.parametrize("dtype", DType_Config)
def test_ReduceMin(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.array([[[5,1], [20,2]],[[30,1], [40,2]],[[55,1], [60,2]]], dtype=dtype)
        model = C.reduce_min(data, 0)
        verify_no_input(model, tmpdir, 'ReduceMin_0')

#ReduceProd
@pytest.mark.parametrize("dtype", DType_Config)
def test_ReduceProd(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.array([[[5,1], [20,2]],[[30,1], [40,2]],[[55,1], [60,2]]], dtype=dtype)
        model = C.reduce_prod(data, 0)
        verify_no_input(model, tmpdir, 'ReduceProd_0')

#ReduceSum
@pytest.mark.parametrize("dtype", DType_Config)
def test_ReduceSum(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.array([[[5,1], [20,2]],[[30,1], [40,2]],[[55,1], [60,2]]], dtype=dtype)
        model = C.reduce_sum(data, 0)
        verify_no_input(model, tmpdir, 'ReduceSum_0')

#Relu
@pytest.mark.parametrize("dtype", DType_Config)
def test_Relu(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.array([[-1, -0.5, 0, 1, 2]], dtype = dtype)
        model = C.relu(data)
        verify_no_input(model, tmpdir, 'Relu_0')

#Reshape
@pytest.mark.parametrize("dtype", DType_Config)
def test_Reshape(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.asarray([[[[0., 1.],[2., 3.],[4., 5.]]]], dtype=dtype)
        i1 = C.input_variable(shape=(3,2))
        model = C.reshape(i1, (2,3))
        verify_one_input(model, data, tmpdir, 'Reshape_1')

#RNN
@pytest.mark.parametrize("dtype", DType_Config)
def test_RNN(tmpdir, dtype):

    with C.default_options(dtype = dtype):
        def CreatRNN(cell_dim,
                     activation,
                     initial_state,
                     direction,
                     num_layers,
                     init=C.default_override_or(C.glorot_uniform()),
                     init_bias=C.default_override_or(0)):
            if direction == 'bidirectional':
                return C.layers.Sequential([
                    C.layers.For(range(num_layers), lambda i: [
                        (C.layers.Recurrence(C.layers.RNNStep(cell_dim,
                                                              activation = activation,
                                                              init = init,
                                                              init_bias = init_bias),
                                    initial_state = initial_state,
                                    return_full_state = False, go_backwards=False),
                         C.layers.Recurrence(C.layers.RNNStep(cell_dim, activation = activation,
                                        init = init,
                                        init_bias = init_bias),
                                    initial_state = initial_state,
                                    return_full_state = False, go_backwards=True)),
                        C.splice])])
            else:
                go_backward = False if direction == 'forward' else True
                return C.layers.Sequential([
                    C.layers.For(range(num_layers), lambda i: [
                        C.layers.Recurrence(C.layers.RNNStep(cell_dim,
                                                             activation = activation,
                                        init = init,
                                        init_bias = init_bias),
                                    initial_state = initial_state,
                                    return_full_state = False, go_backwards=go_backward)])])

        def MakeRNNNameFromConfig(direction, num_layers, initial_state, activition):
            model_name = 'RNN.' + direction + '.'

            if num_layers == 1:
                model_name += 'one_layer.'
            else:
                assert (num_layers == 2), "needs 1 or 2 layers!"
                model_name += 'two_layer.'

            if (initial_state != 0):
                model_name += 'initial.'

            model_name += activition.__name__
            return model_name

        direction_options = ['forward', 'reverse', 'bidirectional']
        num_layers_options = [1, 2]
        initial_state_options = [0]
        activation_options = [C.tanh, C.relu, C.sigmoid]

        input_dim = 2
        hidden_dim = 3
        batch_size = 1
        sequence_len = 5

        for config in list(product(direction_options, num_layers_options, initial_state_options, activation_options)):
            model_filename = MakeRNNNameFromConfig(*config)
            print(model_filename)
            direction, num_layers, initial_state, activation = config

            x = C.input_variable(input_dim, dynamic_axes=[C.Axis.default_batch_axis(), C.Axis('sequenceAxis')])
            RNNModel = CreatRNN(
                hidden_dim,
                activation,
                initial_state,
                direction,
                num_layers)(x)
            data = np.random.uniform(low=0.0, high=1.0, size=(batch_size, sequence_len, input_dim)).astype(dtype)
            verify_one_input(RNNModel, data, tmpdir, model_filename)

#Selu
@pytest.mark.parametrize("dtype", DType_Config)
def test_Selu(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        model = C.selu(np.array([[-1, -0.5, 0, 1, 2]]).astype(dtype))
        verify_no_input(model, tmpdir, 'Selu_0')

#Sigmoid
@pytest.mark.parametrize("dtype", DType_Config)
def test_Sigmoid(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        model = C.sigmoid(np.array([-2, -1., 0., 1., 2.]).astype(dtype))
        verify_no_input(model, tmpdir, 'Sigmoid_0')

#Slice
@pytest.mark.parametrize("dtype", DType_Config)
def test_Slice(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.asarray([[1,2,-3], [4, 5, 6]],dtype=dtype)
        x1 = C.input_variable((2,3))

        model = C.slice(data, 0, 1, 2)
        verify_no_input(model, tmpdir, 'Slice_0')

        model = C.slice(x1, 0, 1, 2)
        verify_one_input(model, data, tmpdir, 'Slice_1')

        model = C.slice(x1, [0,1], [1,0], [2,1]);
        verify_one_input(model, data, tmpdir, 'Slice2_1')

#Softmax
@pytest.mark.parametrize("dtype", DType_Config)
def test_Softmax(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        model = C.softmax(np.array([[1, 1, 2, 3]]).astype(dtype))
        verify_no_input(model, tmpdir, 'Softmax_0')

#Softplus
@pytest.mark.parametrize("dtype", DType_Config)
def test_Softplus(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        model = C.softplus([[-1, -0.5, 0, 1, 2]])
        verify_no_input(model, tmpdir, 'Softplus_0')

#Softsign
@pytest.mark.parametrize("dtype", DType_Config)
def test_Softsign(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        model = C.softsign(np.array([[-1, -0.5, 0, 1, 2]]).astype(dtype))
        verify_no_input(model, tmpdir, 'Softsign_0')

#Squeeze
#def test_Squeeze(tmpdir):
#    x0 = np.arange(12).reshape((2, 2, 1, 3)).astype('f')
#    x = C.input_variable((2, 1, 3))
#    model = C.squeeze(x)
#    verify_one_input(model, x0, tmpdir, 'Squeeze_0')

#Sum
@pytest.mark.parametrize("dtype", DType_Config)
def test_Sum(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        in1_data = np.asarray([[1., 2., 3., 4.]], dtype = dtype)
        in2_data = np.asarray([[0., 5., -3., 2.]], dtype = dtype)

        in1 = C.input_variable(np.shape(in1_data))
        in2 = C.input_variable(np.shape(in2_data))
        model = C.sum([in1, in2])

        verify_two_input(model, in1_data, in2_data, tmpdir, 'Sum_2')

# SpaceToDepth
@pytest.mark.parametrize("dtype", DType_Config)
def test_SpaceToDepth(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        num_channels = 3
        block_size = 3
        image_shape = (12, 15)
        input_val = np.array(np.reshape(range(num_channels), (num_channels, 1, 1)), dtype=dtype)
        input_val = np.tile(input_val, (1,) + image_shape)
        input_val.shape = (1,) + input_val.shape
        img = C.input_variable((num_channels,) + image_shape, dtype=dtype)
        model = C.space_to_depth(img, block_size)

        verify_one_input(model, input_val, tmpdir, 'SpaceToDepth')

#Sqrt
@pytest.mark.parametrize("dtype", DType_Config)
def test_Sqrt(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        model = C.sqrt(np.array([0., 4.]).astype(dtype))
        verify_no_input(model, tmpdir, 'Sqrt_0')

#Sub
@pytest.mark.parametrize("dtype", DType_Config)
def test_Sub(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        model = C.minus(np.array([1, 2, 3]).astype(dtype), np.array([4, 5, 6]).astype(dtype))
        verify_no_input(model, tmpdir, 'Sub_0')

#Tanh
@pytest.mark.parametrize("dtype", DType_Config)
def test_Tanh(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        model = C.tanh(np.array([[1,2],[3,4]]).astype(dtype))
        verify_no_input(model, tmpdir, 'Tanh_0')

#Transpose
@pytest.mark.parametrize("dtype", DType_Config)
def test_Transpose(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.arange(24).reshape(2,3,4).astype(dtype)
        x = C.input_variable(np.shape(data))

        model = C.transpose(data, perm=(2, 0, 1))
        verify_no_input(model, tmpdir, 'Transpose_0')

        model = C.transpose(x, perm=(2, 0, 1))
        verify_one_input(model, data, tmpdir, 'Transpose_1')

        model = C.transpose(x, perm=(0, 2, 1))
        verify_one_input(model, data, tmpdir, 'Transpose_1_2')

#Transpose
@pytest.mark.parametrize("dtype", DType_Config)
def test_TransposeAxes(tmpdir, dtype):
    with C.default_options(dtype = dtype):
        data = np.array([[[0,1],[2,3],[4,5]]]).astype(dtype)
        model = C.swapaxes(data, 1, 2)
        verify_no_input(model, tmpdir, 'TransposeAxes_0')

    # TODO: there is probably a bug in C.swapaxes which does not allow
    # evaluation of model with data
    #x = C.input_variable(np.shape(data))
    #model = C.swapaxes(x, 1, 2)
    #verify_one_input(model, data, tmpdir, 'TransposeAxes_1')

# Select
@pytest.mark.parametrize("flag, if_true, if_false", (
    ((-100., -1.2, -1.0, -0.5, 0.0, 0.1, 1.0, 100.),
     (1., 2., 3., 4., 5., 6., 7., 8.),
     (11., 12., 13., 14., 15., 16., 17., 18.)),
    (((1, 0, 3), (4, 5, 0)),
     ((1, 2, 3), (4, 5, 6)),
     ((-1, -2, -3), (-4, -5, -6))),
    ((((0, 1), (0, 1)), ((0, 1), (0, 1))),
     (((1, 2), (3, 4)), ((5, 6), (7, 8))),
     (((9, 10), (11, 12)), ((13, 14), (15, 16)))),
))
def test_Select(flag, if_true, if_false, tmpdir):
    flag = np.asarray(flag, dtype=np.float32)
    if_true = np.asarray(if_true, dtype=np.float32)
    if_false = np.asarray(if_false, dtype=np.float32)

    model = C.element_select(flag, if_true, if_false)
    verify_no_input(model, tmpdir, 'Select_0')

    flag_var = C.input_variable(np.shape(flag))
    if_true_var = C.input_variable(np.shape(if_true))
    if_false_var = C.input_variable(np.shape(if_false))

    model = C.element_select(flag_var, if_true, if_false)
    verify_one_input(model, flag, tmpdir, 'Select_1_flag')

    model = C.element_select(flag, if_true_var, if_false)
    verify_one_input(model, if_true, tmpdir, 'Select_1_if_true')

    model = C.element_select(flag, if_true, if_false_var)
    verify_one_input(model, if_false, tmpdir, 'Select_1_if_false')

# Cos
@pytest.mark.parametrize("dtype", DType_Config)
def test_Cos(tmpdir, dtype):
    data = np.asarray([0.0, -0.5, 0.5, 10, 20], dtype)
    model = C.cos(data)
    verify_no_input(model, tmpdir, 'Cos_0')

# Sin
@pytest.mark.parametrize("dtype", DType_Config)
def test_Sin(tmpdir, dtype):
    data = np.asarray([0.0, -0.5, 0.5, 10, 20], dtype)
    model = C.sin(data)
    verify_no_input(model, tmpdir, 'Sin_0')

# Tan
@pytest.mark.parametrize("dtype", DType_Config)
def test_Tan(tmpdir, dtype):
    data = np.asarray([0.0, -0.5, 0.5, 10, 20], dtype)
    model = C.tan(data)
    verify_no_input(model, tmpdir, 'Tan_0')

# Acos
@pytest.mark.parametrize("dtype", DType_Config)
def test_Acos(tmpdir, dtype):
    data = np.asarray([0.0, -0.5, 0.5, 1, -1], dtype)
    model = C.acos(data)
    verify_no_input(model, tmpdir, 'Acos_0')

# Asin
@pytest.mark.parametrize("dtype", DType_Config)
def test_Asin(tmpdir, dtype):
    data = np.asarray([0.0, -0.5, 0.5, 1, -1], dtype)
    model = C.asin(data)
    verify_no_input(model, tmpdir, 'Asin_0')

# Atan
@pytest.mark.parametrize("dtype", DType_Config)
def test_Atan(tmpdir, dtype):
    data = np.asarray([0.0, -0.5, 0.5, 1, -1], dtype)
    model = C.atan(data)
    verify_no_input(model, tmpdir, 'Atan_0')

max_stars_repo_name: Surfndez/CNTK

max_issues_repo_name: tjrileywisc/CNTK

max_forks_repo_name: tjrileywisc/CNTK


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

from sklearn import tree
import pickle
import base64
import numpy as np
import argparse

from singa_auto.model import BaseModel, IntegerKnob, CategoricalKnob, utils
from singa_auto.constants import ModelDependency
from singa_auto.model.dev import test_model_class

class SkDt(BaseModel):
    '''
    Implements a decision tree classifier on Scikit-Learn for IMAGE_CLASSIFICATION
    '''
    @staticmethod
    def get_knob_config():
        return {
            'max_depth': IntegerKnob(1, 32),
            'splitter': CategoricalKnob(['best', 'random']),
            'criterion': CategoricalKnob(['gini', 'entropy']),
            'max_image_size': CategoricalKnob([16, 32])
        }

    def __init__(self, **knobs):
        self.__dict__.update(knobs)
        self._clf = self._build_classifier(self.max_depth, self.criterion, self.splitter)

    def train(self, dataset_path, **kwargs):
        dataset = utils.dataset.load_dataset_of_image_files(dataset_path, max_image_size=self.max_image_size, mode='L')
        self._image_size = dataset.image_size
        (images, classes) = zip(*[(image, image_class) for (image, image_class) in dataset])
        X = self._prepare_X(images)
        y = classes
        self._clf.fit(X, y)

        # Compute train accuracy
        preds = self._clf.predict(X)
        accuracy = sum(y == preds) / len(y)
        utils.logger.log('Train accuracy: {}'.format(accuracy))

    def evaluate(self, dataset_path):
        dataset = utils.dataset.load_dataset_of_image_files(dataset_path, max_image_size=self.max_image_size, mode='L')
        (images, classes) = zip(*[(image, image_class) for (image, image_class) in dataset])
        X = self._prepare_X(images)
        y = classes
        preds = self._clf.predict(X)
        accuracy = sum(y == preds) / len(y)
        return accuracy

    def predict(self, queries):
        queries = utils.dataset.transform_images(queries, image_size=self._image_size, mode='L')
        X = self._prepare_X(queries)
        probs = self._clf.predict_proba(X)
        return probs.tolist()

    def dump_parameters(self):
        params = {}

        # Put model parameters
        clf_bytes = pickle.dumps(self._clf)
        clf_base64 = base64.b64encode(clf_bytes).decode('utf-8')
        params['clf_base64'] = clf_base64

        # Put image size
        params['image_size'] = self._image_size

        return params

    def load_parameters(self, params):
        # Load model parameters
        clf_base64 = params['clf_base64']
        clf_bytes = base64.b64decode(clf_base64.encode('utf-8'))
        self._clf = pickle.loads(clf_bytes)

        # Load image size
        self._image_size = params['image_size']

    def _prepare_X(self, images):
        return [np.asarray(image).flatten() for image in images]

    def _build_classifier(self, max_depth, criterion, splitter):
        clf = tree.DecisionTreeClassifier(
            max_depth=max_depth,
            criterion=criterion,
            splitter=splitter
        )
        return clf

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--train_path', type=str, default='data/fashion_mnist_train.zip', help='Path to train dataset')
    parser.add_argument('--val_path', type=str, default='data/fashion_mnist_val.zip', help='Path to validation dataset')
    parser.add_argument('--test_path', type=str, default='data/fashion_mnist_test.zip', help='Path to test dataset')
    parser.add_argument('--query_path', type=str, default='examples/data/image_classification/fashion_mnist_test_1.png',
                        help='Path(s) to query image(s), delimited by commas')
    (args, _) = parser.parse_known_args()

    queries = utils.dataset.load_images(args.query_path.split(',')).tolist()
    test_model_class(
        model_file_path=__file__,
        model_class='SkDt',
        task='IMAGE_CLASSIFICATION',
        dependencies={
            ModelDependency.SCIKIT_LEARN: '0.20.0'
        },
        train_dataset_path=args.train_path,
        val_dataset_path=args.val_path,
        test_dataset_path=args.test_path,
        queries=queries

    )

max_stars_repo_name: FeynmanDNA/singa-auto

max_issues_repo_name: FeynmanDNA/singa-auto

max_forks_repo_name: FeynmanDNA/singa-auto


text:
import os
import unittest
import torch

import time
import timeit
import numpy as np
import nibabel as nib

from deeds_libtorch.mind_ssc import mind_ssc, filter1D

from __init__ import SRC_DIR, BUILD_DIR, BUILD_JIT_DIR, CPP_DEEDS_MODULE, test_equal_tensors, log_wrapper, mind_compress_features, mind_extract_features, mind_twelve_to_long, mind_long_to_twelve

def extract_features(binaries):
    D,H,W,DIGITS = binaries.shape
    sums = torch.empty((D,H,W,12))
    for feature_idx, d_start_idx in enumerate(range(0,DIGITS,5)):
        sums[...,feature_idx] = binaries[..., d_start_idx:d_start_idx+5].sum(dim=-1)
    return sums

class TestMindSsc(unittest.TestCase):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def test_mind_ssc(self):

        #########################################################
        # Prepare inputs
        QUANTISATION_STEP = 1
        D, H, W =  5, 5, 5

        ## Generate some artificial displacements for x,y,z
        image = torch.ones((D,H,W))
        image[1,1,1] = 2
        image[2,2,2] = -1
        #########################################################
        # Get cpp output
        cpp_mind_ssc_long_long, cpp_mind_ssc_twelve, mind_bare = CPP_DEEDS_MODULE.mind_ssc_descriptor(
            image,
            torch.tensor([QUANTISATION_STEP], dtype=torch.int)
        )
        cpp_mind = mind_long_to_twelve(cpp_mind_ssc_long_long)

        #########################################################
        # Get torch output
        torch_mind_ssc = mind_ssc(image, QUANTISATION_STEP, use_smoothing=False, sigma=0.8, compensation_factor=5.)
        torch_mind_ssc = torch_mind_ssc.reshape(12,D,H,W)

        #########################################################
        # Assert difference
        assert test_equal_tensors(cpp_mind_ssc, torch_mind_ssc)

if __name__ == '__main__':
    # unittest.main()
    tests = TestMindSsc()
    tests.test_mind_ssc()

max_stars_repo_name: MDL-UzL/deeds-libtorch

max_issues_repo_name: MDL-UzL/deeds-libtorch

max_forks_repo_name: MDL-UzL/deeds-libtorch


text:
"""
The datasets module includes a number of standard VAE datasets in the style of the torchvision.datasets module.
"""
import os
import shutil
import zipfile

import numpy as np
from PIL import Image
from torch.utils.data import Dataset

def make_dataset(dir, extensions):
    from torchvision.datasets.folder import has_file_allowed_extension
    images = []
    for root, _, fnames in sorted(os.walk(dir)):
        for fname in sorted(fnames):
            if has_file_allowed_extension(fname, extensions):
                path = os.path.join(root, fname)
                item = path
                images.append(item)
    return images

class SimpleImageFolder(Dataset):
    """
    Simple image folder dataset that loads all images from inside a folder and returns items in (image, image) tuple

    Args:
        root (str): Root directory of dataset containing all aligned images
        loader (function, optional): Image loader function that takes a file or path and returns the loaded image (see torchvision.datasets.folder)
        extensions (:obj:`list` of :obj:`str`, optional): List of file extensions that can be loaded
        transform (``Transform``, optional): A function/transform that takes in an PIL image and returns a transformed version. E.g, ``transforms.RandomCrop``
        target_transform (``Transform``, optional): A function/transform that takes in an PIL image and returns a transformed version. E.g, ``transforms.RandomCrop``
    """
    def __init__(self, root, loader=None, extensions=None, transform=None, target_transform=None):
        from torchvision.datasets.folder import default_loader, IMG_EXTENSIONS
        loader = default_loader if loader is None else loader
        extensions = IMG_EXTENSIONS if extensions is None else extensions

        samples = make_dataset(root, extensions)

        self.root = root
        self.loader = loader
        self.extensions = extensions

        self.samples = samples

        self.transform = transform
        self.target_transform = target_transform

    def __getitem__(self, index):
        """
        Args:
            index (int): Index of image

        Returns:
            tuple: (sample, target) where target is target transformed image.
        """
        path = self.samples[index]
        sample = self.loader(path)
        input_sample, target_sample = sample, sample
        if self.transform is not None:
            input_sample = self.transform(sample)
        if self.target_transform is not None:
            target_sample = self.target_transform(sample)

        return input_sample, target_sample

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

class CelebA(SimpleImageFolder):
    """
    `CelebA <http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html>`_ auto-encoding dataset

    Args:
        root (str): Root directory of dataset containing all aligned images in 'root'
        transform (``Transform``, optional): A function/transform that takes in an PIL image and returns a transformed version. E.g, ``transforms.RandomCrop``
        target_transform (``Transform``, optional): A function/transform that takes in an PIL image and returns a transformed version. E.g, ``transforms.RandomCrop``
    """
    def __init__(self, root, transform=None, target_transform=None):
        super(CelebA, self).__init__(root, transform=transform, target_transform=target_transform)

    def __getitem__(self, index):
        item = super(CelebA, self).__getitem__(index)
        return item

class CelebA_HQ(SimpleImageFolder):
    """
    CelebA_HQ, high quality version of `celebA <http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html>`_ auto-encoding dataset as introduced by `Progressive GAN <https://arxiv.org/abs/1710.10196>`_

    Args:
        root (str): Root directory of dataset containing all hq images in 'root'
        as_npy (bool, optional): If True, assume images are stored in numpy arrays. Else assume a standard image format
        transform (``Transform``, optional): A function/transform that takes in an PIL image and returns a transformed version. E.g, ``transforms.RandomCrop``
    """
    def __init__(self, root, as_npy=False, transform=None):
        from torchvision.datasets.folder import default_loader, IMG_EXTENSIONS
        if as_npy:
            loader = self.npy_loader
            extensions = ['npy']
        else:
            loader = default_loader
            extensions = IMG_EXTENSIONS
        super(CelebA_HQ, self).__init__(root, loader, extensions, transform)

    @staticmethod
    def npy_loader(path):
        img = np.load(path)[0].transpose([1,2,0])
        pil_image = Image.fromarray(img)
        return pil_image

    def __getitem__(self, index):
        item = super(CelebA_HQ, self).__getitem__(index)
        return item

class dSprites(Dataset):
    """
    `dSprites <https://github.com/deepmind/dsprites-dataset>`_ Dataset

    Args:
        root (str): Root directory of dataset containing 'dsprites_ndarray_co1sh3sc6or40x32y32_64x64.npz' or to download it to
        download (bool, optional): If true, downloads the dataset from the internet and puts it in root directory. If dataset is already downloaded, it is not downloaded again.
        transform (``Transform``, optional): A function/transform that takes in an PIL image and returns a transformed version. E.g, ``transforms.RandomCrop``
    """
    def __init__(self, root, download=False, transform=None):
        super(dSprites, self).__init__()
        self.file = root
        self.transform = transform

        if download:
            self.download()

        self.data = self.load_data()
        self.latents_sizes = np.array([1, 3, 6, 40, 32, 32])
        self.latents_bases = np.concatenate((self.latents_sizes[::-1].cumprod()[::-1][1:], np.array([1, ])))
        self.latents_values = np.load(os.path.join(self.file, "latents_values.npy"))
        self.latents_classes = np.load(os.path.join(self.file, "latents_classes.npy"))

    def download(self):
        if not os.path.exists(os.path.join(self.file, "imgs.npy")):
            data_url = 'https://github.com/deepmind/dsprites-dataset/blob/master/dsprites_ndarray_co1sh3sc6or40x32y32_64x64.npz?raw=true'
            import sys
            if sys.version_info[0] < 3:
                import urllib2 as request
            else:
                import urllib.request as request
            file = os.path.join(self.file, "dsprites_ndarray_co1sh3sc6or40x32y32_64x64.npz")

            os.makedirs(self.file, exist_ok=True)
            with request.urlopen(data_url) as response, open(file, 'wb+') as out_file:
                shutil.copyfileobj(response, out_file)

            zip_ref = zipfile.ZipFile(file, 'r')
            zip_ref.extractall(self.file)
            zip_ref.close()

    def get_img_by_latent(self, latent_code):
        """
        Returns the image defined by the latent code

        Args:
            latent_code (:obj:`list` of :obj:`int`): Latent code of length 6 defining each generative factor

        Returns:
            Image defined by given code

        """
        def latent_to_index(latents):
            return np.dot(latents, self.latents_bases).astype(int)
        idx = latent_to_index(latent_code)
        return self.__getitem__(idx)[0]

    def load_data(self):
        root = os.path.join(self.file, "imgs.npy")
        data = np.load(root)
        return data

    def __getitem__(self, index):
        data = self.data[index]
        data = Image.fromarray(data * 255, mode='L')

        if self.transform is not None:
            data = self.transform(data)

        return data, data

    def __len__(self):
        return self.data.shape[0]

max_stars_repo_name: pytorchbearer/variational

max_issues_repo_name: pytorchbearer/variational

max_forks_repo_name: pytorchbearer/variational