import numpy as np

HORIZONTAL = 32
VERTICAL = 10

def is_crack_free(combin1, combin2):
    sum1 = combin1[0]
    sum2 = combin2[0]
    i1, i2 = 1, 1
    while True:
        if sum1 == sum2 == HORIZONTAL:
            return True
        if sum1 == sum2:
            return False

        if sum1 < sum2:
            sum1 += combin1[i1]
            i1 += 1
        else:
            sum2 += combin2[i2]
            i2 += 1

def main():
    blocks = [[2], [3]]
    combinations = []
    while blocks:
        current = blocks.pop()
        current_sum = sum(current)

        if current_sum == HORIZONTAL:
            combinations.append(current)
        elif current_sum > HORIZONTAL:
            pass
        else:
            blocks.append(current + [2])
            blocks.append(current + [3])

    num_of_combin = len(combinations)
    # print(num_of_combin)
    crack_free_cache = [[] for _ in range(num_of_combin)]

    for i1 in range(num_of_combin):
        for i2 in range(i1+1, num_of_combin):
            if is_crack_free(combinations[i1], combinations[i2]):
                crack_free_cache[i1].append(i2)
                crack_free_cache[i2].append(i1)

    # print("crack free cache generated")
    cache = np.zeros((num_of_combin, VERTICAL), dtype=np.int64)

    for i in range(num_of_combin):
        cache[i, 1] = len(crack_free_cache[i])

    def fill_walls(curr_combin, left_vertical):
        if cache[curr_combin, left_vertical] > 0 or left_vertical == 1:
            return cache[curr_combin, left_vertical]

        cache[curr_combin, left_vertical] = \
            sum(fill_walls(comb, left_vertical-1)
                for comb in crack_free_cache[curr_combin])
        return cache[curr_combin, left_vertical]

    print(sum(fill_walls(comb, VERTICAL-1) for comb in range(num_of_combin)))

if __name__ == '__main__':
    main()


from aoc.y2021.day9 import clean_input, part1, part2
from aocd.models import Puzzle

test_input = """2199943210
3987894921
9856789892
8767896789
9899965678"""

data = clean_input(test_input)
actual_data = clean_input(Puzzle(2021, 9).input_data)
troughs = part1(data)[1]
actual_troughs = part1(actual_data)[1]

def test_clean_input():
    assert data.R == 5
    assert data.C == 10
    assert data.g[0] == [2, 1, 9, 9, 9, 4, 3, 2, 1, 0]
    assert data.g[2] == [9, 8, 5, 6, 7, 8, 9, 8, 9, 2]

def test_part1():
    assert part1(data)[0] == 15
    assert part1(actual_data)[0] == 594

def test_part2():
    assert part2(data, troughs) == 1134
    assert part2(actual_data, actual_troughs) == 858494


import flask
from flask import Blueprint, render_template, redirect, url_for, request, jsonify
from flask_login import (current_user, login_required)
from flask_paginate import Pagination, get_page_args
from redis import RedisError
from datetime import datetime
import time
import urllib.parse
from redis.commands.search.query import Query
from .document import Document, Version, CurrentVersion
from src.common.config import CFG_VSS_WITH_LUA
from pydantic import ValidationError
from redis_om import NotFoundError

from src.common.utils import get_db, parse_query_string, get_analytics, pretty_title, track_request, requires_access_level, Role

document_bp = Blueprint('document_bp', __name__,
                        template_folder='./templates')

@document_bp.before_request
def before_request():
    # Track the request in a Redis Stream
    track_request()

    # Store visits in a time series visited pages
    if current_user.is_authenticated and request.endpoint == "document_bp.doc":
        get_db().ts().add("keybase:visits", "*", 1, duplicate_policy='first')

@document_bp.route('/autocomplete', methods=['GET'])
@login_required
def autocomplete():
    # Sanitize input for RediSearch
    query = parse_query_string(flask.request.args.get('q'))
    query = "@currentversion_name_fts|currentversion_content_fts:'" + query + "'"
    rs = get_db().ft("document_idx")\
                 .search(Query(query + " @state:{published|review}")
                 .return_field("currentversion_name")
                 .sort_by("creation", asc=False)
                 .paging(0, 10))

    results = []

    for doc in rs.docs:
        results.append({'value': urllib.parse.unquote(doc.currentversion_name),
                        'label': urllib.parse.unquote(doc.currentversion_name),
                        'pretty': pretty_title(urllib.parse.unquote(doc.currentversion_name)),
                        'id': doc.id.split(':')[-1]})

    return jsonify(matching_results=results)

@document_bp.route('/kb-admin', methods=['GET', 'POST'])
@login_required
def browse():
    title = "List documents"
    desc = "Listing documents"
    keys = []
    names = []
    pretty = []
    creations = []
    keydocument = None
    pagination = None
    rs = None
    category = ""
    asc = 0

    try:
        if flask.request.method == 'GET':
            catfilter, tagfilter, queryfilter, prvfilter, sortbyfilter = "", "", "", "", False

            # Check the ordering
            if flask.request.args.get('asc') == "true":
                sortbyfilter = True
                asc = 1

            # Sanitized input for RediSearch
            if flask.request.args.get('q'):
                queryfilter = parse_query_string(flask.request.args.get('q'))
                queryfilter = "@currentversion_name_fts|currentversion_content_fts:'" + queryfilter + "'"
            # If the category is good, can be processed and set in the UI
            if flask.request.args.get('cat'):
                if get_db().hexists("keybase:categories", flask.request.args.get('cat')):
                    catfilter = " @category:{"+flask.request.args.get('cat')+"} "
                    category = flask.request.args.get('cat')

            # Sanitized tags for RediSearch: may be empty afterwards, a search like @tags:{""} fails
            if flask.request.args.get('tag'):
                tag = flask.request.args.get('tag').translate(str.maketrans('', '', "\"@!{}()|-=>"))
                tagfilter = " @tags:{" + tag + "} "

            prv = flask.request.args.get('prv')
            if prv and (prv=='internal' or prv=='public'):
                prvfilter = " @privacy:{" + prv + "} "

            page, per_page, offset = get_page_args(page_parameter='page', per_page_parameter='per_page')
            rs = get_db().ft("document_idx").search(
                Query(queryfilter + catfilter + tagfilter + prvfilter + " @state:{published|review}")
                .return_field("currentversion_name")
                .return_field("creation")
                .sort_by("creation", asc=sortbyfilter)
                .paging(offset, per_page))

            pagination = Pagination(page=page, per_page=per_page, total=rs.total, css_framework='bulma',
                                    bulma_style='small', prev_label='Previous', next_label='Next page')

        # If after sanitizing the input there is nothing to show, redirect to main
        if (rs is not None) and len(rs.docs):
            for key in rs.docs:
                keys.append(key.id.split(':')[-1])
                names.append(urllib.parse.unquote(key.currentversion_name))
                pretty.append(pretty_title(urllib.parse.unquote(key.currentversion_name)))
                creations.append(datetime.utcfromtimestamp(int(key.creation)).strftime('%Y-%m-%d'))
            keydocument = zip(keys, names, pretty, creations)

        # Get the categories
        categories = get_db().hgetall("keybase:categories")
        return render_template('browse.html', title=title, desc=desc, categories=categories, keydocument=keydocument, page=page,
                               per_page=per_page, pagination=pagination, category=category, asc=asc, privacy=prv)
    except RedisError as err:
        return redirect(url_for("document_bp.browse"))

@document_bp.route('/save', methods=['POST'])
@login_required
@requires_access_level(Role.EDITOR)
def save():
    unixtime = int(time.time())

    try:
        currentversion = CurrentVersion(
            name=urllib.parse.unquote(request.form['name']),
            content=urllib.parse.unquote(request.form['content']),
            last=unixtime,
            owner=current_user.id
        )

        editorversion = Version(
            name=urllib.parse.unquote(request.form['name']),
            content=urllib.parse.unquote(request.form['content']),
            last=unixtime,
            owner=current_user.id
        )

        doc = Document(
            editorversion=editorversion,
            currentversion=currentversion,
            description="",
            keyword="",
            tags="",
            creation=unixtime,
            updated=unixtime,
            processable=0,
            author=current_user.id,
            versions=[]
        )

        doc.save()
    except ValidationError as e:
        print(e)

    return jsonify(message="Document created", id=doc.pk)

@document_bp.route('/publish', methods=['POST'])
@login_required
@requires_access_level(Role.ADMIN)
def publish():
    try:
        document = Document.get(request.form['id'])
    except NotFoundError:
        return jsonify(message="Error publishing the document"), 404

    if document.state == "published":
        return jsonify(message="Document already published"), 403

    unixtime = int(time.time())

    version = Version(
        name=urllib.parse.unquote(request.form['name']),
        content=urllib.parse.unquote(request.form['content']),
        last=unixtime,
        owner=document.editorversion.owner
    )

    currentversion = CurrentVersion(
        name=urllib.parse.unquote(request.form['name']),
        content=urllib.parse.unquote(request.form['content']),
        last=unixtime,
        owner=document.editorversion.owner
    )

    document.versions.insert(0, version)

    # Save the document and change the state TAG to "published"
    document.editorversion = version
    document.currentversion = currentversion
    document.state = "published"
    document.processable = 1
    document.updated = unixtime
    document.save()

    data = {'type': 'publish',
            'id': request.form['id']}
    get_db().xadd("keybase:events", data)

    return jsonify(message="Document published")

@document_bp.route('/addmetadata', methods=['POST'])
@login_required
@requires_access_level(Role.EDITOR)
def addmetadata():
    try:
        document = Document.get(request.form['id'])
    except NotFoundError:
        return jsonify(message="The document does not exist", code="error"), 404

    if len(request.form['keyword']) > 160:
        return jsonify(message="Keywords too long: max is 160 chars", code="error"), 500

    if len(request.form['description']) > 160:
        return jsonify(message="Description too long: max is 160 chars", code="error"), 500

    document.keyword = request.form['keyword']
    document.description = request.form['description']
    document.save()
    return jsonify(message="The metadata has been saved", code="success"), 200

@document_bp.route('/addtag', methods=['POST'])
@login_required
@requires_access_level(Role.EDITOR)
def addtag():
    taglist = []

    try:
        document = Document.get(request.form['id'])
    except NotFoundError:
        return jsonify(message="The document does not exist", code="error"), 404

    # Make sure the tag exists and is valid
    if not get_db().hexists("keybase:tags", request.form['tag']):
        return jsonify(message="The tag does not exist", code="error")

    # Get tags for this document
    if (document.tags is not None) and (len(document.tags) > 0):
        taglist = document.tags.split('|')

    # The document hasn't the tag, and it can be added
    if not taglist.count(request.form['tag']) > 0:
        taglist.append(request.form['tag'])
        document.tags = "|".join(taglist)
        document.save()
    else:
        return jsonify(message="Document already tagged", code="warn")

    return jsonify(message="The tag has been added", code="success", tags=taglist)

@document_bp.route('/addcategory', methods=['POST'])
@login_required
@requires_access_level(Role.EDITOR)
def addcategory():
    try:
        document = Document.get(request.form['id'])
    except NotFoundError:
        return jsonify(message="The document does not exist", code="error"), 404

    # Make sure the category exists
    if not get_db().hexists("keybase:categories", request.form['cat']) and len(request.form['cat']):
        return jsonify(message="The category does not exist", code="error")

    document.category = request.form['cat']
    document.save()
    return jsonify(message="The category has been changed", code="success")

@document_bp.route('/setprivacy', methods=['POST'])
@login_required
@requires_access_level(Role.ADMIN)
def setprivacy():
    try:
        document = Document.get(request.form['id'])
    except NotFoundError:
        return jsonify(message="The document does not exist", code="error"), 404

    # Make sure the privacy is correct
    if not (request.form['privacy'] == 'internal') and not (request.form['privacy'] == 'public'):
        return jsonify(message="The privacy setting not exist", code="error"), 500

    # Do not recommend
    privacy = {"privacy": request.form['privacy']}
    get_db().hset("keybase:vss:{}".format(request.form['id']), mapping=privacy)

    document.privacy = request.form['privacy']
    document.save()
    return jsonify(message="The privacy has been changed", code="success")

@document_bp.route('/deltag', methods=['POST'])
@login_required
@requires_access_level(Role.EDITOR)
def deltag():
    taglist = []

    try:
        document = Document.get(request.form['id'])
    except NotFoundError:
        return jsonify(message="The document does not exist", code="error"), 404

    # Get tags for this document
    if (document.tags is not None) and (len(document.tags) > 0):
        taglist = document.tags.split('|')
        taglist.remove(request.form['tag'])
        document.tags = "|".join(taglist)
        document.save()

    return jsonify(message="The tag has been removed", code="success", tags=taglist)

@document_bp.route('/update', methods=['POST'])
@login_required
@requires_access_level(Role.EDITOR)
def update():
    try:
        document = Document.get(request.form['id'])
    except NotFoundError:
        return jsonify(message="Error saving the document"), 404

    unixtime = int(time.time())

    # If the document has never been published, on saving, it should not become a review
    if document.state != "draft":
        document.state = "review"

    # Save the document, which becomes a current review
    document.editorversion.content = urllib.parse.unquote(request.form['content'])
    document.editorversion.name = urllib.parse.unquote(request.form['name'])
    document.editorversion.last = unixtime
    document.editorversion.owner = current_user.id
    document.save()

    return jsonify(message="Document saved as {}".format(document.state))

@document_bp.route('/edit/<pk>')
@login_required
@requires_access_level(Role.EDITOR)
def edit(pk):
    title = "Edit Document"
    desc = "Edit Document"

    try:
        document = Document.get(pk)
    except NotFoundError:
        return redirect(url_for('document_bp.browse')), 404

    if document.state == 'review' and document.editorversion.owner != current_user.id and not current_user.is_admin():
        return render_template('locked.html', name=document.currentversion.name), 403

    # These are all the categories in the system, for the taxonomy
    # System tags are not returned, now. They can be searched
    categories = get_db().hgetall("keybase:categories")

    document.editorversion.name = urllib.parse.quote(document.editorversion.name)
    document.editorversion.content = urllib.parse.quote(document.editorversion.content)

    return render_template('edit.html',
                           title=title,
                           desc=desc,
                           document=document,
                           categories=categories,
                           pretty=pretty_title(urllib.parse.unquote(document.editorversion.name)))

@document_bp.route('/delete/<pk>')
@login_required
@requires_access_level(Role.ADMIN)
def delete(pk):
    try:
        Document.delete(pk)
        get_db().delete("keybase:vss:{}".format(pk))
    except NotFoundError:
        return redirect(url_for('document_bp.browse')), 404

    return redirect(url_for('document_bp.browse')), 302

@document_bp.route('/doc/<pk>', defaults={'prettyurl': None})
@document_bp.route('/doc/<pk>/<prettyurl>')
@login_required
def doc(pk, prettyurl):
    title = "Read Document"
    desc = "Read Document"
    keys = []
    names = []
    pretty = []
    suggestlist = None

    try:
        document = Document.get(pk)
    except NotFoundError:
        return render_template('404.html'), 404

    # Check if the document is bookmarked
    bookmarked = get_db().hexists("keybase:bookmark:{}".format(current_user.id), pk)

    # If it is a draft, make sure the user is not a viewer
    if document.state == 'draft' and current_user.is_viewer():
        return render_template('locked.html', name=document.currentversion.name), 403

    # If it is a draft, make sure the user is the author
    # If it is a draft, role is admin: can see, edit and publish
    if document.state == 'draft' and document.author != current_user.id and not current_user.is_admin():
        return render_template('locked.html', name=document.currentversion.name), 403

    document.currentversion.name = urllib.parse.quote(document.currentversion.name)
    document.currentversion.content = urllib.parse.quote(document.currentversion.content)

    # The document can be rendered, count the visit
    get_db().ts().add("keybase:docview:{}".format(pk), "*", 1, duplicate_policy='first')

    # Only the admin can see document visits
    analytics = None
    if current_user.is_admin():
        analytics = get_analytics("keybase:docview:{}".format(pk), 86400000, 2592000000)

    # Fetch recommendations using LUA and avoid sending vector embeddings back and forth
    # The first element in the returned list is the number of keys returned, start iterator from [1:]
    # Then, iterate the results in pairs, because the key name is alternated with the returned fields
    if get_db().hexists("keybase:vss:{}".format(pk), "content_embedding"):
        if CFG_VSS_WITH_LUA:
            keys_and_args = ["keybase:vss:{}".format(pk)]
            res = get_db().eval(
                "local vector = redis.call('HMGET',KEYS[1], 'content_embedding') local searchres = redis.call('FT.SEARCH','vss_idx','(@state:{published|review})=>[KNN 6 @content_embedding $B AS score]','PARAMS','2','B',vector[1], 'SORTBY', 'score', 'ASC', 'LIMIT', 1, 6,'RETURN',2,'score','name','DIALECT',2) return searchres",
                1, *keys_and_args)
            it = iter(res[1:])
            for x in it:
                keys.append(str(x.split(':')[-1]))
                docname = str(next(it)[3])
                names.append(docname)
                pretty.append(pretty_title(docname))
            suggestlist = zip(keys, names, pretty)
        else:
            embedding = get_db(decode=False).hget("keybase:vss:{}".format(pk), "content_embedding")
            q = Query("(@state:{published|review})=>[KNN 6 @content_embedding $B AS score]")\
                .return_field("score")\
                .return_field("name")\
                .sort_by("score", asc=True)\
                .dialect(2)\
                .paging(1, 6)
            res = get_db().ft("vss_idx").search(q, query_params={"B": embedding})
            it = iter(res.docs[0:])
            for x in it:
                keys.append(str(x['id'].split(':')[-1]))
                names.append(str(x['name']))
                pretty.append(pretty_title(str(x['name'])))
            suggestlist = zip(keys, names, pretty)

    return render_template('view.html',
                           title=title,
                           desc=desc,
                           docid=pk,
                           bookmarked=bookmarked,
                           document=document,
                           suggestlist=suggestlist,
                           analytics=analytics)

@document_bp.route('/new/<doc>')
@login_required
@requires_access_level(Role.EDITOR)
def new(doc):
    title = "New Document"
    desc = "New Document"
    template = ""

    if doc == 'case':
        template = urllib.parse.quote(
            "## Applies to:\n\n\n
\n## Executive Summary \n\n\n
\n
\n
\n## Introduction \n\n\n
\n
\n
\n## Analysis \n\n\n
\n
\n
\n## Alternatives and Decision Criteria \n\n\n
\n
\n
\n## Recommendations and Implementation Plan \n\n\n
\n
\n
\n## Conclusion \n\n\n
\n
\n
\n## References")
    elif doc == 'troubleshooting':
        template = urllib.parse.quote(
            "## Applies to:\n\n\n
\n## Symptoms \n\n\n
\n
\n
\n## Changes \n\n\n
\n
\n
\n## Cause \n\n\n
\n
\n
\n## Solution \n\n\n
\n
\n
\n## References")
    elif doc == 'design':
        template = urllib.parse.quote(
            "## Applies to:\n\n\n
\n## Purpose \n\n\n
\n
\n
\n## Scope \n\n\n
\n
\n
\n## Details \n\n\n
\n
\n
\n## References")
    elif doc == 'howto':
        template = urllib.parse.quote(
            "## Applies to:\n\n\n
\n## Goal \n\n\n
\n
\n
\n## Solution \n\n\n
\n
\n
\n## References")
    elif doc == 'qa':
        template = urllib.parse.quote(
            "## Applies to:\n\n\n
\n## Question \n\n\n
\n
\n
\n## Answer \n\n\n
\n
\n
\n## References")
    return render_template('new.html', title=title, desc=desc, template=template)


"""
Type annotations for braket service client paginators.

[Open documentation](https://vemel.github.io/boto3_stubs_docs/mypy_boto3_braket/paginators.html)

Usage::

    ```python
    import boto3

    from mypy_boto3_braket import BraketClient
    from mypy_boto3_braket.paginator import (
        SearchDevicesPaginator,
        SearchJobsPaginator,
        SearchQuantumTasksPaginator,
    )

    client: BraketClient = boto3.client("braket")

    search_devices_paginator: SearchDevicesPaginator = client.get_paginator("search_devices")
    search_jobs_paginator: SearchJobsPaginator = client.get_paginator("search_jobs")
    search_quantum_tasks_paginator: SearchQuantumTasksPaginator = client.get_paginator("search_quantum_tasks")
    ```
"""
from typing import Iterator, List

from botocore.paginate import Paginator as Boto3Paginator

from .type_defs import (
    PaginatorConfigTypeDef,
    SearchDevicesFilterTypeDef,
    SearchDevicesResponseTypeDef,
    SearchJobsFilterTypeDef,
    SearchJobsResponseTypeDef,
    SearchQuantumTasksFilterTypeDef,
    SearchQuantumTasksResponseTypeDef,
)

__all__ = ("SearchDevicesPaginator", "SearchJobsPaginator", "SearchQuantumTasksPaginator")

class SearchDevicesPaginator(Boto3Paginator):
    """
    [Show boto3 documentation](https://boto3.amazonaws.com/v1/documentation/api/1.26.121/reference/services/braket.html#Braket.Paginator.SearchDevices)
    [Show boto3-stubs documentation](https://vemel.github.io/boto3_stubs_docs/mypy_boto3_braket/paginators.html#searchdevicespaginator)
    """

    def paginate(
        self,
        *,
        filters: List["SearchDevicesFilterTypeDef"],
        PaginationConfig: PaginatorConfigTypeDef = None
    ) -> Iterator[SearchDevicesResponseTypeDef]:
        """
        [Show boto3 documentation](https://boto3.amazonaws.com/v1/documentation/api/1.26.121/reference/services/braket.html#Braket.Paginator.SearchDevices.paginate)
        [Show boto3-stubs documentation](https://vemel.github.io/boto3_stubs_docs/mypy_boto3_braket/paginators.html#searchdevicespaginator)
        """

class SearchJobsPaginator(Boto3Paginator):
    """
    [Show boto3 documentation](https://boto3.amazonaws.com/v1/documentation/api/1.26.121/reference/services/braket.html#Braket.Paginator.SearchJobs)
    [Show boto3-stubs documentation](https://vemel.github.io/boto3_stubs_docs/mypy_boto3_braket/paginators.html#searchjobspaginator)
    """

    def paginate(
        self,
        *,
        filters: List["SearchJobsFilterTypeDef"],
        PaginationConfig: PaginatorConfigTypeDef = None
    ) -> Iterator[SearchJobsResponseTypeDef]:
        """
        [Show boto3 documentation](https://boto3.amazonaws.com/v1/documentation/api/1.26.121/reference/services/braket.html#Braket.Paginator.SearchJobs.paginate)
        [Show boto3-stubs documentation](https://vemel.github.io/boto3_stubs_docs/mypy_boto3_braket/paginators.html#searchjobspaginator)
        """

class SearchQuantumTasksPaginator(Boto3Paginator):
    """
    [Show boto3 documentation](https://boto3.amazonaws.com/v1/documentation/api/1.26.121/reference/services/braket.html#Braket.Paginator.SearchQuantumTasks)
    [Show boto3-stubs documentation](https://vemel.github.io/boto3_stubs_docs/mypy_boto3_braket/paginators.html#searchquantumtaskspaginator)
    """

    def paginate(
        self,
        *,
        filters: List["SearchQuantumTasksFilterTypeDef"],
        PaginationConfig: PaginatorConfigTypeDef = None
    ) -> Iterator[SearchQuantumTasksResponseTypeDef]:
        """
        [Show boto3 documentation](https://boto3.amazonaws.com/v1/documentation/api/1.26.121/reference/services/braket.html#Braket.Paginator.SearchQuantumTasks.paginate)
        [Show boto3-stubs documentation](https://vemel.github.io/boto3_stubs_docs/mypy_boto3_braket/paginators.html#searchquantumtaskspaginator)
        """


import mediatools.audiofile as audio
import mediatools.filespecs as spec

FILE = "it/seal.mp3"

def test_1():
    allp = list(set(spec.VIDEO_PROPS + spec.AUDIO_PROPS + spec.IMAGE_PROPS))
    specs = audio.AudioFile(FILE).get_properties()
    csv = spec.__to_csv__(specs, allp).split(',')
    assert '192000' in csv
    assert 'Seal' in csv
    assert 'Crazy' in csv
    assert 'it/seal.mp3' in csv

def test_2():
    allp = list(set(spec.VIDEO_PROPS + spec.AUDIO_PROPS + spec.IMAGE_PROPS))
    specs = audio.AudioFile(FILE).get_properties()
    std = spec.__to_std__(specs, allp)
    assert 'abitrate            : 187.5 kbits/s' in std
    assert 'duration            : 00:05:57.094' in std


from ListNode import *

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        # if not head:
        #     return head
        # black_node = head
        # dummy_node = black_node
        # head_node = ListNode
        # head_node.next = black_node
        # while black_node.next:
        #     dummy_node = black_node.next
        #     black_node.next = black_node.next.next
        #     # head_node.next = dummy_node
        #     dummy_node.next = head_node.next
        #     head_node.next = dummy_node
        #
        # return dummy_node
        prev_node = None
        curr_node = head
        while curr_node is not None:
            next_node = curr_node.next
            curr_node.next = prev_node
            prev_node = curr_node
            curr_node = next_node

        return prev_node

if __name__ == '__main__':
    nums = [1, 2, 3, 4, 5]
    # nums = [23, 6, 15]
    # nums = [1]
    # nums = []
    head = list_to_linked_list(nums)
    s = Solution()
    traverse_linked_list(s.reverseList(head))

Linked List 101/3.Classic Problems/Reverse Linked List.py


from utils.extract_id_from_title import extract_id_from_title
from import_new_tournaments.get_new_hh_files.TournamentFiles.TournamentFiles import TournamentFiles

def group_filenames_by_id(filenames: list) -> list:
    """
    Takes a list of tournament files names and creates a TournamentFiles class from them

            Parameters:
                    filenames (List[str]): a list of tournament files names

            Returns:
                    tournament_files (list): a list of TournamentFiles classes
    """

    filenames_classes = {}
    for file_name in filenames:
        id = extract_id_from_title(file_name)
        if id in filenames_classes:
            filenames_classes.get(id).add_hand_history_filename(file_name)
        else:
            new_t = TournamentFiles(id)
            new_t.add_hand_history_filename(file_name)
            filenames_classes[id] = new_t
    return list(filenames_classes.values())


# Simple script that converts a space delimited dataset to a comma separated one

import numpy as np
import sys.argv as argv
import sys.exit as exit

def convertToCSV(filename):
  data = np.genfromtxt(filename, delimiter=' ')
  np.savetxt(filename, data, delimiter=",")

if __name__ == "__main__":
  if len(argv)!=2:
    print("Usage: ./augment inputFileName")
    exit()
  convertToCSV(argv[1])


from django.test import RequestFactory, TestCase
from .models import *
import datetime as dt

class TransactionTestCase(TestCase):
    def setUp(self):
        Category.objects.create(
            name = 'furniture',
            accumulative = True,
            checked=False,
        )
        Category.objects.create(
            name = 'clothes',
            accumulative = True,
        )
        Category.objects.create(
            name = 'salary',
            type = 1,
        )
        Category.objects.create(
            name = 'bonus',
            type = 1,
        )
        Transaction.objects.create(
            transaction_date=dt.date(2019,2,13),
            amount=2600.0,
            description='test1',
            category_id='furniture',
            am_months=36)
        Transaction.objects.create(
            transaction_date=dt.date(2019,4,5),
            amount=520.0,
            description='test2',
            category_id='furniture',
            am_months=12)
        Transaction.objects.create(
            transaction_date=dt.date(2019,6,23),
            amount=800.0,
            description='test3',
            category_id='furniture',
            am_months=18)
        Transaction.objects.create(
            transaction_date=dt.date(2019,2,13),
            amount=200.0,
            description='test4',
            category_id='clothes',
            am_months=24)
        Budget.objects.create(
            category_id = 'furniture',
            amount = 1000,
            start_date = dt.date(2020,6,24),
            freq_month = 0.25
        )
        Budget.objects.create(
            category_id = 'clothes',
            amount = 200,
            start_date = dt.date(2020,6,24),
            freq_month = 0.5
        )
        Budget.objects.create(
            category_id = 'salary',
            amount = 20000,
            start_date = dt.date(2020,6,24),
            freq_month = 0.5
        )

    def test_context_data_0(self):
        response = self.client.get('/bunnySpend5/budget/spending/latest')
        object_list = response.context['object_list']
        self.assertEqual(object_list.count(), 2)

    def test_context_data_1(self):
        response = self.client.get('/bunnySpend5/budget/income/latest')
        object_list = response.context['object_list']
        self.assertEqual(object_list.count(), 1)


import xlwings as xlv

def get_monster_lv(level_type, game_level):
    level_type = level_type
    game_level = game_level

    level_row_sht1 = 0
    level_row_sht2 = 0
    dicts = {}

    ap1 = xlv.App(visible=False, add_book=False)
    ap1.display_alerts = False
    wb1 = ap1.books.open('怪物模板.xlsx')
    sht1 = sht2 = None
    if level_type == "单打":
        sht1 = wb1.sheets['单打怪物分布']
        sht2 = wb1.sheets['海陆单打']
    elif level_type == "双打":
        sht2 = wb1.sheets['海陆双打']
        sht1 = wb1.sheets['双打怪物分布']

    if (sht1 is not None) & (sht2 is not None):
        nrow_sht1 = sht1.api.UsedRange.Rows.count
        ncol_sht1 = sht1.api.UsedRange.Columns.count
        nrow_sht2 = sht2.api.UsedRange.Rows.count
        ncol_sht2 = sht2.api.UsedRange.Columns.count

        rng_sht1 = sht1.range((1, 1), (nrow_sht1, ncol_sht1))
        rng_sht2 = sht2.range((1, 1), (nrow_sht2, ncol_sht2))

        # 找到这关在哪一行
        for x in rng_sht1:
            if x.value == game_level:
                level_row_sht1 = x.row
        num_sht1 = 1
        # 循环把这一行搞成一个dict
        for x1 in rng_sht1.rows[0]:
            key = x1.value
            word = str(sht1.range(level_row_sht1, num_sht1).value)
            dicts[key] = word
            num_sht1 = num_sht1 + 1

        # 在第二个页签做相同的处理
        for y in rng_sht2:
            if y.value == game_level:
                level_row_sht2 = y.row
        num_sht2 = 1
        for y1 in rng_sht2.rows[0]:
            key = y1.value
            word = str(sht2.range(level_row_sht2, num_sht2).value)
            dicts[key] = word
            num_sht2 = num_sht2 + 1

    wb1.close()
    ap1.quit()
    return dicts


from turtle import listen, onkey
from snake import Snake
from dot import Dot
from game import Game
import time

GAME_SPEED = 0.05
GAME_SIZE_X = 200
GAME_SIZE_Y = 200

# Start the game
game = Game(screen_size_x=GAME_SIZE_X, screen_size_y=GAME_SIZE_Y)

snake = Snake()  # initialize snake
dot = Dot()  # initialize dot/food

listen()
onkey(snake.up, "Up")  # This will call the up function if the "Left" arrow key is pressed
onkey(snake.down, "Down")
onkey(snake.left, "Left")
onkey(snake.right, "Right")

game_is_on = True

while game_is_on:
    snake.move()
    game.screen.update()

    if game.at_edge(snake.snake):  # game over
        game_is_on = False

    # detect head collision
    else:
        #detect head collision
        for segment in snake.snake[1:]:
            if segment.distance(snake.head) < 10:
                game_is_on = False

        if game_is_on and dot.on_snake(snake):
            game.update_score()
            snake.grow()
            dot.move()

    time.sleep(GAME_SPEED)

# exit on click
game.screen.exitonclick()


def solve(s):
    stack = []
    ans = 0

    for i, l in enumerate(s):
        if l == "\\":
            stack.append(i)
        elif l == "/":
            if stack:
                j = stack.pop()
                ans += i - j

    print(ans)

if __name__ == "__main__":
    t = int(input())
    for _ in range(t):
        solve(input().strip())


# https://www.beecrowd.com.br/judge/pt/problems/view/2187

values = {50: 0, 10: 0, 5: 0, 1: 0}

v = int(input())

test_number = 1
while v != 0:
    money = v
    for value in values:
        values[value] = money // value
        money -= value * values[value]

    print(f'Teste {test_number}')
    a, b, c, d = values.values()
    print(a, b, c, d, sep=' ')
    print('')

    v = int(input())
    test_number += 1


lista = []
n=int(input("Podaj dlugosc listy:"))
print("Podaj liczby, ktore maja byc zawarte w liscie:")
def usun(x):
    x.sort()
    x=list(set(lista))
    return x
for _ in range(0,n):
    a=int(input())
    lista.append(a)
print("Twoja lista: ",lista)
print("Twoja lista po usunieciu duplikatow: ", usun(lista))


'''
Given a 2D integer array matrix, return the transpose of matrix.

The transpose of a matrix is the matrix flipped over its main diagonal, switching the matrix's row and column indices.

Example 1:

Input: matrix = [[1,2,3],[4,5,6],[7,8,9]]
Output: [[1,4,7],[2,5,8],[3,6,9]]
Example 2:

Input: matrix = [[1,2,3],[4,5,6]]
Output: [[1,4],[2,5],[3,6]]
'''

class Solution(object):
    def transpose(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[List[int]]
        """

        new_matrix = [[0 for x in range(len(matrix))]
                      for y in range(len(matrix[0]))]

        for row in range(len(matrix)):
            for col in range(len(matrix[0])):

                new_matrix[col][row] = matrix[row][col]

        return new_matrix

'''
 [1, 2, 3],
 [4, 5, 6]

 [1, 4],
 [2, 5],
 [3, 6]

 '''


#!/usr/bin/env python
# -*- coding: utf-8 -*-

from textteaser.parser import Parser

from flask import Flask
from flask import render_template
from flask import send_from_directory
from flask import request

DEBUG = True
THRESHOLD = 0.5

app = Flask(__name__)
text = ''

@app.route('/css/<path:path>')
def sendCss(path):
	return send_from_directory('css', path)

@app.route("/whiteout", methods=['GET'])
def index():
	return render_template('whiteout.html', text=text, cleaned=[])

@app.route("/whiteout", methods=['POST'])
def clean():
	text = request.form['text']
	w = Whiteout()
	if DEBUG:
		sentences = w.cleanWithScore(text)
	else:
		sentences = w.clean(text)
	return render_template('whiteout.html', text=text, cleaned=sentences)

class Whiteout:
	def __init__(self):
		self.parser = Parser()
		self.initDict()

	def initDict(self):
		self.words = set()
		self.addWordsFromList('data/20k.txt')
		self.addWordsFromList('data/wordnet.txt')
		self.addWordsFromList('data/mydict.txt')

	def addWordsFromList(self, list):
		with open(list) as file:
			words = file.readlines()
		for word in words:
			self.words.add(word.strip())

	def clean(self, text):
		sentences = self.parser.splitSentences(text)
		cleaned = []
		return [sentence for sentence in sentences
			if self.sentenceScore(sentence) >= THRESHOLD]

	def cleanWithScore(self, text):
		sentences = self.parser.splitSentences(text)
		cleaned = []
		# return [sentence for sentence in sentences
		#	if self.sentenceScore(sentence) >= THRESHOLD]
		for sentence in sentences:
			score = self.sentenceScore(sentence)
			if (score >= THRESHOLD):
				cleaned.append("{:1.3f}".format(score))
				cleaned.append(sentence)
			# cleaned.append(self.cleanSentence(sentence))
		return cleaned

	def sentenceScore(self, sentence):
		sentence = self.parser.removePunctations(sentence)
		words = self.parser.splitWords(sentence)
		count = 0.0
		for word in words:
			if word in self.words and len(word) > 1:
				count = count + 1
		if len(words) == 0:
			return 0.0
		return count / len(words)


from datetime import datetime
from abc import abstractmethod
import os
from sqlalchemy import Column, Text, Integer
from base import Base

class AudioFile(Base):
    """Represent a song played on a music player

    Author: Jaguar Perlas
    ID: A01175812
    """

    __tablename__ = "collection"
    id = Column(Integer, primary_key=True)
    title = Column(Text, nullable=True)
    artist = Column(Text, nullable=True)
    # album = Column(Text, nullable=True)
    runtime = Column(Text, nullable=False)
    # genre = Column(Text, nullable=True)
    rating = Column(Text, nullable=True)
    pathname = Column(Text, nullable=True)
    date_added = Column(Text, nullable=True)
    last_played = Column(Text, nullable=True)

    def __init__(self, title: str, artist: str, runtime: str, rating: int = 0, pathname: str = None) -> None:
        """Initialize a song with a title, artist, album, date added, runtime, pathname, filename,
        user rating, last played, and play count."""
        if type(self) == AudioFile:
            raise ValueError('Creation of super class not allowed')
        self.title = title
        self.artist = artist
        self.runtime = runtime
        self.rating = rating
        self.pathname = pathname
        self.filename = os.path.basename(pathname)
        self.user_rating = rating

        self.date_added = datetime.now()
        self.play_count = 0
        self.last_played = None

        # self._usage = UsageStats(datetime.now())
        AudioFile._validate_constructor(title, artist, runtime, rating, self.pathname)

    @staticmethod
    def _validate_constructor(title: str, artist: str, runtime: str, rating: int, pathname) -> None:
        """Validate the values passed into the constructor"""
        if not ((type(title) != str) or (type(artist) != str) or (type(runtime) != str) or
                (type(rating) != int)):
            if not os.path.exists(pathname):
                raise ValueError('Path does not exist.')
            pass
        else:
            raise ValueError('Values must be a string and "rating" must be an int.')

    @abstractmethod
    def get_description(self):
        """Return a string containing the description of the song"""
        song_description = '%s by %s from the album '' added on %s. Runtime is %s. Last' \
                           ' played on %s. User rating is %s' % (self.title, self._artist,
                                                                 self.date_added, self.runtime,
                                                                 self._last_played, self.user_rating)
        pass

    def song_location(self) -> str:
        """Return a string containing the path of the song file"""
        song_location = '%s is located at %s' % (self.filename, self.pathname)
        return song_location

    def play_song(self) -> None:
        """Plays the song"""
        self.increment_usage_stats()
        print('Now playing: %s by %s' % (self.title, self._artist))
        print('Play count is now %d' % self.play_count)

    @property
    def _user_rating(self) -> int:
        """Gets and returns the user rating"""
        return self.rating

    @_user_rating.setter
    def _user_rating(self, user_rating: int) -> None:
        """Sets the user rating to desired value"""
        if type(user_rating) != int:
            raise ValueError('Input must be a number')
        else:
            if (user_rating < 0) or (user_rating > 5):
                raise ValueError('Rating must be a number out of 10')
            else:
                self.user_rating = int(user_rating)

    @abstractmethod
    def meta_data(self):
        song_dict = {'title': self._title, 'artist': self._artist,
                     'date_added': self.date_added, 'runtime': self.runtime,
                     'pathname': self.pathname, 'filename': self.filename, 'play_count':
                         self.play_count, 'last_played': self._last_played,
                     'rating': self.user_rating}
        pass

    #UsageStats functions below vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

    @property
    def _date_added(self):
        """ return the date the song or playlist was added to the library """
        return self._date_added.strftime("%Y-%m-%d")

    @property
    def _last_played(self):
        """ return the date the song or playlist was last played """
        if self.last_played is None:
            return None
        else:
            return self.last_played.strftime("%Y-%m-%d")

    @property
    def _play_count(self):
        """ return the number of times the song or playlist has been played """
        return self._play_count

    def increment_usage_stats(self):
        """ update the play count and last played time when a song is played """
        self.play_count += 1
        self.last_played = datetime.now()

    @classmethod
    def __valid_datetime(cls, date):
        """ private method to validate the date is datetime object """
        if type(date) is not datetime:
            return False
        else:
            return True


class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        return self.ksum(nums, target, 4)

    def ksum(self, nums, target, k):
        if k == 2:
            ans = set()
            found = set()
            for num in nums:
                if target - num in found:
                    if num <= target-num:
                        ans.add((num, target-num))
                    else:
                        ans.add((target-num, num))
                found.add(num)
            return ans
        else:
            ret = set()
            for i in range(len(nums)):
                if i == 0 or nums[i-1] != nums[i]:
                    for _list in self.ksum(nums[i+1:], target-nums[i], k-1):
                        tmp = tuple(sorted([nums[i]] + list(_list)))
                        ret.add(tmp)
            return ret


#!/usr/bin/env python3
import os, subprocess
import logging
from pathlib import Path

import h5py
import hsluv
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import ticker
import glob
from sklearn.gaussian_process import GaussianProcessRegressor as GPR
from sklearn.gaussian_process.kernels import RBF, WhiteKernel, Matern
from scipy.interpolate import interp1d, interp2d
from matplotlib.gridspec import GridSpec
from scipy.integrate import quad
import matplotlib.gridspec as gridspec

fontsmall, fontnormal, fontlarge = 4.5, 6, 7
offblack = '#262626'
aspect = 1/1.618
resolution = 72.27
textwidth = 270/resolution
textheight = 200/resolution
fullwidth = 300/resolution
fullheight = 200/resolution

plt.rcdefaults()
plt.rcParams.update({
    'font.family': 'DejaVu Sans-Serif',
    'font.sans-serif': ['Lato'],
    'mathtext.fontset': 'custom',
    'mathtext.default': 'it',
    'mathtext.rm': 'sans',
    'mathtext.it': 'sans:italic:medium',
    'mathtext.cal': 'sans',
    'font.size': fontnormal,
    'legend.fontsize': fontsmall,
    'axes.labelsize': fontnormal,
    'axes.titlesize': fontnormal,
    'xtick.labelsize': fontsmall,
    'ytick.labelsize': fontsmall,
    'lines.linewidth': .8,
    'lines.markersize': 3,
    'lines.markeredgewidth': 0,
    'patch.linewidth': .5,
    'axes.linewidth': .4,
    'xtick.major.width': .4,
    'ytick.major.width': .4,
    'xtick.minor.width': .4,
    'ytick.minor.width': .4,
    'xtick.major.size': 1.2,
    'ytick.major.size': 1.2,
    'xtick.minor.size': .8,
    'ytick.minor.size': .8,
    'xtick.major.pad': 1.5,
    'ytick.major.pad': 1.5,
    'axes.formatter.limits': (-5, 5),
    'axes.spines.top': True,
    'axes.spines.right': True,
    'ytick.right': True,
    'axes.labelpad': 3,
    'text.color': offblack,
    'axes.edgecolor': offblack,
    'axes.labelcolor': offblack,
    'xtick.color': offblack,
    'ytick.color': offblack,
    'legend.numpoints': 1,
    'legend.scatterpoints': 1,
    'legend.frameon': False,
    'image.cmap': 'Blues',
    'image.interpolation': 'none',
    'pdf.fonttype': 42
})
cm1, cm2 = plt.cm.Blues(.8), plt.cm.Reds(.8)
cb,co,cg,cr,ck = plt.cm.Blues(.6), \
    plt.cm.Oranges(.6), plt.cm.Greens(.6), plt.cm.Reds(.6),\
    '.5'
gray = '0.8'

plotdir = Path('plots')
plotdir.mkdir(exist_ok=True)

plot_functions = {}

def plot(f):
    """
    Plot function decorator.  Calls the function, does several generic tasks,
    and saves the figure as the function name.

    """
    def wrapper(*args, **kwargs):
        logging.info('generating plot: %s', f.__name__)
        f(*args, **kwargs)

        fig = plt.gcf()

        #if not fig.get_tight_layout():
        #    set_tight(fig)
        os.makedirs(plotdir /f.__name__.split('_')[0], exist_ok=True)
        plotfile = plotdir /f.__name__.split('_')[0]/ '{}.png'.format(f.__name__.split('_')[1])
        fig.savefig(str(plotfile), dpi=300)
        logging.info('wrote %s', plotfile)
        plt.close(fig)

    plot_functions[f.__name__] = wrapper

    return wrapper

def set_tight(fig=None, **kwargs):
    """
    Set tight_layout with a better default pad.

    """
    if fig is None:
        fig = plt.gcf()

    kwargs.setdefault('pad', .01)
    fig.set_tight_layout(kwargs)

def auto_ticks(ax, axis='both', minor=False, **kwargs):
    """
    Convenient interface to matplotlib.ticker locators.

    """
    axis_list = []

    if axis in {'x', 'both'}:
        axis_list.append(ax.xaxis)
    if axis in {'y', 'both'}:
        axis_list.append(ax.yaxis)

    for axis in axis_list:
        axis.get_major_locator().set_params(**kwargs)
        if minor:
            axis.set_minor_locator(ticker.AutoMinorLocator(minor))

def darken(rgb, amount=.15):
    """
    Darken a color by the given amount in HSLuv space.

    """
    h, s, l = hsluv.rgb_to_hsluv(rgb)
    return hsluv.hsluv_to_rgb((h, s, (1 - amount)*l))

NCZA = ['He','Ne','Kr','Xe'],[cb,cg,cr,ck],[2,10,36,54],[4,20,84,131]
folder = "Run/Production/Generalized/K0d5/"

print("loading")
#samples = {it: np.loadtxt(folder+"/{}-{}-cutRA.dat".format(Z,A)).T
#       for it, c, Z, A in zip(*NCZA)}
#samples['d'] = np.loadtxt(folder+"/1-2-cutRA.dat").T
print("done")

def AvgKinematics(xname):
    AllLabels = [r"$\langle \nu\rangle$", r"$\langle z\rangle$", r"$\langle Q^2\rangle$ [GeV${}^2$]",r"$\langle p_T^2\rangle$ [GeV${}^2$]"]
    if xname=='nu':
        idx = 0
        idy = (1,2,3)
    if xname=='z':
        idx = 1
        idy = (0,2,3)
    if xname=='Q2':
        idx = 2
        idy = (0,1,3)
    if xname=='pt2':
        idx = 3
        idy = (0,1,2)
    ylabels = [AllLabels[i] for i in idy]
    xlabel = AllLabels[idx]
    fig, axes = plt.subplots(1,3,figsize=(textwidth,.35*textwidth), sharex=True)
    xl, xh, x, y1, y2, y3 = data = np.loadtxt("Exp/HERMES/SIDIS/AvgKinmatics/{}-binned.dat".format(xname)).T
    if xname in ['Q2','pt2']:
        axes[0].semilogx()
    for ax, y, ylabel in zip(axes, [y1,y2,y3], ylabels):
        ax.errorbar(x, y ,xerr=[x-xl,xh-x],fmt='k.')
        ax.set_xlabel(xlabel)
        ax.set_ylabel(ylabel)
        ax.set_xlim(np.max([xl.min(),.01]), xh.max())
        ax.set_ylim(ymin=0, ymax=y.max()*1.5)
    pid, z, pT, nu, Q2 = np.loadtxt(folder+"/36-84-cutRA.dat").T
    zmin = .1 if xname=='z' else .2
    numin = 4. if xname=='nu' else 6.
    cut = ( (pid==211) | (pid==-211) | (pid==111)) & (z>zmin) & (nu>numin)

    z = z[cut]
    nu = nu[cut]
    Q2 = Q2[cut]
    pt2 = pT[cut]**2
    data = [nu, z, Q2, pt2]
    for ax, iy in zip(axes, idy):
        X = []
        Y = []
        for il, ih in zip(xl, xh):
            cut = (il<data[idx])&(data[idx]<ih)
            X.append(data[idx][cut].mean())
            Y.append(data[iy][cut].mean())
        ax.plot(X, Y,'ro')

    set_tight(fig,pad=0.4)

@plot
def dihadron_figS20():
    fig, axes = plt.subplots(1,3,figsize=(.8*textwidth,textwidth*.35), sharex=True,sharey=True)
    # exp:
    for Z, A, name, ax in zip([7,36,54],[14,84,131],['N','Kr','Xe'], axes):
        _, _, X, Y, Ystat = np.loadtxt("Exp/HERMES/Dihadron/R12_{}.dat".format(name)).T
        ax.errorbar(X,Y,yerr=Ystat,fmt='k.', label="HERMES")
    # model:
    b = np.array([.0,.05,.075,.125,.15,.2,.3,.4,.5])
    x = (b[:-1]+b[1:])/2.
    dx = b[1:]-b[:-1]
    Ks = ['0d5','1','2']
    nu0, nu1 = 0,2000
    Q20, Q21 = 0,2000
    x0, x1 = 0,1
    for model,color,label in zip(['Generalized','Collinear'],[cr,cb],['Gen.','H-T']):
        YK0 = []
        for K in Ks:
            z1, z2, Q2, nu, w = np.loadtxt("Run/Production/Dihadron-20/{}/{}/1-2-cutRA.dat".format(model,K)).T
            xB = Q2/2./0.938/nu
            cut = (z1>.5) & (nu>nu0)&(nu<nu1)& (Q2>Q20)&(Q2<Q21) &\
                  (x0<xB) & (xB<x1)
            dN0, _ = np.histogram(z2[cut], weights=w[cut], bins=b)
            N0 = np.sum(w[cut])
            YK0.append(dN0/N0)
        for Z, A, name, ax in zip([7,36,54],[14,84,131],['N','Kr','Xe'], axes):
            YK1 = []
            for K in Ks:
                z1, z2, Q2, nu, w = np.loadtxt("Run/Production/Dihadron-20/{}/{}/{}-{}-cutRA.dat".format(model,K,Z,A)).T
                xB = Q2/2./0.938/nu
                cut = (z1>.5) & (nu>nu0)&(nu<nu1)& (Q2>Q20)&(Q2<Q21) &\
                  (x0<xB) & (xB<x1)
                dN0, _ = np.histogram(z2[cut], weights=w[cut], bins=b)
                N0 = np.sum(w[cut])
                YK1.append(dN0/N0)
            ax.fill_between(x, YK1[0]/YK0[0], YK1[2]/YK0[2], color=color, label=label, alpha=.7)
            ax.plot(x, YK1[1]/YK0[1], color=color)
            ax.set_xlabel(r"$z_2$")
            if ax.is_first_col():
                ax.set_ylabel(r"$R_{2h}(z_2)$")
            ax.plot([0,.5], [1,1], 'k-', lw=.5)
            ax.set_title(r"$e+{{\rm {:s}}}\rightarrow h+\cdots$".format(name))
    ax.set_xlim(0,.5)
    ax.set_ylim(0.5,1.4)
    axes[0].legend()
    ax.annotate(r"$z_1>0.5$"+"\n"+r"Excluding $\{+,-\}$", xy=(.25,.8), xycoords="axes fraction", fontsize=5)

    plt.subplots_adjust(wspace=0, left=.12, right=.98, bottom=.2, top=.86)
@np.vectorize
def exact(X, Y):
    # X = 2kq/(k2+q2)
    # Y = |k-q|^2/(2z(1-z)E)
    # (k2+q2)/(2z(1-z)E) = Y/(1-X)
    # 2kq/(2z(1-z)E) = Y*X/(1-X)
    def df(x):
        cos = np.cos(x)
        return X*cos/(1 - X*cos) * (1-np.cos(Y/(1-X) - cos*Y*X/(1-X)))
    return quad(df, 0, 2*np.pi)[0]/2./np.pi

@np.vectorize
def Gen(kt2LoverEstuff, q2overkt2):
    X = 2*np.sqrt(q2overkt2)/(1+q2overkt2)
    Y = kt2LoverEstuff*(1+q2overkt2)*(1-X)
    return exact(X, Y)

@np.vectorize
def HT(kt2LoverEstuff, q2overkt2):
    return 2*q2overkt2*(1-np.cos(kt2LoverEstuff))

@np.vectorize
def HT2(kt2LoverEstuff, q2overkt2):
    X = 2*np.sqrt(q2overkt2)/(1+q2overkt2)
    Y = kt2LoverEstuff*(1+q2overkt2)*(1-X)
    A = Y/(1-X)
    B = Y*X/(1-X)
    phase1 = jv(0,B)-jv(1,B)/B
    phase2 = -jv(1,B)
    if (q2overkt2>1):
        q2overkt2 = 1./q2overkt2
    return 2*q2overkt2*(1 - 2*np.cos(A)*phase1) + 2*np.sqrt(q2overkt2)*np.sin(A)*phase2
from scipy.special import jv

@plot
def Other_GENvsHT1():
    x = np.exp(np.linspace(-1.5,4,2000))
    fig, axes = plt.subplots(1,5, figsize=(1.1*textwidth,.35*textwidth),sharex=True, sharey=True)
    for q2overkt2, ax, s in zip([.25, 0.5, .9999, 2,4], axes, [0.25,0.5,1,2,4]):
        ax.plot(1/x, HT(x,q2overkt2),'-',color=cb,alpha=.7, label='H.T.')
        #ax.plot(1/x, HT2(x,q2overkt2),'-',color=cg,alpha=1, label='H.T., improved')
        ax.plot(1/x, Gen(x,q2overkt2),'-',color=cr,alpha=.7,lw=1, label='Gen.')
        ax.plot(1/x, 0/x, 'k-',lw=.5)
        ax.semilogx()
        ax.set_xlim(1/x[-1],1/x[0])
        ax.set_ylim(-1,7)
        if ax.is_first_col():
            ax.set_ylabel(r"$\frac{d\Delta_1}{dk_\perp^2}(u,\frac{k_\perp^2}{l_\perp^2})$ (a.u.)")
        ax.annotate("$k_\perp^2/l_\perp^2 = {}$".format(s),xy=(.3,.88), xycoords="axes fraction")
    axes[2].set_xlabel(r"$u = \tau_f/t^+$")
    axes[0].legend(loc=(.1,.6))
    plt.subplots_adjust(wspace=0,top=.99,left=.12,right=.98,bottom=.25)

@plot
def Other_spacetime4():
    fig, ax = plt.subplots(1,1,figsize=(.5*textwidth,textwidth*.4))

    bins = np.exp(np.linspace(np.log(.02),np.log(100),21))
    dt = bins[1:]-bins[:-1]
    t = (bins[1:]+bins[:-1])/2.
    kl,kh = 0,10
    for sqrts,color in zip([15],[cr,cg,cb]):
        Neve = 1e5
        status, xB, Q20, nu, tauf, lt2, pt2, z, k0, L  = np.loadtxt("Run/SpaceTime/{}vac/82-208-stat.dat".format(sqrts)).T
        tt = tauf/L
        cut = (status==111) & (L>50) #& (kl<k0)& (k0<kh)
        H, _ = np.histogram(tt[cut],bins=bins)
        H = np.array(H)
        dH = np.sqrt(H)/(dt*Neve)
        H0 = H/(dt*Neve)
        ax.plot(t, H0, 'k-', lw=0.35)

        status, xB, Q20, nu, tauf, lt2, pt2, z, k0, L  = np.loadtxt("Run/SpaceTime/{}/82-208-stat.dat".format(sqrts)).T
        tt = tauf/L
        cut = (status==111) & (L>50) # & (kl<k0)& (k0<kh)
        H, _ = np.histogram(tt[cut],bins=bins)
        H = np.array(H)
        dH = np.sqrt(H)/(dt*Neve)
        H1 = H/(dt*Neve)
        ax.plot(t, H1, '-', alpha=.7, color=color,lw=1., label=r'$\sqrt{{s}}={}$'.format(sqrts))
        ##
        cut = (status==222) & (L>50) # & (kl<k0)& (k0<kh)
        H, _ = np.histogram(tt[cut],bins=bins)
        H = np.array(H)
        dH = np.sqrt(H)/(dt*Neve)
        H1 = H/(dt*Neve)
        ax.plot(t, H1, '--', alpha=.7, color=color)

    ax.set_title(r"$e$+Pb, $Q>2$ GeV, $\nu>10$ GeV, $L>10$ fm",fontsize=5)
    ax.set_ylabel(r"$L dN_{g}/d\tau_{f,g}$")
    ax.set_xlim(0.02,100)
    ax.set_xlabel(r"$\tau_{f,g}/L$")
    ax.semilogy()
    ax.semilogx()
    ax.set_ylim(1e-5, 1e3)
    #ax.legend(loc=(.6,.45))
    #ax.set_xticks([0,1,2,3,4,5,6])
    ax.plot([1,1],[1e-5,1e-4],'k')
    ax.plot([1,1.1],[1e-5,2e-5],'k')
    ax.plot([1,1/1.1],[1e-5,2e-5],'k')
    ax.annotate(r"Thin solid: vac shower"+'\n'\
                 r"Thick solid: shower $p_T>Q_0$"+'\n'\
                +r"Dashed: gluon $p_T<Q_0$",
                xy=(.22,.77), xycoords='axes fraction',fontsize=5)
    plt.subplots_adjust(wspace=0.25, left=.21, right=.96, bottom=.18, top=.88)

#@plot
def AvgKinematics_nu():
    AvgKinematics('nu')
#@plot
def AvgKinematics_z():
    AvgKinematics('z')
#@plot
def AvgKinematics_Q2():
    AvgKinematics('Q2')
#@plot
def AvgKinematics_pt2():
    AvgKinematics('pt2')

@plot
def sudakov_fig():
    fig, ax = plt.subplots(1,1,figsize=(textwidth*.4,textwidth*.25), sharex=True,sharey=True)
    Neve = 1e4
    for Z, A, name in zip([54],[131],['Xe']):
        nc,nh,ns = np.loadtxt("Run/Sudakov/{}-{}-stat.dat".format(Z,A)).T
        nrad = nh+ns
        ax.hist(nc ,bins=[-.5,.5,1.5,2.5,3.5,4.5,5.5],density=True,histtype='step')

    ax.legend(loc='best', framealpha=.5)
    ax.set_xlabel(r"$N_{\rm coll}$")
    ax.set_ylabel("Prob.")
    ax.set_ylim(0,.6)
    ax.set_xlim(-.5,5)
    ax.annotate("e-Xe", xy=(2,.4))
    set_tight(fig)

# page 10 why differ at low multiplicuty
@plot
def ed_dNdzdpTpi():
    fig, axes = plt.subplots(1,4,figsize=(1.3*textwidth,textwidth*.4), sharex=True,sharey=True)

    b = np.linspace(0,1,10)
    x = (b[:-1]+b[1:])/2.
    dx = b[1:]-b[:-1]
    Ne = 1e6
    axes[0].semilogy()
    pid, z, pT, nu, Q2 = np.loadtxt("Run/Production/ed/1-2-StopM0d0.dat").T
    for ax, zbin in zip(axes,[[.2,.3],[.3,.4],[.4,.6],[.6,.8]]):
        ax.annotate(r"${}<z_h<{}$".format(*zbin), xy=(.1, .9), xycoords="axes fraction")
        for line, color, iid in zip(['-','--'],[cr, cb],[211,-211]):
            cut = (pid==iid) & (zbin[0]<z) & (z<zbin[1])

            Y = np.histogram((pT)[cut],bins=b)[0]/dx/Ne/(zbin[1]-zbin[0])
            ax.plot(x, Y, line, color=color, lw=1, alpha=.8)
            ax.set_xlim(0,1)
            if ax.is_last_row():
                ax.set_xlabel(r"$p_T$ [GeV${}$]")
            if ax.is_first_col():
                ax.set_ylabel(r"$dN/dp_T/dz_h$")
            ax.set_ylim(ymin=0)

    for ax, zbin in zip(axes,[[.2,.3],[.3,.4],[.4,.6],[.6,.8]]):
        for color,iid,n in zip([cr,cb],[211,-211],['pi+','pi-']):
            x,y,ystat,_,ysys,_ = np.loadtxt("ExpData/pT/ed-{}-z-{}-{}.dat".format(n,*zbin)).T
            ssid = {211:'\pi^+', -211:'\pi^-', 111:'\pi^0',
                       321:'K^+',  -321:'K^-',
                       2212:'p',  -2212:"\\bar{p}"}[iid]
            ax.errorbar(x,y,yerr=ystat, fmt='.', color=darken(color), label=r'HERMES ${}$'.format(ssid)
            )
            xb = [0.]+list((x[1:]+x[:-1])/2.) + [1.]
            for il,ih,yl,yh in zip(xb[:-1],xb[1:],y-ysys,y+ysys):
                ax.fill_between([il,ih],[yl,yl],[yh,yh],
                            edgecolor=darken(color),facecolor='none')
    axes[0].legend(loc=(.03, .1))

    ax.set_ylim(1e-2,1e1)
    ax.set_xlim(0.0,1.1)
    ax.set_xticks([0.,.3,.6,.9])
    plt.subplots_adjust(wspace=0, left=.1,right=.99,bottom=.25, top=.96)

@plot
def ed_dNdzdpTK():
    fig, axes = plt.subplots(1,4,figsize=(1.3*textwidth,textwidth*.4), sharex=True,sharey=True)

    b = np.linspace(0,1,10)
    x = (b[:-1]+b[1:])/2.
    dx = b[1:]-b[:-1]
    Ne = 1e6
    axes[0].semilogy()
    pid, z, pT, nu, Q2 = np.loadtxt("Run/Production/ed/1-2-StopM0d0.dat").T
    for ax, zbin in zip(axes,[[.2,.3],[.3,.4],[.4,.6],[.6,.8]]):
        ax.annotate(r"${}<z_h<{}$".format(*zbin), xy=(.1, .9), xycoords="axes fraction")
        for line, color, iid in zip(['-','--'],[cr, cb],[321,-321]):
            cut = (pid==iid) & (zbin[0]<z) & (z<zbin[1])

            Y = np.histogram((pT)[cut],bins=b)[0]/dx/Ne/(zbin[1]-zbin[0])
            ax.plot(x, Y, line, color=color, lw=1, alpha=.8)
            ax.set_xlim(0,1)
            if ax.is_last_row():
                ax.set_xlabel(r"$p_T$ [GeV${}$]")
            if ax.is_first_col():
                ax.set_ylabel(r"$dN/dp_T/dz_h$")
            ax.set_ylim(ymin=0)

    for ax, zbin in zip(axes,[[.2,.3],[.3,.4],[.4,.6],[.6,.8]]):
        for color,iid,n in zip([cr,cb],[321,-321],['K+','K-']):
            x,y,ystat,_,ysys,_ = np.loadtxt("ExpData/pT/ed-{}-z-{}-{}.dat".format(n,*zbin)).T
            ssid = {211:'\pi^+', -211:'\pi^-', 111:'\pi^0',
                       321:'K^+',  -321:'K^-',
                       2212:'p',  -2212:"\\bar{p}"}[iid]
            ax.errorbar(x,y,yerr=ystat, fmt='.', color=darken(color), label=r'HERMES ${}$'.format(ssid)
            )
            xb = [0.]+list((x[1:]+x[:-1])/2.) + [1.]
            for il,ih,yl,yh in zip(xb[:-1],xb[1:],y-ysys,y+ysys):
                ax.fill_between([il,ih],[yl,yl],[yh,yh],
                            edgecolor=darken(color),facecolor='none')
    axes[0].legend(loc=(.03, .1))

    ax.set_ylim(1e-3,1e1)
    ax.set_xlim(0.0,1.1)
    ax.set_xticks([0.,.3,.6,.9])
    plt.subplots_adjust(wspace=0, left=.1,right=.99,bottom=.25, top=.96)

@plot
def ed_dNdz():
    fig = plt.figure(figsize=(1.3*textwidth,.5*textwidth))
    spec = gridspec.GridSpec(ncols=4, nrows=3, figure=fig)
    axes = np.array([
    [fig.add_subplot(spec[:2, i]) for i in range(4)],
    [fig.add_subplot(spec[2, i]) for i in range(4)]
    ])
    name = {211:"$\pi^+$",
           -211:"$\pi^-$",
            321:"$K^+$",
           -321:"$K^-$"}

    for ax,iid,n in zip(axes[0],[211,-211,321,-321],['pi+','pi-','K+','K-']):
        x,y,ystat,_,ysys,_ = np.loadtxt("ExpData/z/ed-{}.dat".format(n)).T
        ax.errorbar(x,y,yerr=ystat,fmt='.', color='k'
           , label=r'HERMES'
           )
        xb = [0.1]+list((x[1:]+x[:-1])/2.) + [.9]
        for il,ih,yl,yh in zip(xb[:-1],xb[1:],y-ysys,y+ysys):
            ax.fill_between([il,ih],[yl,yl],[yh,yh],
                            edgecolor='k',facecolor='none')

    Ne = 1e6
    for stopM, ss, color, label in zip([1.0, 0.0], ('1d0','0d0'), [cr, cb], [r'$M_{\rm stop}=1.0$ GeV', r'$M_{\rm stop}=0$']):
        pid, z, pT, nu, Q2 = np.loadtxt("Run/Production/ed/1-2-StopM{}.dat".format(ss)).T
        for ax,axr,iid in zip(axes[0],axes[1],[211,-211,321,-321]):

            sid = {211:'pi+', -211:'pi-', 111:'pi0',
                       321:'K+',  -321:'K-',
                       2212:'p',  -2212:'pbar'}[iid]
            ssid = {211:'\pi^+', -211:'\pi^-', 111:'\pi^0',
                       321:'K^+',  -321:'K^-',
                       2212:'p',  -2212:"\\bar{p}"}[iid]
            x,y,ystat,_,ysys,_ = np.loadtxt("ExpData/z/ed-{}.dat".format(sid)).T
            xb = [0.1]+list((x[1:]+x[:-1])/2.) + [.9]
            xb = np.array(xb)
            x = (xb[:-1]+xb[1:])/2.
            dx  = xb[1:]-xb[:-1]
            cut = (pid==iid)
            Y = np.histogram(z[cut],bins=xb)[0]/dx/Ne
            ax.plot(x, Y, color=color, lw=1,alpha=.8,label=label)
            ax.set_xlim(0.05,1.05)
            axr.set_xlim(0.05,1.05)
            axr.set_xlabel(r"$z_h$")
            if ax.is_first_col():
                ax.set_ylabel(r"$dN/dz_h$")
            if ax.is_first_col():
                axr.set_ylabel("Exp./MC.")
            ax.semilogy()
            ax.set_ylim(5e-5,1e1)

            x,y,ystat,_,ysys,_ = np.loadtxt("ExpData/z/ed-{}.dat".format(sid)).T
            y/=Y
            ystat/=Y
            ysys /= Y
            axr.errorbar(x,y,yerr=ystat,fmt='.', color=color,label=label)
            xb = [0.]+list((x[1:]+x[:-1])/2.) + [1.]
            for il,ih,yl,yh in zip(xb[:-1],xb[1:],y-ysys,y+ysys):
                axr.fill_between([il,ih],[yl,yl],[yh,yh],
                            edgecolor=color,facecolor='none')
            axr.plot([0,1.05],[1,1],'k--', lw=.6)
            axr.set_ylim(0,2.3)
            ax.annotate(r"${}$".format(ssid), xy=(.6,.8), xycoords="axes fraction")
            if ax.is_first_col():
                pass
                #ax.legend()
            else:
                ax.set_yticklabels([])
            ax.set_xticklabels([])
            if axr.is_first_col():
                pass
                #axr.legend()
            else:
                axr.set_yticklabels([])
    axes[0,0].legend()
    #for i in [0,1]:
    #    axes[i].set_ylim(1e-2,5)
    #for i in [2,3]:
    #    axes[i].set_ylim(1e-2,1)
    plt.subplots_adjust(wspace=.0, hspace=.0, left=.1, right=.97, bottom=.2, top=.97)

def RA_z(iid):
    sid = {211:'pi+', -211:'pi-', 111:'pi0',
           321:'K+',  -321:'K-',
           2212:'p',  -2212:'pbar'}[iid]
    ssid = {211:'\pi^+', -211:'\pi^-', 111:'\pi^0',
           321:'K^+',  -321:'K^-',
           2212:'p',  -2212:"\\bar{p}"}[iid]
    fig, ax = plt.subplots(1,1,figsize=(.55*textwidth,.5*textwidth), sharey=True,sharex=True)
    for N,color,Z,A in zip(*NCZA):
        x,xl,xh,y,ystat,_,ysys,_ = \
       np.loadtxt("Exp/HERMES/SIDIS/RA_z/e{}-{}.dat".format(N,sid),
                 skiprows=12,
                 delimiter=',').T
        ax.errorbar(x,y,yerr=ystat,fmt='.', color=darken(color),
                 label=r'HERMES ${{}}^{{{:d}}}${:s}'.format(A,N))
        for il,ih,yl,yh in zip(xl,xh,y-ysys,y+ysys):
            ax.fill_between([il,ih],[yl,yl],[yh,yh],
                            edgecolor=darken(color),facecolor='none')

    bins = np.array(list(xl)+[xh[-1]])
    db = bins[1:]-bins[:-1]
    zm = x#(bins[1:]+bins[:-1])/2.
    pid, z, pT, nu, Q2 = samples['d']#np.loadtxt(folder+"/1-2-cutRA.dat").T
    cut = (pid==iid) & (nu>6)
    Y0 = np.histogram(z[cut],bins=bins)[0]/db
    for N,color,Z,A in zip(*NCZA):
        pid, z, pT, nu, Q2 = samples[N]
        #np.loadtxt(folder+"/{}-{}-cutRA.dat".format(Z,A)).T
        cut = ( pid==iid ) & (nu>6)
        Y = np.histogram(z[cut],bins=bins)[0]/db
        ax.plot(zm, Y/Y0, color=color, alpha=.7)
    ax.set_xlim(.0,1.05)
    ax.plot([.0,1.5],[1,1],'k-',lw=.3)

    ax.legend(loc='lower left')
    ax.set_ylim(0,1.5)
    ax.set_xlabel(r"$z_h=E_h/\nu$ in target frame")
    ax.set_ylabel(r"$R_{{A}}$")
    ax.annotate(r"${:s}$".format(ssid),xy=(.07,.9),xycoords="axes fraction")
    set_tight(fig, pad=.2)

def RA_pT(iid):
    sid = {211:'pi+', -211:'pi-', 111:'pi0',
           321:'K+',  -321:'K-',
           2212:'p',  -2212:'pbar'}[iid]
    ssid = {211:'\pi^+', -211:'\pi^-', 111:'\pi^0',
           321:'K^+',  -321:'K^-',
           2212:'p',  -2212:"\\bar{p}"}[iid]
    fig, ax = plt.subplots(1,1,figsize=(.55*textwidth,.5*textwidth), sharey=False,sharex=True)

    for N,color,Z,A in zip(*NCZA):
        x,xl,xh,y,ystat,_,ysys,_ = \
            np.loadtxt("Exp/HERMES/SIDIS/RA_pT2/e{}-{}.dat".format(N,sid),
            #skiprows=12,
            delimiter=',').T
        ax.errorbar(x,y,yerr=ystat,fmt='.', color=darken(color),
                 label=r'HERMES ${{}}^{{{:d}}}${:s}'.format(A,N))
        for il,ih,yl,yh in zip(xl,xh,y-ysys,y+ysys):
            ax.fill_between([il,ih],[yl,yl],[yh,yh],
                            edgecolor=darken(color),facecolor='none')

    b = np.array(list(xl)+[xh[-1]])
    x = x
    dx = b[1:]-b[:-1]
    zmin = 0.2
    pid, z, pT, nu, Q2 = samples['d']#np.loadtxt(folder+"/1-2-cutRA.dat").T
    cut = (pid == iid) & (z>zmin) & (nu>6)
    Y0 = np.histogram((pT**2)[cut],bins=b)[0]/dx
    for N,color,Z,A in zip(*NCZA):
        pid, z, pT, nu, Q2 = samples[N]#np.loadtxt(folder+"/{}-{}-cutRA.dat".format(Z,A)).T
        cut = (pid == iid) & (z>zmin)& (nu>6)
        Y = np.histogram((pT**2)[cut],bins=b)[0]/dx
        ax.plot(x, Y/Y0, color=color, lw=1,alpha=.8)
    ax.plot([1e-2,10],[1,1],'k-', lw=.5)
    ax.set_xlim(0,2)
    ax.set_ylim(.4,2.1)
    ax.set_xlabel(r"$p_T^2$ [GeV${}^2$]")
    ax.set_ylabel(r"$R_{A}$")
    ax.legend(loc="upper left")
    ax.annotate(r"${:s}$".format(ssid),xy=(.6,.9),xycoords="axes fraction")
    set_tight(fig,pad=0.2)

def RA_nu(iid):
    sid = {211:'pi+', -211:'pi-', 111:'pi0',
           321:'K+',  -321:'K-',
           2212:'p',  -2212:'pbar'}[iid]
    ssid = {211:'\pi^+', -211:'\pi^-', 111:'\pi^0',
           321:'K^+',  -321:'K^-',
           2212:'p',  -2212:"\\bar{p}"}[iid]
    fig, ax = plt.subplots(1,1,figsize=(.55*textwidth,.5*textwidth), sharey=False,sharex=True)

    for N,color,Z,A in zip(*NCZA):
        x,xl,xh,y,ystat,_,ysys,_ = \
            np.loadtxt("Exp/HERMES/SIDIS/RA_nu/e{}-{}.dat".format(N,sid),
            #skiprows=12,
            delimiter=',').T
        ax.errorbar(x,y,yerr=ystat,fmt='.', color=darken(color),
                 label=r'HERMES ${{}}^{{{:d}}}${:s}'.format(A,N))
        for il,ih,yl,yh in zip(xl,xh,y-ysys,y+ysys):
            ax.fill_between([il,ih],[yl,yl],[yh,yh],
                            edgecolor=darken(color),facecolor='none')

    b = np.array(list(xl)+[xh[-1]])
    x = x
    dx = b[1:]-b[:-1]
    zmin = 0.2
    pid, z, pT, nu, Q2 = samples['d']#np.loadtxt(folder+"/1-2-cutRA.dat").T
    cut = (pid == iid) & (z>zmin)
    Y0 = np.histogram(nu[cut],bins=b)[0]/dx
    for N,color,Z, A in zip(*NCZA):
        pid, z, pT, nu, Q2 = samples[N]#np.loadtxt(folder+"/{}-{}-cutRA.dat".format(Z,A)).T
        cut = (pid == iid) & (z>zmin)
        Y = np.histogram(nu[cut],bins=b)[0]/dx
        ax.plot(x, Y/Y0, color=color, lw=1,alpha=.8)
    ax.plot([0,25],[1,1],'k-', lw=.5)
    ax.set_xlim(0,25)
    ax.set_ylim(0,1.5)
    ax.set_xlabel(r"$\nu$ [GeV]")
    ax.set_ylabel(r"$R_{A}$")
    ax.legend(loc="lower right")
    ax.annotate(r"${:s}$".format(ssid),xy=(.6,.9),xycoords="axes fraction")
    set_tight(fig,pad=0.2)

def RA_Q2(iid):
    sid = {211:'pi+', -211:'pi-', 111:'pi0',
           321:'K+',  -321:'K-',
           2212:'p',  -2212:'pbar'}[iid]
    ssid = {211:'\pi^+', -211:'\pi^-', 111:'\pi^0',
           321:'K^+',  -321:'K^-',
           2212:'p',  -2212:"\\bar{p}"}[iid]
    fig, ax = plt.subplots(1,1,figsize=(.55*textwidth,.5*textwidth), sharey=False,sharex=True)

    for N,color,Z,A in zip(*NCZA):
        x,xl,xh,y,ystat,_,ysys,_ = \
            np.loadtxt("Exp/HERMES/SIDIS/RA_Q2/e{}-{}.dat".format(N,sid),
            #skiprows=12,
            delimiter=',').T
        ax.errorbar(x,y,yerr=ystat,fmt='.', color=darken(color),
                 label=r'HERMES ${{}}^{{{:d}}}${:s}'.format(A,N))
        for il,ih,yl,yh in zip(xl,xh,y-ysys,y+ysys):
            ax.fill_between([il,ih],[yl,yl],[yh,yh],
                            edgecolor=darken(color),facecolor='none')

    b = np.array(list(xl)+[xh[-1]])
    x = x#(b[:-1]+b[1:])/2.
    dx = b[1:]-b[:-1]
    zmin = 0.2
    pid, z, pT, nu, Q2 =samples['d']# np.loadtxt(folder+"/1-2-cutRA.dat").T
    cut = (pid == iid) & (z>zmin) & (nu>6)
    Y0 = np.histogram(Q2[cut],bins=b)[0]/dx
    for N,color,Z,A in zip(*NCZA):
        pid, z, pT, nu, Q2 = samples[N]#np.loadtxt(folder+"/{}-{}-cutRA.dat".format(Z,A)).T
        cut = (pid == iid) & (z>zmin) & (nu>6)
        Y = np.histogram(Q2[cut],bins=b)[0]/dx

        ax.plot(x, Y/Y0, color=color, lw=1,alpha=.8)
    ax.plot([0.5,25],[1,1],'k-', lw=.5)
    ax.set_xlim(.5,25)
    ax.set_ylim(0,1.5)
    ax.semilogx()
    ax.set_xlabel(r"$Q^2$ [GeV${}^2$]")
    ax.set_ylabel(r"$R_{A}$")
    ax.legend(loc="lower left")
    ax.annotate(r"${:s}$".format(ssid),xy=(.6,.9),xycoords="axes fraction")
    set_tight(fig,pad=0.2)
@plot
def RpT_pi0():
    RA_pT(111)
@plot
def RpT_pip():
    RA_pT(211)
@plot
def RpT_pim():
    RA_pT(-211)
@plot
def RpT_Kp():
    RA_pT(321)
@plot
def RpT_Km():
    RA_pT(-321)
@plot
def RpT_p():
    RA_pT(2212)
@plot
def RpT_pbar():
    RA_pT(-2212)
@plot
def RQ2_pi0():
    RA_Q2(111)
@plot
def RQ2_pip():
    RA_Q2(211)
@plot
def RQ2_pim():
    RA_Q2(-211)
@plot
def RQ2_Kp():
    RA_Q2(321)
@plot
def RQ2_Km():
    RA_Q2(-321)
@plot
def RQ2_p():
    RA_Q2(2212)
@plot
def RQ2_pbar():
    RA_Q2(-2212)

@plot
def Rnu_pi0():
    RA_nu(111)
@plot
def Rnu_pip():
    RA_nu(211)
@plot
def Rnu_pim():
    RA_nu(-211)
@plot
def Rnu_Kp():
    RA_nu(321)
@plot
def Rnu_Km():
    RA_nu(-321)
@plot
def Rnu_p():
    RA_nu(2212)
@plot
def Rnu_pbar():
    RA_nu(-2212)

@plot
def Rz_pi0():
    RA_z(111)
@plot
def Rz_pip():
    RA_z(211)
@plot
def Rz_pim():
    RA_z(-211)
@plot
def Rz_Kp():
    RA_z(321)
@plot
def Rz_Km():
    RA_z(-321)
@plot
def Rz_p():
    RA_z(2212)
@plot
def Rz_pbar():
    RA_z(-2212)

@plot
def Other_Qs():
    Tamin = 0.1/5.076**2
    Tamax = 2.8/5.076**2
    Ta = np.linspace(Tamin, Tamax, 51)
    lnQ2x = np.linspace(np.log(1), np.log(1e5), 51)
    Qs2_data = np.loadtxt("Run/Tables/Qs.dat").reshape(51,51)
    from scipy.interpolate import interp1d

    fig, ax = plt.subplots(1,1, figsize=(textwidth*.4, textwidth*.4))
    x = np.exp(np.linspace(-4.1,0,21))
    for ita, c in zip([-1,10],[cb,cr]):
        ta = Ta[ita]
        Qs2 = interp1d(lnQ2x, Qs2_data[ita])
        y1 = Qs2( np.log(4/x))
        y2 = Qs2( np.log(16/x))
        ax.plot(x, y1, '-', color=c, label='$Q=2$ GeV')
        ax.plot(x, y2, '--', color=c, label='$Q=4$ GeV')
        ax.fill_between(x, y1, y2, color=c, alpha=.3)
    ax.legend()
    ax.set_ylabel(r"$Q_S^2$ [GeV${}$]")
    ax.set_xlabel(r"$x_B$")
    ax.set_xlim(1e-2,1)
    ax.set_ylim(0,4)
    ax.annotate(r"$T_A={:1.2f}$ [fm${{}}^{{-2}}$]".format(Ta[-1]*5.076**2),
               xy=(.1, .88), xycoords="axes fraction", color=cb, fontsize=5)
    ax.annotate(r"$T_A={:1.2f}$ [fm${{}}^{{-2}}$]".format(Ta[5]*5.076**2),
               xy=(.1, .75), xycoords="axes fraction", color=cr, fontsize=5)
    ax.semilogx()
    plt.tight_layout(True)

@plot
def Other_qhat():
    Tamin = 0.02/5.076**2
    Tamax = 2.8/5.076**2
    Ta = np.linspace(Tamin, Tamax, 51)
    lnQ2x = np.linspace(np.log(1), np.log(1e5), 51)
    Qs2_data = np.loadtxt("Run/Tables/Qs.dat").reshape(51,51)
    from scipy.interpolate import interp1d
    rho0 = 0.17/5.076**3
    fig, ax = plt.subplots(1,1, figsize=(textwidth*.4, textwidth*.4))
    x = np.exp(np.linspace(-4.1,0,21))
    for ita, c in zip([-1,10],[cb,cr]):
        ta = Ta[ita]
        Qs2 = interp1d(lnQ2x, Qs2_data[ita])
        y1 = Qs2( np.log(4/x))/ta*rho0 * 5.076 * 4/9
        y2 = Qs2( np.log(16/x))/ta*rho0 * 5.076 * 4/9
        ax.plot(x, y1, '-', color=c, label='$Q=2$ GeV')
        ax.plot(x, y2, '--', color=c, label='$Q=4$ GeV')
        ax.fill_between(x, y1, y2, color=c, alpha=.3)
    ax.legend()
    ax.set_ylabel(r"$\hat{q}_F$ [GeV${}^2$/fm]")
    ax.set_xlabel(r"$x_q$")
    ax.set_xlim(1e-2,1)
    ax.set_ylim(0,.06)
    #ax.set_yticks([0,.01,.02, .03])
    ax.annotate(r"$T_A={:1.2f}$ [fm${{}}^{{-2}}$]".format(Ta[-1]*5.076**2),
               xy=(.1, .88), xycoords="axes fraction", color=cb, fontsize=5)
    ax.annotate(r"$T_A={:1.2f}$ [fm${{}}^{{-2}}$]".format(Ta[5]*5.076**2),
               xy=(.1, .75), xycoords="axes fraction", color=cr, fontsize=5)
    ax.semilogx()
    plt.tight_layout(True)

@plot
def Other_xG():
    #fig, ax = plt.subplots(1,1, )
    x = np.exp(np.linspace(-4.6,0,21))
    kT = np.exp(np.linspace(-2.3,2.3,21))
    xG = np.loadtxt("/home/weiyao/Research/TMDlib/tmdlib-2.2.01/examples-c++/xG.dat")
    #for ikT, ixG in zip(kT, xG.T):
    #    ax.plot(x+ikT, ixG+ikT, 'r-')

    from matplotlib import cm
    from matplotlib.ticker import LinearLocator
    from mpl_toolkits.mplot3d import Axes3D
    fig = plt.figure(figsize=(textwidth*.5, textwidth*.5))
    ax = fig.add_subplot(projection='3d',
                      )

    X, Y = np.meshgrid(np.log(x), np.log(kT))
    X = X.T
    Y = Y.T
    # Plot the surface.
    surf = ax.plot_surface(X, Y, xG, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)

    #ax.semilogx()
    ax.set_xlim(np.log(.01), 0)
    ax.set_ylim(-2.3,2.3)
    ax.set_ylabel(r"$k_T$ [GeV]")
    ax.set_title(r"$xG(x, k_T, \mu=5 {\rm~GeV})$")
    ax.set_xlabel(r"$x$")
    ax.view_init(30,50)
    #ax.xaxis.set_scale('log')
    # Add a color bar which maps values to colors.
    #fig.colorbar(surf, shrink=0.5, aspect=5)
    ax.set_xticks([np.log(0.01), np.log(.1), np.log(1)])
    ax.set_xticklabels([r"$10^{-2}$", r"$10^{-1}$",r"$10^{0}$"])
    ax.set_yticks([np.log(0.1), np.log(1), np.log(10)])
    ax.set_yticklabels([r"$10^{-1}$", r"$10^{0}$",r"$10^{1}$"])
    set_tight(fig, pad=0.5, rect=[.05,.12,1,1])
if __name__ == '__main__':
    import argparse

    choices = list(plot_functions)

    def arg_to_plot(arg):
        arg = Path(arg).stem
        if arg not in choices:
            raise argparse.ArgumentTypeError(arg)
        return arg

    parser = argparse.ArgumentParser(description='generate plots')
    parser.add_argument(
        'plots', nargs='*', type=arg_to_plot, metavar='PLOT',
        help='{} (default: all)'.format(', '.join(choices).join('{}'))
    )
    args = parser.parse_args()

    if args.plots:
        for p in args.plots:
            plot_functions[p]()
    else:
        for it, f in zip(plot_functions.keys(), plot_functions.values()):
            print("Generating ", it+".png")
            f()


#!/usr/bin/python3
def divisible_by_2(my_list=[]):
    """Check if number is divisible by 2"""
    multiple = []
    for num in my_list:
        if num % 2 == 0:
            multiple.append(True)
        else:
            multiple.append(False)
    return (multiple)


# this file makes the website folder a python package
# it imports the folder and whatever is inside the init.py will run automatically
# the __init__.py specifically makes the folder a python package that can
# be imported into other files
# sets up flask application
from os import path
from flask import Flask
from flask_sqlalchemy import SQLAlchemy # used for the database
from flask_login import LoginManager

db = SQLAlchemy() # initializes and defines a new db
DB_NAME = "database.db" # names the database database.db

def create_app():
  application = Flask(__name__)
  application.config['SECRET_KEY'] = 'hellohello' # secret key for my app
  application.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_NAME}' # python code inside squiggly brackets and is evaluated as a string
  # code above, SQLAlchemy database is stored at sqlite:///{dbname} location
  # it stores the database in the website folder
  # now initialize db by giving it our flask app
  db.init_app(application)

  # now we define database models - the schema of what this db will look like

  # we then have to register our blueprints in init.py
  # we have to tell flask we have views and routes for the app, so here's where they are
  from .views import views
  from .auth import auth
  # then we register the blueprints with our flask app
  application.register_blueprint(views, url_prefix='/')
  application.register_blueprint(auth, url_prefix='/')
  # what the lines above are saying is all the url's that are stored inside of these blueprints file, how do we access them

  # after registering the blueprints and models.py schema is setup, we return here and create the database
  # we import models so that it defines the classes in models.py
  from .models import User, Note

  create_database(application)

  login_manager = LoginManager() # helps manage users
  login_manager.login_view = 'auth.login' # so should flask redirect us if not logged in?
  login_manager.init_app(application) # tells the login manager which app we are using

  @login_manager.user_loader # this tells flask how we load a user
  def load_user(id):
    return User.query.get(int(id)) # works similar to filter by, except by default query.get looks for the primary key, which checks the int version of whatever id is passed into load_user(id)

  return application

def create_database(application): # checks if database exists, if not, create one, if yes, don't override it because it has data in it already
  if not path.exists('website/' + DB_NAME):
    db.create_all(app=application)
    print('Created Database!')


import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
import re, string
import os

class PropertiesClassification:
    __instance = None

    # carregando o dataset apartir do diretório de trabalho da aplicação
    __workDir = os.getcwd()
    train = pd.read_csv(__workDir + r'/dataset-processed.csv')

    # inserindo rotulos
    label_cols = ['programacao orientada a objeto', 'linguagem de marcacao', 'banco de dados', 'linguagem de script']
    train['none'] = 1-train[label_cols].max(axis=1)

    # eliminando vazios
    CONTENT = 'content'
    train[CONTENT].fillna("unknown", inplace=True)

    # criando um saco de palavras
    def __tokenize(s):
        re_tok = re.compile(f'([{string.punctuation}“”¨«»®´·º½¾¿¡§£₤‘’])')
        return re_tok.sub(r' \1 ', s).split()

    # vetorizando com tf-idf
    vec = TfidfVectorizer(ngram_range=(1,2), tokenizer=__tokenize,
            min_df=3, max_df=0.9, strip_accents='unicode',
                use_idf=1, smooth_idf=1, sublinear_tf=1)

    # criando matriz esparca de numeros
    trn_term_doc = vec.fit_transform(train[CONTENT])

    @staticmethod
    def instance():
        if not PropertiesClassification.__instance:
            PropertiesClassification.__instance = PropertiesClassification()
        return PropertiesClassification.__instance


from .base import PlatformEventLoop

from pyglet.libs.win32 import _kernel32, _user32, types, constants
from pyglet.libs.win32.types import *

class Win32EventLoop(PlatformEventLoop):
    def __init__(self):
        super(Win32EventLoop, self).__init__()

        self._next_idle_time = None

        # Force immediate creation of an event queue on this thread -- note
        # that since event loop is created on pyglet.app import, whatever
        # imports pyglet.app _must_ own the main run loop.
        msg = types.MSG()
        _user32.PeekMessageW(ctypes.byref(msg), 0,
                             constants.WM_USER, constants.WM_USER,
                             constants.PM_NOREMOVE)

        self._event_thread = _kernel32.GetCurrentThreadId()

        self._wait_objects = []
        self._recreate_wait_objects_array()

        self._timer_proc = types.TIMERPROC(self._timer_proc_func)
        self._timer = _user32.SetTimer(0, 0, constants.USER_TIMER_MAXIMUM, self._timer_proc)

        self._timer_func = None

    def add_wait_object(self, obj, func):
        self._wait_objects.append((obj, func))
        self._recreate_wait_objects_array()

    def remove_wait_object(self, obj):
        for i, (_object, _) in enumerate(self._wait_objects):
            if obj == _object:
                del self._wait_objects[i]
                break
        self._recreate_wait_objects_array()

    def _recreate_wait_objects_array(self):
        if not self._wait_objects:
            self._wait_objects_n = 0
            self._wait_objects_array = None
            return

        self._wait_objects_n = len(self._wait_objects)
        self._wait_objects_array = \
            (HANDLE * self._wait_objects_n)(*[o for o, f in self._wait_objects])

    def start(self):
        if _kernel32.GetCurrentThreadId() != self._event_thread:
            raise RuntimeError('EventLoop.run() must be called from the same ' +
                               'thread that imports pyglet.app')

        self._timer_func = None
        self._polling = False
        self._allow_polling = True

    def step(self, timeout=None):
        self.dispatch_posted_events()

        msg = types.MSG()
        if timeout is None:
            timeout = constants.INFINITE
        else:
            timeout = int(timeout * 1000) # milliseconds

        result = _user32.MsgWaitForMultipleObjects(
            self._wait_objects_n,
            self._wait_objects_array,
            False,
            timeout,
            constants.QS_ALLINPUT)
        result -= constants.WAIT_OBJECT_0

        if result == self._wait_objects_n:
            while _user32.PeekMessageW(ctypes.byref(msg),
                                       0, 0, 0, constants.PM_REMOVE):
                _user32.TranslateMessage(ctypes.byref(msg))
                _user32.DispatchMessageW(ctypes.byref(msg))
        elif 0 <= result < self._wait_objects_n:
            obj, func = self._wait_objects[result]
            func()

        # Return True if timeout was interrupted.
        return result <= self._wait_objects_n

    def notify(self):
        # Nudge the event loop with a message it will discard.  Note that only
        # user events are actually posted.  The posted event will not
        # interrupt the window move/size drag loop -- it seems there's no way
        # to do this.
        _user32.PostThreadMessageW(self._event_thread, constants.WM_USER, 0, 0)

    def set_timer(self, func, interval):
        if func is None or interval is None:
            interval = constants.USER_TIMER_MAXIMUM
        else:
            interval = int(interval * 1000) # milliseconds

        self._timer_func = func
        _user32.SetTimer(0, self._timer, interval, self._timer_proc)

    def _timer_proc_func(self, hwnd, msg, timer, t):
        if self._timer_func:
            self._timer_func()


"""Move internal account target relationship

Revision ID: 4c430b37b01d
Revises: ea1ac3bfdff9
Create Date: 2020-03-25 23:58:55.645872

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
from lucrum import database

revision = '4c430b37b01d'
down_revision = 'ea1ac3bfdff9'
branch_labels = None
depends_on = None

def upgrade():
	# ### commands auto generated by Alembic - please adjust! ###
	with op.batch_alter_table('account', schema=None) as batch_op:
		batch_op.add_column(sa.Column('target_id', sa.Integer(), nullable=False, default=1))
		batch_op.create_foreign_key(batch_op.f('fk_account_target_id_target'), 'target', ['target_id'], ['id'])

	with op.batch_alter_table('target', schema=None) as batch_op:
		batch_op.drop_constraint('fk_target_internal_account_id_account', type_='foreignkey')
		batch_op.drop_column('internal_account_id')

	# ### end Alembic commands ###

def downgrade():
	# ### commands auto generated by Alembic - please adjust! ###
	with op.batch_alter_table('target', schema=None) as batch_op:
		batch_op.add_column(sa.Column('internal_account_id', sa.INTEGER(), nullable=True))
		batch_op.create_foreign_key('fk_target_internal_account_id_account', 'account', ['internal_account_id'], ['id'])

	with op.batch_alter_table('account', schema=None) as batch_op:
		batch_op.drop_constraint(batch_op.f('fk_account_target_id_target'), type_='foreignkey')
		batch_op.drop_column('target_id')

	# ### end Alembic commands ###


# recursive DFS version
def dfs_rec(adjLists, visited, v):
    visited[v] = True
    print(v, " ", end='')
    for w in adjLists[v]:
        if(not visited[w]):
            dfs_rec(adjLists, visited, w)

# Usually dfs_rec() would be sufficient. However, if we don't want to pass
# a boolean array to our function, we can use another function dfs().
# We only have to pass the adjacency list and the source node to dfs(),
#as opposed to dfs_rec(), where we have to pass the boolean array additionally.
def dfs(adjLists, s):
    visited = []
    n = len(adjLists)
    for i in range(n):
        visited.append(False)
    dfs_rec(adjLists, visited, s)

# ------------------------------------------------------------------

# create the graph in adjacency list representation
adjLists = [ [1,2,3], [5,6], [4], [2,4], [1], [], [4] ]

# test our implementation
dfs(adjLists, 0)

def dfs_iterative(adjLists, s):
    stack = []
    stack.append(s)
    n = len(adjLists)
    visited = []
    for i in range(0,n):
        visited.append(False)

    while(len(stack)>0):
        v = stack.pop()
        if(not visited[v]):
            visited[v] = True
            print(v, " ", end='')

            # auxiliary stack to visit neighbors in the order they appear
            # in the adjacency list
            # alternatively: iterate through the adjacency list in reverse order
            # but this is only to get the same output as the recursive dfs
            # otherwise, this would not be necessary
            stack_aux = []
            for w in adjLists[v]:
                if(not visited[w]):
                    stack_aux.append(w)
            while(len(stack_aux)>0):
                stack.append(stack_aux.pop())

# ------------------------------------------------------------------

# create the graph in adjacency list representation
adjLists = [ [1,2,3], [5,6], [4], [2,4], [1], [], [4] ]

# test our implementation
dfs_iterative(adjLists, 0)


from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
import time
import random
from u2be_json import *

class scraping_u2:
	page_source = ''
	def __init__(self, url_text):
		self.url_text = url_text
	#display all the comments and replays
	def display_all_the_comments(self):
		self.driver = webdriver.Firefox()
		self.driver.get(self.url_text)
		##parar el video
		video2 = self.driver.find_element_by_class_name("ytp-play-button.ytp-button")
		video2.click()
		i=0
		ultima_medida = self.driver.execute_script("return document.documentElement.scrollHeight;")
		#bucle para desplazarnos hacia abajo
		while True:
			#bucle para desplazarnos poco a poco
			while i <= ultima_medida:
				cadena_medida = "window.scrollTo(0," + str(i) + ");"
				self.driver.execute_script(cadena_medida)
				#el incremento lo hacemos ramdon para que no sospechen
				incremento = random.randint(50,100)
				i = i + incremento
				#el tiempo de espera tambien
				tiempo_espera = random.uniform(0.4,0.5)
				time.sleep(tiempo_espera)
			nueva_medida = self.driver.execute_script("return document.documentElement.scrollHeight;")
			if nueva_medida == ultima_medida:
				break
			ultima_medida = nueva_medida
		body = self.driver.find_element_by_xpath("/html/body")
		#buscamos los id more-text que es para ver las contestaciones
		more_text = self.driver.find_elements_by_xpath("//*[@id='more-text']")
		#damos click a todas los comentarios con contestación
		for dale in more_text:
			dale.click()
			time.sleep(0.5)
		#comentarios siguientes
		continuacion = self.driver.find_elements_by_xpath("//yt-formatted-string[contains(concat(' ',normalize-space(@class),' '),'style-scope yt-next-continuation')]")
		for conti in continuacion:
			conti.click()
			time.sleep(0.5)
		self.page_source =self.driver.page_source
		self.get_comments()
	#get al the comments in a diccionary
	def get_comments(self):
		#we load the object u2be_json with the source fo the web page
		self.objeto_u2be = u2be_json(self.page_source)
		self.objeto_u2be.load_script()
		self.objeto_u2be.video_data()
		self.objeto_u2be.video_comments()


#%matplotlib inline

"""
Matplotlib Animation Example

author: Jake Vanderplas
email: vanderplas@astro.washington.edu
website: http://jakevdp.github.com
license: BSD
Please feel free to use and modify this, but keep the above information. Thanks!
"""

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation, rc
rc('animation', html='html5')

from mpl_toolkits.mplot3d import axes3d

from IPython.display import HTML

def toXYZ(vectors):
    # transform vectors to X, Y, Z form
    vectors = np.array(vectors).T
    #X, Y, Z = vectors

    origins = np.zeros(shape=vectors.shape)

    return vectors, origins # X, Y, Z

def draw_vectors_2d(vectors, origins, fig):
    X, Y = origins
    U, V = vectors

    ax = fig.add_subplot(111)
    eps = 0.1
    ax.set_xlim([U.min() - eps, U.max() + eps])
    ax.set_ylim([V.min() - eps, V.max() + eps])

    ax.set_title("2D vectors",fontsize=14)
    ax.set_xlabel("x",fontsize=12)
    ax.set_ylabel("y",fontsize=12)
    ax.grid(True,linestyle='--',color='0.75')

    ax.quiver(X, Y, U, V, color='rrggbbkkccmmyy', angles='xy', scale_units='xy', scale=1)

    plt.show()

def draw_vectors_3d(vectors, origins, fig):
    # First set up the figure, the axis, and the plot element we want to animate
    ax = fig.add_subplot(111, projection='3d')
    line, = ax.plot([], [], lw=2)

    # initialization function: plot the background of each frame
    def init():
        line.set_data([], [])
        return line,

    # animation function.  This is called sequentially
    def animate(i):
        #x = np.linspace(0, 2, 1000)
        #y = np.sin(2 * np.pi * (x - 0.01 * i))
        #line.set_data(x, y)
        angle = 2
        ax.view_init(elev=None, azim=i*angle)

        return line,

    a1 = [1, 0, 0]
    b1 = [0, 1, 0]
    c1 = [0, 0, 1]
    d1 = np.sum([a1, b1, c1], axis=1)

    # transform vectors to X, Y, Z form
    #vectors = np.array([a1, b1, c1, d1]).T
    #print(vectors)
    U, W, V = vectors
    #origins = np.zeros(shape=vectors.shape)
    X, Y, Z = origins

    #ax.plot(X, Y, Z)
    ax.quiver(X, Y, Z, U, V, W, color='rgbkcmy') # up to 7 different vector colors

    eps = 0.1
    ax.set_xlim([U.min() - eps, U.max() + eps])
    ax.set_ylim([V.min() - eps, V.max() + eps])
    ax.set_zlim([V.min() - eps, V.max() + eps])

    ax.set_title("3D vectors",fontsize=14)
    ax.set_xlabel("x",fontsize=12)
    ax.set_ylabel("y",fontsize=12)
    ax.set_zlabel("z",fontsize=12)
    ax.grid(True,linestyle='--',color='0.75')

    # call the animator.  blit=True means only re-draw the parts that have changed.
    anim = animation.FuncAnimation(fig, animate, init_func=init,
                                   frames=180, interval=100, repeat=True, blit=True)

    # save the animation as an mp4.  This requires ffmpeg or mencoder to be
    # installed.  The extra_args ensure that the x264 codec is used, so that
    # the video can be embedded in html5.  You may need to adjust this for
    # your system: for more information, see
    # http://matplotlib.sourceforge.net/api/animation_api.html
    anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])

    #plt.show()

    plt.close()
    return HTML(anim.to_html5_video())

Machine Learning Summer School/Session1/LinealAlgebra/Linearity and vectors/drawing.py