<commit_before>"""
A Trie/Prefix Tree is a kind of search tree used to provide quick lookup
of words/patterns in a set of words. A basic Trie however has O(n^2) space complexity
making it impractical in practice. It however provides O(max(search_string, length of
longest word)) lookup time making it an optimal approach when space is not an issue.
"""

class TrieNode:
    def __init__(self):
        self.nodes = dict()  # Mapping from char to TrieNode
        self.is_leaf = False

    def insert_many(self, words: list[str]):
        """
        Inserts a list of words into the Trie
        :param words: list of string words
        :return: None
        """
        for word in words:
            self.insert(word)

    def insert(self, word: str):
        """
        Inserts a word into the Trie
        :param word: word to be inserted
        :return: None
        """
        curr = self
        for char in word:
            if char not in curr.nodes:
                curr.nodes[char] = TrieNode()
            curr = curr.nodes[char]
        curr.is_leaf = True

    def find(self, word: str) -> bool:
        """
        Tries to find word in a Trie
        :param word: word to look for
        :return: Returns True if word is found, False otherwise
        """
        curr = self
        for char in word:
            if char not in curr.nodes:
                return False
            curr = curr.nodes[char]
        return curr.is_leaf

    def delete(self, word: str):
        """
        Deletes a word in a Trie
        :param word: word to delete
        :return: None
        """

        def _delete(curr: TrieNode, word: str, index: int):
            if index == len(word):
                # If word does not exist
                if not curr.is_leaf:
                    return False
                curr.is_leaf = False
                return len(curr.nodes) == 0
            char = word[index]
            char_node = curr.nodes.get(char)
            # If char not in current trie node
            if not char_node:
                return False
            # Flag to check if node can be deleted
            delete_curr = _delete(char_node, word, index + 1)
            if delete_curr:
                del curr.nodes[char]
                return len(curr.nodes) == 0
            return delete_curr

        _delete(self, word, 0)

def print_words(node: TrieNode, word: str):
    """
    Prints all the words in a Trie
    :param node: root node of Trie
    :param word: Word variable should be empty at start
    :return: None
    """
    if node.is_leaf:
        print(word, end=" ")

    for key, value in node.nodes.items():
        print_words(value, word + key)

def test_trie():
    words = "banana bananas bandana band apple all beast".split()
    root = TrieNode()
    root.insert_many(words)
    # print_words(root, "")
    assert all(root.find(word) for word in words)
    assert root.find("banana")
    assert not root.find("bandanas")
    assert not root.find("apps")
    assert root.find("apple")
    assert root.find("all")
    root.delete("all")
    assert not root.find("all")
    root.delete("banana")
    assert not root.find("banana")
    assert root.find("bananas")
    return True

def print_results(msg: str, passes: bool) -> None:
    print(str(msg), "works!" if passes else "doesn't work :(")

def pytests():
    assert test_trie()

def main():
    """
    >>> pytests()
    """
    print_results("Testing trie functionality", test_trie())

if __name__ == "__main__":
    main()
<commit_msg>[mypy] Fix type annotations for trie.py (#5022)<commit_after>"""
A Trie/Prefix Tree is a kind of search tree used to provide quick lookup
of words/patterns in a set of words. A basic Trie however has O(n^2) space complexity
making it impractical in practice. It however provides O(max(search_string, length of
longest word)) lookup time making it an optimal approach when space is not an issue.
"""

class TrieNode:
    def __init__(self) -> None:
        self.nodes: dict[str, TrieNode] = dict()  # Mapping from char to TrieNode
        self.is_leaf = False

    def insert_many(self, words: list[str]) -> None:
        """
        Inserts a list of words into the Trie
        :param words: list of string words
        :return: None
        """
        for word in words:
            self.insert(word)

    def insert(self, word: str) -> None:
        """
        Inserts a word into the Trie
        :param word: word to be inserted
        :return: None
        """
        curr = self
        for char in word:
            if char not in curr.nodes:
                curr.nodes[char] = TrieNode()
            curr = curr.nodes[char]
        curr.is_leaf = True

    def find(self, word: str) -> bool:
        """
        Tries to find word in a Trie
        :param word: word to look for
        :return: Returns True if word is found, False otherwise
        """
        curr = self
        for char in word:
            if char not in curr.nodes:
                return False
            curr = curr.nodes[char]
        return curr.is_leaf

    def delete(self, word: str) -> None:
        """
        Deletes a word in a Trie
        :param word: word to delete
        :return: None
        """

        def _delete(curr: TrieNode, word: str, index: int) -> bool:
            if index == len(word):
                # If word does not exist
                if not curr.is_leaf:
                    return False
                curr.is_leaf = False
                return len(curr.nodes) == 0
            char = word[index]
            char_node = curr.nodes.get(char)
            # If char not in current trie node
            if not char_node:
                return False
            # Flag to check if node can be deleted
            delete_curr = _delete(char_node, word, index + 1)
            if delete_curr:
                del curr.nodes[char]
                return len(curr.nodes) == 0
            return delete_curr

        _delete(self, word, 0)

def print_words(node: TrieNode, word: str) -> None:
    """
    Prints all the words in a Trie
    :param node: root node of Trie
    :param word: Word variable should be empty at start
    :return: None
    """
    if node.is_leaf:
        print(word, end=" ")

    for key, value in node.nodes.items():
        print_words(value, word + key)

def test_trie() -> bool:
    words = "banana bananas bandana band apple all beast".split()
    root = TrieNode()
    root.insert_many(words)
    # print_words(root, "")
    assert all(root.find(word) for word in words)
    assert root.find("banana")
    assert not root.find("bandanas")
    assert not root.find("apps")
    assert root.find("apple")
    assert root.find("all")
    root.delete("all")
    assert not root.find("all")
    root.delete("banana")
    assert not root.find("banana")
    assert root.find("bananas")
    return True

def print_results(msg: str, passes: bool) -> None:
    print(str(msg), "works!" if passes else "doesn't work :(")

def pytests() -> None:
    assert test_trie()

def main() -> None:
    """
    >>> pytests()
    """
    print_results("Testing trie functionality", test_trie())

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


<commit_before>import operator

from django.contrib.auth.models import User
from django.db.models import Q

from selectable.base import ModelLookup
from selectable.registry import registry

class UserLookup(ModelLookup):
    model = User
    search_fields = (
        'first_name__icontains',
        'last_name__icontains',
        'email__icontains',
    )

    def get_query(self, request, term):
        qs = self.get_queryset()
        if term:
            search_filters = []
            if len(term.split()) == 1:
                if self.search_fields:
                    for field in self.search_fields:
                        search_filters.append(Q(**{field: term}))
                qs = qs.filter(reduce(operator.or_, search_filters))
            else:
                # Accounts for 'John Doe' term; will compare against get_full_name
                qs = [x for x in qs if term.lower() in x.get_full_name().lower()]
        return qs

    def get_item_value(self, item):
        return item.email

    def get_item_label(self, item):
        return u"%s (%s)" % (item.get_full_name(), item.email)

    def create_item(self, value):
        """We aren't actually creating a new user, we just need to supply the
           email to the form processor
        """
        return value

registry.register(UserLookup)
<commit_msg>Optimize!<commit_after>import operator

from django.contrib.auth.models import User
from django.db.models import Q

from selectable.base import ModelLookup
from selectable.registry import registry

class UserLookup(ModelLookup):
    model = User
    search_fields = (
        'first_name__icontains',
        'last_name__icontains',
        'email__icontains',
    )

    def get_query(self, request, term):
        qs = self.get_queryset()
        if term:
            search_filters = []
            if len(term.split()) == 1:
                if self.search_fields:
                    for field in self.search_fields:
                        search_filters.append(Q(**{field: term}))
                qs = qs.filter(reduce(operator.or_, search_filters))
            else:
                # Accounts for 'John Doe' term; will compare against get_full_name
                term = term.lower()
                qs = [x for x in qs if term in x.get_full_name().lower()]
        return qs

    def get_item_value(self, item):
        return item.email

    def get_item_label(self, item):
        return u"%s (%s)" % (item.get_full_name(), item.email)

    def create_item(self, value):
        """We aren't actually creating a new user, we just need to supply the
           email to the form processor
        """
        return value

registry.register(UserLookup)
<|endoftext|>


<commit_before>from __future__ import division
import game.messages as messages
import game.permissions as permissions
import csv

from datetime import timedelta
from django.http import Http404, HttpResponse
from django.shortcuts import render
from django.template import RequestContext
from helper import renderError
from game.forms import ScoreboardForm
from game.models import Level, Attempt
from portal.models import Class, Teacher, Student

def scoreboard(request):
    """ Renders a page with students' scores. A teacher can see the the visible classes in their
        school. Student's view is restricted to their class if their teacher enabled the
        scoreboard for said class.

    **Context**

    ``RequestContext``
    ``form``
        Form used to choose a class and level to show. Instance of `forms.ScoreboardForm.`
    ``student_data``
        List of lists containing all the data to be stored in the scoreboard table.
    ``headers``
        List of Strings representing the headers of the scoreboard table.

    **Template:**

    :template:`game/scoreboard.html`
    """
    if not permissions.can_see_scoreboard(request.user):
        return renderError(request, messages.noPermissionTitle(), messages.noPermissionScoreboard())

    form, student_data, headers, error_response = create_scoreboard(request)

    if error_response:
        return error_response

    if 'export' in request.POST:
        return get_scoreboard_csv(student_data, headers)
    else:
        return get_scoreboard_view(request, form, student_data, headers)

def get_scoreboard_view(request, form, student_data, headers):
    context = RequestContext(request, {
        'form': form,
        'student_data': student_data,
        'headers': headers,
    })
    return render(request, 'game/scoreboard.html', context_instance=context)

def get_scoreboard_csv(student_data, headers):
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="scoreboard.csv"'

    #remove list element with list of level scores (the following elements hold the same data separately)
    if headers[1] != 'Score':
        for row in student_data:
            del row[3]

    writer = csv.writer(response)
    writer.writerow(headers)
    writer.writerows(student_data)

    return response

def create_scoreboard(request):

    def are_classes_viewable_by_teacher(class_ids, userprofile):
        teachers = Teacher.objects.filter(school=userprofile.teacher.school)
        classes_list = Class.objects.filter(teacher__in=teachers).values_list('id', flat=True)
        for class_id in class_ids:
            if class_id and not class_id in classes_list:
                return False
        return True

    def populate_scoreboard(request):

        # Getting data from the request object
        userprofile = request.user.userprofile
        level_ids = map(int, request.POST.getlist('levels'))
        class_ids = map(int, request.POST.getlist('classes'))

        # Get the list of students and levels to be displayed
        # As the list passed by the multiselect is in order, using a for loop will preserve the order and
        # only get the default levels instead of the custom levels as well
        # Django 1.7 does not support sorting queryset by converting strings to int
        # Django 1.8 supports the use of expressios in order_by, should try using that to write cleaner codes
        # https://docs.djangoproject.com/en/1.8/releases/1.8/#query-expressions-conditional-expressions-and-database-functions

        students = Student.objects.filter(class_field__id__in = class_ids)

        levels = Level.objects.filter(id__in=level_ids)

        # Check that all the classes selected are valid
        if is_teacher(userprofile):
            if not are_classes_viewable_by_teacher(class_ids, userprofile):
                raise Http404

        # Retrieve the class that the student is in, check that the class selected in drop down menu is the same
        # Each student can only be in one class at a time, so there will be only be one element in the list
        elif is_student(userprofile):
            class_ = userprofile.student.class_field
            if class_ids[0] and int(class_ids[0]) != class_.id:
                raise Http404
            students = class_.students.all()
            # If student is not permitted to look at other students' score, it will only show the student's own data
            if not is_viewable(class_):
                students = class_.students.filter(id=userprofile.student.id)
        else:
            raise Http404
        # If there are more than one level to show, show the total score, total time and score of each level
        # Otherwise, show the details of the level (the score, total time, start time and end time)
        if len(level_ids) > 1:
            # Rows: Students from each class
            # Cols: Total Score, Total Time, Level X, ... , Level Y
            headers = get_levels_headers(['Name', 'Total Score', 'Total Time', 'Progress'], levels)
            student_data = multiple_students_multiple_levels(students, level_ids)
        else:
            # Rows: Students from each class
            # Cols: Score, Total Time, Start Time, End Time
            headers = ['Name', 'Score', 'Total Time', 'Start Time', 'Finish Time']
            student_data = multiple_students_one_level(students, level_ids[0])
        return student_data, headers

    def one_row(student, level_id):
        row = [student]

        attempt = Attempt.objects.filter(level__id=level_id, student=student).first()
        if attempt:
            row.append(attempt.score if attempt.score is not None else '')
            row.append(chop_miliseconds(attempt.finish_time - attempt.start_time))
            row.append(attempt.start_time)
            row.append(attempt.finish_time)
        else:
            row.append("")
            row.append("")
            row.append("")
            row.append("")

        return row

    # many_rows return the
    def many_rows(student_data, level_ids):
        threshold = 10.0

        num_levels = len(level_ids)
        for row in student_data:
            student = row[0]
            num_all = num_finished = num_attempted = num_started = 0

            if Attempt.objects.filter(student=student).exists():
                attempts = Attempt.objects.filter(level__id__in=level_ids, student=student)

                attempts_dict = {attempt.level.id : attempt for attempt in attempts}
                for level in level_ids:
                    attempt = attempts_dict.get(level)
                    if attempt:
                        num_all += 1;
                        if attempt.score:
                            if attempt.score >= threshold:
                                num_finished += 1
                            else:
                                num_attempted += 1
                        else:
                            num_started += 1

                        row[1] += attempt.score if attempt.score is not None else 0
                        row[2].append(chop_miliseconds(attempt.finish_time - attempt.start_time))
                        # '-' is used to show that the student has started the level but has not submitted any attempts
                        row.append(attempt.score if attempt.score is not None else '-')
                        row[3].append(attempt.score if attempt.score is not None else '-')
                    else:
                        row[2].append(timedelta(0))
                        row.append("")
                        row[3].append("")

                row[4] = compute_proportions(num_levels, num_started, num_attempted, num_finished)
            else:
                row[3].extend([''] * num_levels)
        for row in student_data:
            row[2] = sum(row[2], timedelta())

        return student_data

    def compute_proportions(num_levels, num_started, num_attempted, num_finished):
        return (num_started/num_levels)*100, (num_attempted/num_levels)*100, (num_finished/num_levels)*100

    # Returns rows of student object with score, start time, end time of the level
    def multiple_students_one_level(students, level):
        student_data = []

        for student in students:
            student_data.append(one_row(student, level))

        return student_data

    # Return rows of student object with values for progress bar and scores of each selected level
    def multiple_students_multiple_levels(students, level_ids):
        student_data = []

        for student in students:
            student_data.append([student, 0.0, [], [], (0.0, 0.0, 0.0)])

        return many_rows(student_data, level_ids)

    def get_levels_headers(headers, levels):
        headers += levels
        return headers

    def is_viewable(class_):
        return class_.classmates_data_viewable

    def chop_miliseconds(delta):
        return delta - timedelta(microseconds=delta.microseconds)

    def is_student(userprofile):
        return hasattr(userprofile, 'student') and not userprofile.student.is_independent()

    def is_teacher(userprofile):
        return hasattr(userprofile, 'teacher')

    def is_independent_student(userprofile):
        return hasattr(userprofile, 'student') and userprofile.student.is_independent()

    def classes_for(userprofile):
        if is_teacher(userprofile):
            teachers = Teacher.objects.filter(school=userprofile.teacher.school)
            classes_list = [c.id for c in Class.objects.all() if (c.teacher in teachers)]
            return Class.objects.filter(id__in=classes_list)
        elif is_student(userprofile):
            class_ = userprofile.student.class_field
            return Class.objects.filter(id=class_.id)

    def error_response(message):
        return None, None, None, renderError(request, messages.noPermissionTitle(), message)

    userprofile = request.user.userprofile
    headers = []
    classes = classes_for(userprofile)

    if is_independent_student(userprofile):
        return error_response(messages.noPermissionScoreboard())

    if is_teacher(userprofile) and len(classes) == 0:
        return error_response(messages.noDataToShow())

    form = ScoreboardForm(request.POST or None, classes=classes)
    student_data = None

    # Update the scoreboard if the class and or level were selected.
    if request.method == 'POST':
        if form.is_valid():
            student_data, headers = populate_scoreboard(request)

    return form, student_data, headers, None
<commit_msg>#538 Refactoring code in scoreboard.py, extracted condition to variable is_authorised, refactored query calls in scoreboard/classes_for()<commit_after>from __future__ import division
import game.messages as messages
import game.permissions as permissions
import csv

from datetime import timedelta
from django.http import Http404, HttpResponse
from django.shortcuts import render
from django.template import RequestContext
from helper import renderError
from game.forms import ScoreboardForm
from game.models import Level, Attempt
from portal.models import Class, Teacher, Student

def scoreboard(request):
    """ Renders a page with students' scores. A teacher can see the the visible classes in their
        school. Student's view is restricted to their class if their teacher enabled the
        scoreboard for said class.

    **Context**

    ``RequestContext``
    ``form``
        Form used to choose a class and level to show. Instance of `forms.ScoreboardForm.`
    ``student_data``
        List of lists containing all the data to be stored in the scoreboard table.
    ``headers``
        List of Strings representing the headers of the scoreboard table.

    **Template:**

    :template:`game/scoreboard.html`
    """
    if not permissions.can_see_scoreboard(request.user):
        return renderError(request, messages.noPermissionTitle(), messages.noPermissionScoreboard())

    form, student_data, headers, error_response = create_scoreboard(request)

    if error_response:
        return error_response

    if 'export' in request.POST:
        return get_scoreboard_csv(student_data, headers)
    else:
        return get_scoreboard_view(request, form, student_data, headers)

def get_scoreboard_view(request, form, student_data, headers):
    context = RequestContext(request, {
        'form': form,
        'student_data': student_data,
        'headers': headers,
    })
    return render(request, 'game/scoreboard.html', context_instance=context)

def get_scoreboard_csv(student_data, headers):
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="scoreboard.csv"'

    #remove list element with list of level scores (the following elements hold the same data separately)
    if headers[1] != 'Score':
        for row in student_data:
            del row[3]

    writer = csv.writer(response)
    writer.writerow(headers)
    writer.writerows(student_data)

    return response

def create_scoreboard(request):

    def are_classes_viewable_by_teacher(class_ids, userprofile):
        teachers = Teacher.objects.filter(school=userprofile.teacher.school)
        classes_in_teachers_school = Class.objects.filter(teacher__in=teachers).values_list('id', flat=True)
        for class_id in class_ids:
            is_authorised = class_id in classes_in_teachers_school
            if not is_authorised:
                return False
        return True

    def populate_scoreboard(request):

        # Getting data from the request object
        userprofile = request.user.userprofile
        level_ids = map(int, request.POST.getlist('levels'))
        class_ids = map(int, request.POST.getlist('classes'))

        # Get the list of students and levels to be displayed
        # As the list passed by the multiselect is in order, using a for loop will preserve the order and
        # only get the default levels instead of the custom levels as well
        # Django 1.7 does not support sorting queryset by converting strings to int
        # Django 1.8 supports the use of expressios in order_by, should try using that to write cleaner codes
        # https://docs.djangoproject.com/en/1.8/releases/1.8/#query-expressions-conditional-expressions-and-database-functions

        students = Student.objects.filter(class_field__id__in = class_ids)

        levels = Level.objects.filter(id__in=level_ids)

        # Check that all the classes selected are valid
        if is_teacher(userprofile):
            if not are_classes_viewable_by_teacher(class_ids, userprofile):
                raise Http404

        # Retrieve the class that the student is in, check that the class selected in drop down menu is the same
        # Each student can only be in one class at a time, so there will be only be one element in the list
        elif is_student(userprofile):
            class_ = userprofile.student.class_field
            if class_ids[0] and int(class_ids[0]) != class_.id:
                raise Http404
            students = class_.students.all()
            # If student is not permitted to look at other students' score, it will only show the student's own data
            if not is_viewable(class_):
                students = class_.students.filter(id=userprofile.student.id)
        else:
            raise Http404
        # If there are more than one level to show, show the total score, total time and score of each level
        # Otherwise, show the details of the level (the score, total time, start time and end time)
        if len(level_ids) > 1:
            # Rows: Students from each class
            # Cols: Total Score, Total Time, Level X, ... , Level Y
            headers = get_levels_headers(['Name', 'Total Score', 'Total Time', 'Progress'], levels)
            student_data = multiple_students_multiple_levels(students, level_ids)
        else:
            # Rows: Students from each class
            # Cols: Score, Total Time, Start Time, End Time
            headers = ['Name', 'Score', 'Total Time', 'Start Time', 'Finish Time']
            student_data = multiple_students_one_level(students, level_ids[0])
        return student_data, headers

    def one_row(student, level_id):
        row = [student]

        attempt = Attempt.objects.filter(level__id=level_id, student=student).first()
        if attempt:
            row.append(attempt.score if attempt.score is not None else '')
            row.append(chop_miliseconds(attempt.finish_time - attempt.start_time))
            row.append(attempt.start_time)
            row.append(attempt.finish_time)
        else:
            row.append("")
            row.append("")
            row.append("")
            row.append("")

        return row

    # many_rows return the
    def many_rows(student_data, level_ids):
        threshold = 10.0

        num_levels = len(level_ids)
        for row in student_data:
            student = row[0]
            num_all = num_finished = num_attempted = num_started = 0

            if Attempt.objects.filter(student=student).exists():
                attempts = Attempt.objects.filter(level__id__in=level_ids, student=student)

                attempts_dict = {attempt.level.id : attempt for attempt in attempts}
                for level in level_ids:
                    attempt = attempts_dict.get(level)
                    if attempt:
                        num_all += 1;
                        if attempt.score:
                            if attempt.score >= threshold:
                                num_finished += 1
                            else:
                                num_attempted += 1
                        else:
                            num_started += 1

                        row[1] += attempt.score if attempt.score is not None else 0
                        row[2].append(chop_miliseconds(attempt.finish_time - attempt.start_time))
                        # '-' is used to show that the student has started the level but has not submitted any attempts
                        row.append(attempt.score if attempt.score is not None else '-')
                        row[3].append(attempt.score if attempt.score is not None else '-')
                    else:
                        row[2].append(timedelta(0))
                        row.append("")
                        row[3].append("")

                row[4] = compute_proportions(num_levels, num_started, num_attempted, num_finished)
            else:
                row[3].extend([''] * num_levels)
        for row in student_data:
            row[2] = sum(row[2], timedelta())

        return student_data

    def compute_proportions(num_levels, num_started, num_attempted, num_finished):
        return (num_started/num_levels)*100, (num_attempted/num_levels)*100, (num_finished/num_levels)*100

    # Returns rows of student object with score, start time, end time of the level
    def multiple_students_one_level(students, level):
        student_data = []

        for student in students:
            student_data.append(one_row(student, level))

        return student_data

    # Return rows of student object with values for progress bar and scores of each selected level
    def multiple_students_multiple_levels(students, level_ids):
        student_data = []

        for student in students:
            student_data.append([student, 0.0, [], [], (0.0, 0.0, 0.0)])

        return many_rows(student_data, level_ids)

    def get_levels_headers(headers, levels):
        headers += levels
        return headers

    def is_viewable(class_):
        return class_.classmates_data_viewable

    def chop_miliseconds(delta):
        return delta - timedelta(microseconds=delta.microseconds)

    def is_student(userprofile):
        return hasattr(userprofile, 'student') and not userprofile.student.is_independent()

    def is_teacher(userprofile):
        return hasattr(userprofile, 'teacher')

    def is_independent_student(userprofile):
        return hasattr(userprofile, 'student') and userprofile.student.is_independent()

    def classes_for(userprofile):
        if is_teacher(userprofile):
            teachers = Teacher.objects.filter(school=userprofile.teacher.school)
            return Class.objects.filter(teacher__in=teachers)
        elif is_student(userprofile):
            class_ = userprofile.student.class_field
            return Class.objects.filter(id=class_.id)

    def error_response(message):
        return None, None, None, renderError(request, messages.noPermissionTitle(), message)

    userprofile = request.user.userprofile
    headers = []
    classes = classes_for(userprofile)

    if is_independent_student(userprofile):
        return error_response(messages.noPermissionScoreboard())

    if is_teacher(userprofile) and len(classes) == 0:
        return error_response(messages.noDataToShow())

    form = ScoreboardForm(request.POST or None, classes=classes)
    student_data = None

    # Update the scoreboard if the class and or level were selected.
    if request.method == 'POST':
        if form.is_valid():
            student_data, headers = populate_scoreboard(request)

    return form, student_data, headers, None
<|endoftext|>


<commit_before><commit_msg>Drop unused imports. Pass database_name into Inquisitor constructor<commit_after><|endoftext|>


<commit_before>import numpy as np

def disp_in_box(drij, box):
  """ Enforce minimum image convention (MIC) on displacement vectors.

  Args:
    drij (np.array): ri - rj for all pairs of particles rij
    box (np.array): side lengths of orthombic box
  Return:
    np.array: displacement vectors under MIC.
  """
  ndim = drij.shape[-1]
  try:
    ndim1 = len(box)  # except if box is float
  except TypeError as err:
    #nint = np.around(drij/box)
    #return drij-box*nint
    raise err
  assert ndim1 == ndim
  for idim in range(ndim):
    nint = np.around(drij[:, :, idim]/box[idim])
    drij[:, :, idim] -= box[idim]*nint
  return drij

def displacement_table(pos, box, mic=True):
  """ Calculate displacements ri-rj between all pairs of particles.

  Args:
    pos (np.array): particle positions
    box (float): side lengths of box
    mic (bool, optional): enforce minimum image convention (MIC)
  Return:
    np.array: drij, a table of displacement vectors
     shape (natom, natom, ndim)
  """
  drij = pos[:, np.newaxis] - pos[np.newaxis]
  if mic:
    disp_in_box(drij, box)
  return drij

def gofv(myr, drij, vec):
  """ grid vector quantity over pair separation
  calculate drij[i, j] dot vec[i] and count for each bin

  see usage in grid_force_difference

  Args:
    myr (np.array): bin edges for pair separation (nbin,)
    drij (np.array): displacement table (natom, natom, ndim)
    vec (np.array): vector quantity to grid (natom, ndim)
  Return:
    (np.array, np.array): (ysum, counts)
  Example:
    >>> myr = np.linspace(0.5, 3.0, 32)
    >>> vec = np.random.rand(len(drij), 3)
    >>> ysum, counts = gofv(myr, drij, vec)
  """
  # !!!! assume linear grid
  nr = len(myr)
  rmin = myr[0]
  dr = myr[1]-myr[0]
  if not np.isclose(myr[2]-myr[1], dr):
    raise RuntimeError('not linear grid')
  # histogram
  ysum = np.zeros(nr)
  counts = np.zeros(nr, dtype=int)
  rij = np.linalg.norm(drij, axis=-1)
  nmol = rij.shape[0]
  for i in range(nmol):
    for j in range(i+1, nmol):
      deno = rij[i, j]
      ir = int((deno-rmin)//dr)  # bin index
      if (0 <= ir) and (ir < nr):
        rhat = -drij[i, j]  # drij is dr_i - dr_j NOT ri->rj
        nume = np.dot(rhat, vec[i])
        val = nume/deno
        ysum[ir] += val
        counts[ir] += 1
  return ysum, counts

def gofr_bin_edges(rmin, rmax, nr):
  # create linear grid
  bin_edges = np.linspace(rmin, rmax, nr)
  return bin_edges

def gofr_norm(myr, natom, volume):
  """ calculate norm needed to turn counts from gofv to
   pair correlation g(r)

  Args:
    myr (np.array): bin edges for pair separation (nbin,)
    natom (int): number of atoms in the box
    volume (float): volume of the box
  Return:
    np.array: nvec, normalization vector g(r) = nvec*[gofv counts]
  Example:
    >>> ysum, counts = gofv(myr, drij, vec)
    >>> nvec = gofr_norm(myr, len(drij), volume)
    >>> gr = nvec*counts
  """
  # !!!! assume 3 dimensions
  ndim = 3
  # !!!! assume linear grid
  nr = len(myr)
  rmin = myr[0]
  dr = myr[1]-myr[0]
  if not np.isclose(myr[2]-myr[1], dr):
    raise RuntimeError('not linear grid')
  # calculate volume differences
  vnorm = np.diff(4*np.pi/3*myr**ndim)
  # calculate density normalization
  npair = natom*(natom-1)/2
  rho = npair/volume
  # assemble norm vector
  nvec = 1./(rho*vnorm)
  return nvec

def gofr_count(myr, dists):
  # !!!! assume linear grid
  dr = myr[1]-myr[0]
  if not np.isclose(myr[2]-myr[1], dr):
    raise RuntimeError('not linear grid')
  # initialize memory
  nr = len(myr)
  gr = np.zeros(nr-1)
  # bin distances
  rmin = myr.min()
  rmax = myr.max()
  ir = (dists[(rmin<dists) & (dists<rmax)]-rmin)//dr
  # histogram
  ilist, counts = np.unique(ir.astype(int), return_counts=True)
  gr[ilist] = counts
  return gr

def yl_ysql(yl, ysql):
  """ calculate mean and error given a list of val and sq

  Args:
    yl (list): list of values, (nentry,)
    ysql (list): list of squares, (nentry,)
  Return:
    (np.array, np.array): (ym, ye),
      (mean, error)
  """
  ym = np.mean(yl, axis=0)
  # calculate stddev
  y2m = np.mean(ysql, axis=0)
  ye = np.sqrt((y2m-ym**2)/(len(yl)-1))
  return ym, ye

def ysum_ysq_count(ysum, ysq, counts):
  """ calculate mean and error given accumulated sum of val and sq

  Args:
    ysum (np.array): accumulated sum of values, (nentry,)
    ysq (np.array): accumulated sum of squares, (nentry,)
    counts (np.array): number of hits for each entry, (nentry,)
  Return:
    (np.array, np.array, np.array): (sel, ym, ye),
      (valid entries, mean, error)
  Example:
    >>> nr = len(myr)
    >>> ysum = np.zeros(nr)
    >>> ysq = np.zeros(nr)
    >>> csum = np.zeros(nr, dtype=int)
    >>> csq = np.zeros(nr, dtype=int)
    >>> for box, pos, vec in zip(boxl, posl, vecl):
    >>>   drij = displacement_table(pos, box)
    >>>   y1, c1 = gofv(myr, drij, vec)
    >>>   ysum += y1
    >>>   ysq += y1**2
    >>>   csum += c1
    >>>   csq += c1**2
    >>> sel, ym, ye = ysum_ysq_count(ysum, ysq, csum)
    >>> myx = myr[sel]
    >>> # g(r)
    >>> grcnt = len(boxl)*np.ones(len(myy))
    >>> sel1, grm, gre = ysum_ysq_count(csum, csq, grcnt)
    >>> nvec = gofr_norm(myr, len(drij), volume)
    >>> grm *= nvec; gre *= nvec
  """
  sel = counts > 1  # need to divide by counts-1
  ym = ysum[sel]/counts[sel]
  y2 = ysq[sel]/counts[sel]
  ye2 = (y2-ym**2)/(counts[sel]-1)
  ye = ye2**0.5
  return sel, ym, ye

def grid_force_difference(myr, boxl, posl, vecl):
  nr = len(myr)
  ysum = np.zeros(nr)
  ysq = np.zeros(nr)
  counts = np.zeros(nr, dtype=int)
  csq = np.zeros(nr, dtype=int)
  for box, pos, vec in zip(boxl, posl, vecl):
    drij = displacement_table(pos, box)
    y1, c1 = gofv(myr, drij, vec)
    ysum += y1
    ysq += y1**2
    counts += c1
    csq += c1**2
  nconf = len(boxl)
  natom = len(posl[0])
  sel, ym, ye = ysum_ysq_count(ysum, ysq, counts)
  myx = myr[sel]
  sel, cm, ce = ysum_ysq_count(counts, csq, nconf*np.ones(len(myr)))
  nvec = gofr_norm(myr, natom, np.prod(box))
  grm = nvec*cm
  gre = nvec*ce
  return myx, ym, ye, grm, gre

def h2com(pos, box, rmax=np.inf, pair_all=True):
  from qharv.inspect import box_pos, axes_pos
  natom = len(pos)
  drij = box_pos.displacement_table(pos, box)
  rij = np.linalg.norm(drij, axis=-1)
  pairs = axes_pos.find_dimers(rij, rmax)
  nmol = len(pairs)
  if pair_all:
    assert nmol == natom//2
  if len(pairs) < 1:
    return []
  com = pos[pairs[:, 0]] - 0.5*drij[pairs[:, 0], pairs[:, 1]]
  return com

def rhok(kvecs, pos):
  if kvecs.ndim == 1:
    kvecs = kvecs[np.newaxis, :]
  # dot the last axis of kvecs and pos
  exponentials = np.exp(-1j*np.inner(kvecs, pos))
  # sum over position index
  rhok = np.sum(exponentials, axis=-1)
  return rhok

def Sk(kvecs, pos):
  natom = pos.shape[-2]
  rho = rhok(kvecs, pos)
  sk = rho*rho.conj()/natom
  if sk.ndim >= 2:
    sk = sk.mean(axis=-1)
  return sk.real

def legal_kvecs(axes, nsh, eps=1e-8):
  from qharv.inspect import axes_pos
  raxes = axes_pos.raxes(axes)
  gvecs = axes_pos.cubic_pos(2*nsh+1)-nsh
  kvecs = np.dot(gvecs, raxes)
  kmags = np.linalg.norm(kvecs, axis=-1)
  sel = (kmags>eps) & (kvecs[:, 2]>=0)
  return kvecs[sel]
<commit_msg>myr to bin_edges<commit_after>import numpy as np

def disp_in_box(drij, box):
  """ Enforce minimum image convention (MIC) on displacement vectors.

  Args:
    drij (np.array): ri - rj for all pairs of particles rij
    box (np.array): side lengths of orthombic box
  Return:
    np.array: displacement vectors under MIC.
  """
  ndim = drij.shape[-1]
  try:
    ndim1 = len(box)  # except if box is float
  except TypeError as err:
    #nint = np.around(drij/box)
    #return drij-box*nint
    raise err
  assert ndim1 == ndim
  for idim in range(ndim):
    nint = np.around(drij[:, :, idim]/box[idim])
    drij[:, :, idim] -= box[idim]*nint
  return drij

def displacement_table(pos, box, mic=True):
  """ Calculate displacements ri-rj between all pairs of particles.

  Args:
    pos (np.array): particle positions
    box (float): side lengths of box
    mic (bool, optional): enforce minimum image convention (MIC)
  Return:
    np.array: drij, a table of displacement vectors
     shape (natom, natom, ndim)
  """
  drij = pos[:, np.newaxis] - pos[np.newaxis]
  if mic:
    disp_in_box(drij, box)
  return drij

def gofv(myr, drij, vec):
  """ grid vector quantity over pair separation
  calculate drij[i, j] dot vec[i] and count for each bin

  see usage in grid_force_difference

  Args:
    myr (np.array): bin edges for pair separation (nbin,)
    drij (np.array): displacement table (natom, natom, ndim)
    vec (np.array): vector quantity to grid (natom, ndim)
  Return:
    (np.array, np.array): (ysum, counts)
  Example:
    >>> myr = np.linspace(0.5, 3.0, 32)
    >>> vec = np.random.rand(len(drij), 3)
    >>> ysum, counts = gofv(myr, drij, vec)
  """
  # !!!! assume linear grid
  nr = len(myr)
  rmin = myr[0]
  dr = myr[1]-myr[0]
  if not np.isclose(myr[2]-myr[1], dr):
    raise RuntimeError('not linear grid')
  # histogram
  ysum = np.zeros(nr)
  counts = np.zeros(nr, dtype=int)
  rij = np.linalg.norm(drij, axis=-1)
  nmol = rij.shape[0]
  for i in range(nmol):
    for j in range(i+1, nmol):
      deno = rij[i, j]
      ir = int((deno-rmin)//dr)  # bin index
      if (0 <= ir) and (ir < nr):
        rhat = -drij[i, j]  # drij is dr_i - dr_j NOT ri->rj
        nume = np.dot(rhat, vec[i])
        val = nume/deno
        ysum[ir] += val
        counts[ir] += 1
  return ysum, counts

def gofr_bin_edges(rmin, rmax, nr):
  # create linear grid
  bin_edges = np.linspace(rmin, rmax, nr)
  return bin_edges

def gofr_norm(bin_edges, natom, volume):
  """ calculate norm needed to turn counts from gofv to
   pair correlation g(r)

  Args:
    bin_edges (np.array): bin edges for pair separation (nbin,)
    natom (int): number of atoms in the box
    volume (float): volume of the box
  Return:
    np.array: nvec, normalization vector g(r) = nvec*[gofv counts]
  Example:
    >>> ysum, counts = gofv(myr, drij, vec)
    >>> nvec = gofr_norm(myr, len(drij), volume)
    >>> gr = nvec*counts
  """
  # !!!! assume 3 dimensions
  ndim = 3
  # !!!! assume linear grid
  dr = bin_edges[1]-bin_edges[0]
  dr1 = bin_edges[2]-bin_edges[1]
  if not np.isclose(dr1, dr):
    raise RuntimeError('not linear grid')
  # calculate volume differences
  vnorm = np.diff(4*np.pi/3*bin_edges**ndim)
  # calculate density normalization
  npair = natom*(natom-1)/2
  rho = npair/volume
  # assemble norm vector
  nvec = 1./(rho*vnorm)
  return nvec

def gofr_count(bin_edges, dists):
  # !!!! assume linear grid
  dr = bin_edges[1]-bin_edges[0]
  dr1 = bin_edges[2]-bin_edges[1]
  if not np.isclose(dr1, dr):
    raise RuntimeError('not linear grid')
  # initialize memory
  nr = len(bin_edges)-1
  gr = np.zeros(nr)
  # bin distances
  rmin = bin_edges.min()
  rmax = bin_edges.max()
  ir = (dists[(rmin<dists) & (dists<rmax)]-rmin)//dr
  # histogram
  ilist, counts = np.unique(ir.astype(int), return_counts=True)
  gr[ilist] = counts
  return gr

def yl_ysql(yl, ysql):
  """ calculate mean and error given a list of val and sq

  Args:
    yl (list): list of values, (nentry,)
    ysql (list): list of squares, (nentry,)
  Return:
    (np.array, np.array): (ym, ye),
      (mean, error)
  """
  ym = np.mean(yl, axis=0)
  # calculate stddev
  y2m = np.mean(ysql, axis=0)
  ye = np.sqrt((y2m-ym**2)/(len(yl)-1))
  return ym, ye

def ysum_ysq_count(ysum, ysq, counts):
  """ calculate mean and error given accumulated sum of val and sq

  Args:
    ysum (np.array): accumulated sum of values, (nentry,)
    ysq (np.array): accumulated sum of squares, (nentry,)
    counts (np.array): number of hits for each entry, (nentry,)
  Return:
    (np.array, np.array, np.array): (sel, ym, ye),
      (valid entries, mean, error)
  Example:
    >>> nr = len(myr)
    >>> ysum = np.zeros(nr)
    >>> ysq = np.zeros(nr)
    >>> csum = np.zeros(nr, dtype=int)
    >>> csq = np.zeros(nr, dtype=int)
    >>> for box, pos, vec in zip(boxl, posl, vecl):
    >>>   drij = displacement_table(pos, box)
    >>>   y1, c1 = gofv(myr, drij, vec)
    >>>   ysum += y1
    >>>   ysq += y1**2
    >>>   csum += c1
    >>>   csq += c1**2
    >>> sel, ym, ye = ysum_ysq_count(ysum, ysq, csum)
    >>> myx = myr[sel]
    >>> # g(r)
    >>> grcnt = len(boxl)*np.ones(len(myy))
    >>> sel1, grm, gre = ysum_ysq_count(csum, csq, grcnt)
    >>> nvec = gofr_norm(myr, len(drij), volume)
    >>> grm *= nvec; gre *= nvec
  """
  sel = counts > 1  # need to divide by counts-1
  ym = ysum[sel]/counts[sel]
  y2 = ysq[sel]/counts[sel]
  ye2 = (y2-ym**2)/(counts[sel]-1)
  ye = ye2**0.5
  return sel, ym, ye

def grid_force_difference(myr, boxl, posl, vecl):
  nr = len(myr)
  ysum = np.zeros(nr)
  ysq = np.zeros(nr)
  counts = np.zeros(nr, dtype=int)
  csq = np.zeros(nr, dtype=int)
  for box, pos, vec in zip(boxl, posl, vecl):
    drij = displacement_table(pos, box)
    y1, c1 = gofv(myr, drij, vec)
    ysum += y1
    ysq += y1**2
    counts += c1
    csq += c1**2
  nconf = len(boxl)
  natom = len(posl[0])
  sel, ym, ye = ysum_ysq_count(ysum, ysq, counts)
  myx = myr[sel]
  sel, cm, ce = ysum_ysq_count(counts, csq, nconf*np.ones(len(myr)))
  nvec = gofr_norm(myr, natom, np.prod(box))
  grm = nvec*cm
  gre = nvec*ce
  return myx, ym, ye, grm, gre

def h2com(pos, box, rmax=np.inf, pair_all=True):
  from qharv.inspect import box_pos, axes_pos
  natom = len(pos)
  drij = box_pos.displacement_table(pos, box)
  rij = np.linalg.norm(drij, axis=-1)
  pairs = axes_pos.find_dimers(rij, rmax)
  nmol = len(pairs)
  if pair_all:
    assert nmol == natom//2
  if len(pairs) < 1:
    return []
  com = pos[pairs[:, 0]] - 0.5*drij[pairs[:, 0], pairs[:, 1]]
  return com

def rhok(kvecs, pos):
  if kvecs.ndim == 1:
    kvecs = kvecs[np.newaxis, :]
  # dot the last axis of kvecs and pos
  exponentials = np.exp(-1j*np.inner(kvecs, pos))
  # sum over position index
  rhok = np.sum(exponentials, axis=-1)
  return rhok

def Sk(kvecs, pos):
  natom = pos.shape[-2]
  rho = rhok(kvecs, pos)
  sk = rho*rho.conj()/natom
  if sk.ndim >= 2:
    sk = sk.mean(axis=-1)
  return sk.real

def legal_kvecs(axes, nsh, eps=1e-8):
  from qharv.inspect import axes_pos
  raxes = axes_pos.raxes(axes)
  gvecs = axes_pos.cubic_pos(2*nsh+1)-nsh
  kvecs = np.dot(gvecs, raxes)
  kmags = np.linalg.norm(kvecs, axis=-1)
  sel = (kmags>eps) & (kvecs[:, 2]>=0)
  return kvecs[sel]
<|endoftext|>


<commit_before>from collections import OrderedDict

from django.utils.translation import ugettext_lazy as _

from c3nav.mapdata.models import AreaLocation, LocationGroup

def get_default_include_avoid():
    include = set()
    avoid = set()

    locations = list(AreaLocation.objects.exclude(routing_inclusion='default'))
    locations += list(LocationGroup.objects.exclude(routing_inclusion='default'))

    for location in locations:
        if location.routing_inclusion != 'allow_avoid':
            avoid.add(location.location_id)

    return include, avoid

# Todo: add cache
def get_includables_avoidables(request):
    includables = []
    avoidables = []

    locations = list(AreaLocation.objects.exclude(routing_inclusion='default'))
    locations += list(LocationGroup.objects.exclude(routing_inclusion='default'))

    if request.c3nav_full_access:
        includables.append((':nonpublic', _('non-public areas')))
        avoidables.append((':public', _('public areas')))

    from c3nav.access.apply import can_access_package

    for location in locations:
        item = (location.location_id, location.title)

        if not can_access_package(request, location.package):
            continue

        if location.routing_inclusion == 'needs_permission':
            if not request.c3nav_full_access and location.location_id not in request.c3nav_access_list:
                continue

        if location.routing_inclusion == 'allow_avoid':
            avoidables.append(item)
        else:
            includables.append(item)

    return OrderedDict(includables), OrderedDict(avoidables)

def get_maybe_invisible_areas():
    return AreaLocation.objects.exclude(routing_inclusion='default')

def get_maybe_invisible_areas_names():
    return tuple(area.name for area in get_maybe_invisible_areas())

def parse_include_avoid(request, include_input, avoid_input):
    includable, avoidable = get_includables_avoidables(request)
    include_input = set(include_input) & set(includable)
    avoid_input = set(avoid_input) & set(avoidable)

    default_include, default_avoid = get_default_include_avoid()

    include = set(default_include) | include_input
    avoid = set(default_avoid) - include_input | avoid_input

    return ':nonpublic' in includable, include, avoid
<commit_msg>fix get_includables_avoidables<commit_after>from collections import OrderedDict

from django.utils.translation import ugettext_lazy as _

from c3nav.mapdata.models import AreaLocation, LocationGroup

def get_default_include_avoid():
    include = set()
    avoid = set()

    locations = list(AreaLocation.objects.exclude(routing_inclusion='default'))
    locations += list(LocationGroup.objects.exclude(routing_inclusion='default'))

    for location in locations:
        if location.routing_inclusion != 'allow_avoid':
            avoid.add(location.location_id)

    return include, avoid

# Todo: add cache
def get_includables_avoidables(request):
    includables = []
    avoidables = []

    locations = list(AreaLocation.objects.exclude(routing_inclusion='default'))
    locations += list(LocationGroup.objects.exclude(routing_inclusion='default'))

    if request.c3nav_full_access:
        includables.append((':nonpublic', _('non-public areas')))
        avoidables.append((':public', _('public areas')))

    for location in locations:
        item = (location.location_id, location.title)

        if not location.location_id not in request.c3nav_access_list and not request.c3nav_full_access:
            if location.routing_inclusion == 'needs_permission':
                continue

        if location.routing_inclusion == 'allow_avoid':
            avoidables.append(item)
        else:
            includables.append(item)

    return OrderedDict(includables), OrderedDict(avoidables)

def get_maybe_invisible_areas():
    return AreaLocation.objects.exclude(routing_inclusion='default')

def get_maybe_invisible_areas_names():
    return tuple(area.name for area in get_maybe_invisible_areas())

def parse_include_avoid(request, include_input, avoid_input):
    includable, avoidable = get_includables_avoidables(request)
    include_input = set(include_input) & set(includable)
    avoid_input = set(avoid_input) & set(avoidable)

    default_include, default_avoid = get_default_include_avoid()

    include = set(default_include) | include_input
    avoid = set(default_avoid) - include_input | avoid_input

    return ':nonpublic' in includable, include, avoid
<|endoftext|>


<commit_before>from sympy import *
from sympy.modules.specfun.factorials import *
#from sympy.modules.printing.latex import latex

x = Symbol('x')
y = Symbol('y')
z = Symbol('z')

fs = factorial_simplify
fac = factorial

def test_factorial1():
    assert [fac(t) for t in [0,1,2,3,4]] == [1,1,2,6,24]
    assert (fac(-1) == oo) == True
    assert fac(Rational(1,2)) == Rational(1,2)*sqrt(pi)
    assert fac(Rational(3,2)) == Rational(3,4)*sqrt(pi)
    assert fac(Rational(5,2)) == Rational(15,8)*sqrt(pi)
    assert fac(Rational(-1,2)) == sqrt(pi)
    assert fac(Rational(-3,2)) == -2*sqrt(pi)
    assert fac(Rational(-5,2)) == Rational(4,3)*sqrt(pi)
    assert fac(Rational(-17,2)) == Rational(256,2027025)*sqrt(pi)
    #assert latex(fac(x, evaluate=False)) == "$x!$"
    #assert latex(fac(-4, evaluate=False)) == "$(-4)!$"
    #assert latex(fac(-x, evaluate=False)) == "$(- x)!$"

def _test_factorial_evalf():
    def relcmp(a,b):
        return abs(float(a-b))/abs(float(a))
    for i in range(20):
        assert relcmp(fac(i, evaluate=False).evalf(), fac(i)) < 1e-10
    for i in range(-7, 7, 2):
        x = Rational(i)/2
        assert relcmp(fac(x, evaluate=False).evalf(), fac(x)) < 1e-10
    assert relcmp(fac(165, evaluate=False).evalf(), fac(165)) < 1e-10
    assert relcmp(fac(-0.75).evalf(), 3.6256099082219083) < 1e-10
    assert relcmp((1-fac(1e-8).evalf())*10**8, 0.5772157) < 1e-5
    assert relcmp((fac(-1e-8).evalf()-1)*10**8, 0.5772157) < 1e-5
    re, im = fac(7+8*I).evalf().get_re_im()
    assert relcmp(re, 1.84428481562553) < 1e-10
    assert relcmp(im, -125.96060801751909) < 1e-10

def _test_factorial2():
    assert factorial2(0) == 1
    assert factorial2(2) == 2
    assert factorial2(4) == 2*4
    assert factorial2(6) == 2*4*6
    assert factorial2(1) == 1
    assert factorial2(3) == 3
    assert factorial2(5) == 3*5
    assert factorial2(7) == 3*5*7
    assert (factorial2(-2) == oo) == True
    assert (factorial2(-4) == oo) == True
    assert factorial2(-1) == 1
    assert factorial2(-3) == -1
    assert factorial2(-7) == Rational(-1,15)
    assert factorial2(-9) == Rational(1,105)
    assert latex(factorial2(x, evaluate=False)) == "$x!!$"
    assert latex(factorial2(-4, evaluate=False)) == "$(-4)!!$"
    assert latex(factorial2(-x, evaluate=False)) == "$(- x)!!$"

def _test_factorial_simplify():
    assert fs(fac(x+5)/fac(x+5)) == 1
    assert fs(fac(x+1)/fac(x)) == 1+x
    assert fs(fac(x+2)/fac(x)) == (1+x)*(2+x)
    assert fs(fac(x+3)/fac(x)) == (1+x)*(2+x)*(3+x)
    assert fs(fac(x-1)/fac(x)) == (1/x)
    assert fs(fac(x-2)/fac(x)) == 1/(x*(-1+x))
    assert fs(fac(x-3)/fac(x)) == 1/(x*(-1+x)*(-2+x))
    assert fs(fac(x)*(x+1)*(x+2)) == fac(x+2)
    assert fs(fac(x)/x/(x-1)) == fac(x-2)
    assert fs(x*(x-1)/fac(x)) == 1/fac(x-2)
    assert fs((1/(x+1))/fac(x)) == 1/fac(x+1)
    assert fs(fac(x)*fac(y-2)*fac(z+2)/fac(z)/fac(y+1)) == fac(x)*(z+1)*(z+2)/(y-1)/y/(y+1)
    assert fs(fac(x)*fac(y+1)*fac(z+2)/fac(z)/fac(y-2)) == fac(x)*(z+1)*(z+2)*(y-1)*y*(y+1)

def _test_rising_falling():
    assert rising_factorial(x, 0) == 1
    assert rising_factorial(x, 1) == x
    assert rising_factorial(x, 2) == x*(x+1)
    assert rising_factorial(x, 3) == x*(x+1)*(x+2)
    assert falling_factorial(x, 0) == 1
    assert falling_factorial(x, 1) == x
    assert falling_factorial(x, 2) == x*(x-1)
    assert falling_factorial(x, 3) == x*(x-1)*(x-2)
    assert rising_factorial(1, x) == factorial(x)
    assert falling_factorial(1, x) == 1/factorial(1-x)
    assert falling_factorial(15, 8) == 259459200
    assert falling_factorial(-3,4) == 360
    assert falling_factorial(3,-4) == Rational(1,840)
    assert rising_factorial(15, 8) == 12893126400
    assert rising_factorial(-3,4) == 0
    n = Symbol('n')
    assert latex(rising_factorial(x, n, evaluate=False)) == "${(x)}^{(n)}$"
    assert latex(falling_factorial(x, n, evaluate=False)) == "${(x)}_{(n)}$"

def _test_binomial():
    assert binomial(x, 0) == 1
    assert binomial(x, x) == 1
    assert binomial(0, 0) == 1
    assert binomial(0, 1) == 0
    assert binomial(0, x) == sin(pi*x)/(pi*x)
    assert binomial(x, 1) == x
    assert binomial(x, 2) == Rational(1,2)*x*(x-1)
    assert binomial(x, 3) == Rational(1,6)*x*(x-1)*(x-2)
    assert [binomial(4,k) for k in range(5)] == [1,4,6,4,1]
    assert [binomial(5,k) for k in range(6)] == [1,5,10,10,5,1]
    assert sum(binomial(20, k) for k in range(21)) == 2**20
    assert binomial(10**20, 10**20 - 2) == \
        4999999999999999999950000000000000000000
    assert latex(binomial(8,3,evaluate=False)) == r"${{8}\choose{3}}$"

def _test_gamma():
    assert gamma(0) == oo
    assert gamma(1) == 1
    assert gamma(2) == 1
    assert gamma(3) == 2
    assert gamma(Rational(1,2)) == sqrt(pi)
    assert latex(gamma(3+x)) == "$\Gamma(3+x)$"
    from sympy import simplify
    assert simplify(lower_gamma(1,x) + upper_gamma(1,x)) == gamma(1)
    assert simplify(lower_gamma(5,x) + upper_gamma(5,x)) == gamma(5)

def _test_derivatives():
    x = Symbol('x')
    from sympy.modules.specfun.zeta_functions import polygamma, euler_gamma
    assert diff(gamma(4*x), x) == 4*gamma(4*x)*polygamma(0, 4*x)
    assert diff(factorial(4*x), x) == 4*gamma(1+4*x)*polygamma(0, 1+4*x)
    assert diff(log(gamma(x)), x, 5) == polygamma(4, x)
    assert diff(factorial(x), x).subs(x, 0) == -euler_gamma
    assert diff(factorial(x), x).subs(x, 4) \
           == 24*(Rational(25, 12)-euler_gamma)
<commit_msg>more tests uncommented<commit_after>from sympy import *
from sympy.modules.specfun.factorials import *
#from sympy.modules.printing.latex import latex

x = Symbol('x')
y = Symbol('y')
z = Symbol('z')

fs = factorial_simplify
fac = factorial

def test_factorial1():
    assert [fac(t) for t in [0,1,2,3,4]] == [1,1,2,6,24]
    assert (fac(-1) == oo) == True
    assert fac(Rational(1,2)) == Rational(1,2)*sqrt(pi)
    assert fac(Rational(3,2)) == Rational(3,4)*sqrt(pi)
    assert fac(Rational(5,2)) == Rational(15,8)*sqrt(pi)
    assert fac(Rational(-1,2)) == sqrt(pi)
    assert fac(Rational(-3,2)) == -2*sqrt(pi)
    assert fac(Rational(-5,2)) == Rational(4,3)*sqrt(pi)
    assert fac(Rational(-17,2)) == Rational(256,2027025)*sqrt(pi)
    #assert latex(fac(x, evaluate=False)) == "$x!$"
    #assert latex(fac(-4, evaluate=False)) == "$(-4)!$"
    #assert latex(fac(-x, evaluate=False)) == "$(- x)!$"

def _test_factorial_evalf():
    def relcmp(a,b):
        return abs(float(a-b))/abs(float(a))
    for i in range(20):
        assert relcmp(fac(i, evaluate=False).evalf(), fac(i)) < 1e-10
    for i in range(-7, 7, 2):
        x = Rational(i)/2
        assert relcmp(fac(x, evaluate=False).evalf(), fac(x)) < 1e-10
    assert relcmp(fac(165, evaluate=False).evalf(), fac(165)) < 1e-10
    assert relcmp(fac(-0.75).evalf(), 3.6256099082219083) < 1e-10
    assert relcmp((1-fac(1e-8).evalf())*10**8, 0.5772157) < 1e-5
    assert relcmp((fac(-1e-8).evalf()-1)*10**8, 0.5772157) < 1e-5
    re, im = fac(7+8*I).evalf().get_re_im()
    assert relcmp(re, 1.84428481562553) < 1e-10
    assert relcmp(im, -125.96060801751909) < 1e-10

def test_factorial2():
    assert factorial2(0) == 1
    assert factorial2(2) == 2
    assert factorial2(4) == 2*4
    assert factorial2(6) == 2*4*6
    assert factorial2(1) == 1
    assert factorial2(3) == 3
    assert factorial2(5) == 3*5
    assert factorial2(7) == 3*5*7
    assert (factorial2(-2) == oo) == True
    assert (factorial2(-4) == oo) == True
    assert factorial2(-1) == 1
    assert factorial2(-3) == -1
    assert factorial2(-7) == Rational(-1,15)
    assert factorial2(-9) == Rational(1,105)
    #assert latex(factorial2(x, evaluate=False)) == "$x!!$"
    #assert latex(factorial2(-4, evaluate=False)) == "$(-4)!!$"
    #assert latex(factorial2(-x, evaluate=False)) == "$(- x)!!$"

def _test_factorial_simplify():
    assert fs(fac(x+5)/fac(x+5)) == 1
    assert fs(fac(x+1)/fac(x)) == 1+x
    assert fs(fac(x+2)/fac(x)) == (1+x)*(2+x)
    assert fs(fac(x+3)/fac(x)) == (1+x)*(2+x)*(3+x)
    assert fs(fac(x-1)/fac(x)) == (1/x)
    assert fs(fac(x-2)/fac(x)) == 1/(x*(-1+x))
    assert fs(fac(x-3)/fac(x)) == 1/(x*(-1+x)*(-2+x))
    assert fs(fac(x)*(x+1)*(x+2)) == fac(x+2)
    assert fs(fac(x)/x/(x-1)) == fac(x-2)
    assert fs(x*(x-1)/fac(x)) == 1/fac(x-2)
    assert fs((1/(x+1))/fac(x)) == 1/fac(x+1)
    assert fs(fac(x)*fac(y-2)*fac(z+2)/fac(z)/fac(y+1)) == fac(x)*(z+1)*(z+2)/(y-1)/y/(y+1)
    assert fs(fac(x)*fac(y+1)*fac(z+2)/fac(z)/fac(y-2)) == fac(x)*(z+1)*(z+2)*(y-1)*y*(y+1)

def _test_rising_falling():
    assert rising_factorial(x, 0) == 1
    assert rising_factorial(x, 1) == x
    assert rising_factorial(x, 2) == x*(x+1)
    assert rising_factorial(x, 3) == x*(x+1)*(x+2)
    assert falling_factorial(x, 0) == 1
    assert falling_factorial(x, 1) == x
    assert falling_factorial(x, 2) == x*(x-1)
    assert falling_factorial(x, 3) == x*(x-1)*(x-2)
    assert rising_factorial(1, x) == factorial(x)
    assert falling_factorial(1, x) == 1/factorial(1-x)
    assert falling_factorial(15, 8) == 259459200
    assert falling_factorial(-3,4) == 360
    assert falling_factorial(3,-4) == Rational(1,840)
    assert rising_factorial(15, 8) == 12893126400
    assert rising_factorial(-3,4) == 0
    n = Symbol('n')
    assert latex(rising_factorial(x, n, evaluate=False)) == "${(x)}^{(n)}$"
    assert latex(falling_factorial(x, n, evaluate=False)) == "${(x)}_{(n)}$"

def _test_binomial():
    assert binomial(x, 0) == 1
    assert binomial(x, x) == 1
    assert binomial(0, 0) == 1
    assert binomial(0, 1) == 0
    assert binomial(0, x) == sin(pi*x)/(pi*x)
    assert binomial(x, 1) == x
    assert binomial(x, 2) == Rational(1,2)*x*(x-1)
    assert binomial(x, 3) == Rational(1,6)*x*(x-1)*(x-2)
    assert [binomial(4,k) for k in range(5)] == [1,4,6,4,1]
    assert [binomial(5,k) for k in range(6)] == [1,5,10,10,5,1]
    assert sum(binomial(20, k) for k in range(21)) == 2**20
    assert binomial(10**20, 10**20 - 2) == \
        4999999999999999999950000000000000000000
    assert latex(binomial(8,3,evaluate=False)) == r"${{8}\choose{3}}$"

def _test_gamma():
    assert gamma(0) == oo
    assert gamma(1) == 1
    assert gamma(2) == 1
    assert gamma(3) == 2
    assert gamma(Rational(1,2)) == sqrt(pi)
    assert latex(gamma(3+x)) == "$\Gamma(3+x)$"
    from sympy import simplify
    assert simplify(lower_gamma(1,x) + upper_gamma(1,x)) == gamma(1)
    assert simplify(lower_gamma(5,x) + upper_gamma(5,x)) == gamma(5)

def _test_derivatives():
    x = Symbol('x')
    from sympy.modules.specfun.zeta_functions import polygamma, euler_gamma
    assert diff(gamma(4*x), x) == 4*gamma(4*x)*polygamma(0, 4*x)
    assert diff(factorial(4*x), x) == 4*gamma(1+4*x)*polygamma(0, 1+4*x)
    assert diff(log(gamma(x)), x, 5) == polygamma(4, x)
    assert diff(factorial(x), x).subs(x, 0) == -euler_gamma
    assert diff(factorial(x), x).subs(x, 4) \
           == 24*(Rational(25, 12)-euler_gamma)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from flask import render_template, redirect, request, make_response, abort
from filterss import app
from forms import FilterForm
from helpers import get_url, url_vars, set_filter, connect_n_parse
from helpers import remove_tags, test_cond, word_wrap, format_date, test_url
import sys
import urllib

reload(sys)
sys.setdefaultencoding('utf-8')

@app.route('/')
@app.route('/index')
def index():
    form = FilterForm()
    return render_template('form.html', form=form)

@app.route('/filter', methods=('GET', 'POST'))
def filter():
    form = FilterForm()
    if form.validate_on_submit():
        url = get_url(form.rss_url.data)
        url_query = url_vars(
            url,
            form.title_inc.data,
            form.title_exc.data,
            form.link_inc.data,
            form.link_exc.data)
        return redirect('/info?' + url_query)
    return render_template('form.html', form=form)

@app.route('/rss')
def rss():

    # load GET vars
    url = set_filter(request.args.get("url"))
    t_inc = set_filter(request.args.get("title_inc"))
    t_exc = set_filter(request.args.get("title_exc"))
    l_inc = set_filter(request.args.get("link_inc"))
    l_exc = set_filter(request.args.get("link_exc"))

    # load orginal RSS (xml)
    try:
        dom = connect_n_parse(url)
    except:
        return abort(500)

    # loop items
    for item in dom.getElementsByTagName('item'):

        # get title & link
        title = item.getElementsByTagName('title')[0].toxml()
        link = item.getElementsByTagName('link')[0].toxml()
        title = remove_tags(title)
        link = remove_tags(link)

        # test conditions
        cond1 = test_cond(t_inc, title, True)
        cond2 = test_cond(t_exc, title, False)
        cond3 = test_cond(l_inc, link, True)
        cond4 = test_cond(l_exc, link, False)

        # delete undesired nodes
        if not cond1 or not cond2 or not cond3 or not cond4:
            item.parentNode.removeChild(item)

    # print RSS (xml)
    filtered = dom.toxml()
    response = make_response(filtered)
    response.headers["Content-Type"] = "application/xml"
    return response

@app.route('/info')
def info():

    # load GET vars
    url = set_filter(request.args.get("url"))
    t_inc = set_filter(request.args.get("title_inc"))
    t_exc = set_filter(request.args.get("title_exc"))
    l_inc = set_filter(request.args.get("link_inc"))
    l_exc = set_filter(request.args.get("link_exc"))
    rss_url = request.url_root + 'rss?'
    rss_url = rss_url + url_vars(url, t_inc, t_exc, l_inc, l_exc)
    rss_url_encoded = urllib.quote(rss_url)

    # load orginal RSS (xml)
    try:
        dom = connect_n_parse(url)
    except:
        url_query = url_vars(url, t_inc, t_exc, l_inc, l_exc)
        return redirect('/error?' + url_query)

    # get title
    rss_title = dom.getElementsByTagName('title')[0].toxml()
    rss_title = remove_tags(rss_title)

    # loop items
    all_items = []
    filtered_items = []
    for item in dom.getElementsByTagName('item'):

        # get title & link
        title = item.getElementsByTagName('title')[0].toxml()
        link = item.getElementsByTagName('link')[0].toxml()
        date = item.getElementsByTagName('pubDate')[0].toxml()
        title = remove_tags(title)
        link = remove_tags(link)
        date = remove_tags(date)

        # test conditions
        cond1 = test_cond(t_inc, title, True)
        cond2 = test_cond(t_exc, title, False)
        cond3 = test_cond(l_inc, link, True)
        cond4 = test_cond(l_exc, link, False)

        # sort nodes
        item_class = 'skip'
        item = {'title': title,
                'title_wrap': word_wrap(title),
                'url': link,
                'date': format_date(date),
                'css_class': item_class}
        if cond1 and cond2 and cond3 and cond4:
            filtered_items.append(item)
            item['css_class'] = ''
        all_items.append(item)

    return render_template(
        'info.html',
        url=url,
        rss_title=rss_title,
        rss_url=rss_url,
        rss_url_encoded=rss_url_encoded,
        all_items=all_items,
        filtered_items=filtered_items)

@app.route('/check_url', methods=['GET'])
def check_url():
    url = request.args.get('url')
    return str(test_url(url))

@app.route('/robots.txt', methods=['GET'])
def sitemap():
    response = make_response(open('robots.txt').read())
    response.headers["Content-type"] = "text/plain"
    return response

@app.route('/error')
def error():
    url = str(request.args.get("url"))
    return render_template('error.html', url=url)

@app.errorhandler(500)
def page_not_found(e):
    return render_template('error.html'), 500
<commit_msg>Minor changes & code cleaning<commit_after># coding: utf-8
from flask import render_template, redirect, request, make_response, abort
from filterss import app
from forms import FilterForm
from helpers import get_url, url_vars, set_filter, connect_n_parse
from helpers import remove_tags, test_cond, word_wrap, format_date, test_url
import sys
import urllib

reload(sys)
sys.setdefaultencoding('utf-8')

@app.route('/')
def index():
    return render_template('form.html', form=FilterForm())

@app.route('/filter', methods=('GET', 'POST'))
def filter():
    form = FilterForm()
    if form.validate_on_submit():
        url = get_url(form.rss_url.data)
        url_query = url_vars(
            url,
            form.title_inc.data,
            form.title_exc.data,
            form.link_inc.data,
            form.link_exc.data)
        return redirect('/info?' + url_query)
    return render_template('form.html', form=form)

@app.route('/rss')
def rss():

    # load GET vars
    url = set_filter(request.args.get("url"))
    t_inc = set_filter(request.args.get("title_inc"))
    t_exc = set_filter(request.args.get("title_exc"))
    l_inc = set_filter(request.args.get("link_inc"))
    l_exc = set_filter(request.args.get("link_exc"))

    # load orginal RSS (xml)
    try:
        dom = connect_n_parse(url)
    except:
        return abort(500)

    # loop items
    for item in dom.getElementsByTagName('item'):

        # get title & link
        title = item.getElementsByTagName('title')[0].toxml()
        link = item.getElementsByTagName('link')[0].toxml()
        title = remove_tags(title)
        link = remove_tags(link)

        # test conditions
        cond1 = test_cond(t_inc, title, True)
        cond2 = test_cond(t_exc, title, False)
        cond3 = test_cond(l_inc, link, True)
        cond4 = test_cond(l_exc, link, False)

        # delete undesired nodes
        if not cond1 or not cond2 or not cond3 or not cond4:
            item.parentNode.removeChild(item)

    # print RSS (xml)
    filtered = dom.toxml()
    response = make_response(filtered)
    response.headers["Content-Type"] = "application/xml"
    return response

@app.route('/info')
def info():

    # load GET vars
    url = set_filter(request.args.get("url"))
    t_inc = set_filter(request.args.get("title_inc"))
    t_exc = set_filter(request.args.get("title_exc"))
    l_inc = set_filter(request.args.get("link_inc"))
    l_exc = set_filter(request.args.get("link_exc"))
    rss_url = request.url_root + 'rss?'
    rss_url = rss_url + url_vars(url, t_inc, t_exc, l_inc, l_exc)
    rss_url_encoded = urllib.quote(rss_url)

    # load orginal RSS (xml)
    try:
        dom = connect_n_parse(url)
    except:
        url_query = url_vars(url, t_inc, t_exc, l_inc, l_exc)
        return redirect('/error?' + url_query)

    # get title
    rss_title = dom.getElementsByTagName('title')[0].toxml()
    rss_title = remove_tags(rss_title)

    # loop items
    all_items = []
    filtered_items = []
    for item in dom.getElementsByTagName('item'):

        # get title & link
        title = item.getElementsByTagName('title')[0].toxml()
        link = item.getElementsByTagName('link')[0].toxml()
        date = item.getElementsByTagName('pubDate')[0].toxml()
        title = remove_tags(title)
        link = remove_tags(link)
        date = remove_tags(date)

        # test conditions
        cond1 = test_cond(t_inc, title, True)
        cond2 = test_cond(t_exc, title, False)
        cond3 = test_cond(l_inc, link, True)
        cond4 = test_cond(l_exc, link, False)

        # sort nodes
        item_class = 'skip'
        item = {'title': title,
                'title_wrap': word_wrap(title),
                'url': link,
                'date': format_date(date),
                'css_class': item_class}
        if cond1 and cond2 and cond3 and cond4:
            filtered_items.append(item)
            item['css_class'] = ''
        all_items.append(item)

    return render_template(
        'info.html',
        url=url,
        rss_title=rss_title,
        rss_url=rss_url,
        rss_url_encoded=rss_url_encoded,
        all_items=all_items,
        filtered_items=filtered_items)

@app.route('/check_url', methods=['GET'])
def check_url():
    url = request.args.get('url')
    return str(test_url(url))

@app.route('/robots.txt', methods=['GET'])
def sitemap():
    response = make_response(open('robots.txt').read())
    response.headers["Content-type"] = "text/plain"
    return response

@app.route('/error')
def error():
    url = str(request.args.get("url"))
    return render_template('error.html', url=url)

@app.errorhandler(500)
def page_not_found(e):
    return render_template('error.html'), 500
<|endoftext|>


<commit_before><commit_msg>Remove debugging noise from docstring.py<commit_after><|endoftext|>


<commit_before># -*- python -*-

# stdlib imports ---
import os
import os.path as osp

# waf imports ---
import waflib.Utils
import waflib.Logs as msg
from waflib.Configure import conf

#
_heptooldir = osp.dirname(osp.abspath(__file__))

def options(ctx):
    ctx.load('hwaf-base', tooldir=_heptooldir)
    return

def configure(ctx):
    ctx.load('hwaf-base', tooldir=_heptooldir)
    return

@conf
def find_posixlibs(ctx, **kwargs):

    ctx.load('hwaf-base', tooldir=_heptooldir)

    if not ctx.env.HWAF_FOUND_C_COMPILER:
        ctx.fatal('load a C compiler first')
        pass

    if not ctx.env.HWAF_FOUND_CXX_COMPILER:
        ctx.fatal('load a C++ compiler first')
        pass

    # find libm
    ctx.check_with(
        ctx.check,
        "m",
        features='cxx cxxprogram',
        lib='m',
        uselib_store='m',
        **kwargs
        )

    # find dl
    ctx.check_with(
        ctx.check,
        "dl",
        features='cxx cxxprogram',
        lib='dl',
        uselib_store='dl',
        **kwargs
        )

    # find pthread
    ctx.check_with(
        ctx.check,
        "pthread",
        features='cxx cxxprogram',
        lib='pthread',
        uselib_store='pthread',
        **kwargs
        )

    # find libz
    ctx.check_with(
        ctx.check,
        "zlib",
        features='cxx cxxprogram',
        header_name="zlib.h",
        lib='z',
        uselib_store='z',
        **kwargs
        )

    # find libiberty
    iberty_mandatory = kwargs.get('mandatory', True)
    if ctx.is_darwin():
        iberty_mandatory = kwargs.get('mandatory', False)
        pass
    iberty_kwargs = dict(kwargs)
    iberty_kwargs['mandatory'] = iberty_mandatory
    ctx.check_with(
        ctx.check,
        "iberty",
        features='c cprogram',
        header_name="libiberty.h",
        lib='iberty',
        uselib_store='iberty',
        **iberty_kwargs
        )

    # find bfd
    bfd_mandatory = kwargs.get('mandatory', True)
    if ctx.is_darwin():
        bfd_mandatory = kwargs.get('mandatory', False)
        pass
    bfd_kwargs = dict(kwargs)
    bfd_kwargs['mandatory'] = bfd_mandatory

    ctx.check_with(
        ctx.check,
        "bfd",
        features='cxx cxxprogram',
        defines=['PACKAGE="package-name"','PACKAGE_VERSION="package-version"',],
        header_name="bfd.h",
        lib='bfd',
        uselib_store='bfd',
        use='dl iberty',
        **bfd_kwargs
        )
    ctx.env.DEFINES_bfd = []

    # find rt
    if not ctx.is_darwin():
        ctx.check_with(
            ctx.check,
            "rt",
            features='cxx cxxprogram',
            lib='rt',
            uselib_store='rt',
            **kwargs
            )
        pass

    # test bfd
    ctx.check_cxx(
        msg="Checking bfd_init",
        okmsg="ok",
        fragment='''\
        #ifndef PACKAGE
        # define PACKAGE "package-name"
        #endif
        #ifndef PACKAGE_VERSION
        # define PACKAGE_VERSION 1
        #endif
        #include "bfd.h"
        #include <iostream>

        int main(int argc, char* argv[]) {
          bfd_init();
          bfd_error_type err = bfd_get_error();
          return (int)err;
        }
        ''',
        use="bfd dl iberty z",
        execute  = True,
        mandatory= bfd_mandatory,
        )

    ctx.env.HWAF_FOUND_POSIXLIBS = 1
    return

## EOF ##
<commit_msg>posix: properly handle static-libs (bfd,iberty). do not require a c++ compiler but a C one.<commit_after># -*- python -*-

# stdlib imports ---
import os
import os.path as osp

# waf imports ---
import waflib.Utils
import waflib.Logs as msg
from waflib.Configure import conf

#
_heptooldir = osp.dirname(osp.abspath(__file__))

def options(ctx):
    ctx.load('hwaf-base', tooldir=_heptooldir)
    ctx.load('find_gdb', tooldir=_heptooldir)
    return

def configure(ctx):
    ctx.load('hwaf-base', tooldir=_heptooldir)
    ctx.load('find_gdb', tooldir=_heptooldir)
    return

@conf
def find_posixlibs(ctx, **kwargs):

    ctx.load('hwaf-base', tooldir=_heptooldir)

    if not ctx.env.HWAF_FOUND_C_COMPILER:
        ctx.fatal('load a C compiler first')
        pass

    if not ctx.env.HWAF_FOUND_CXX_COMPILER:
        ctx.fatal('load a C++ compiler first')
        pass

    if not ctx.env.HWAF_FOUND_GDB:
        # gdb might have installed interesting libs (iberty, bfd)
        ctx.find_gdb(mandatory=False)
        pass

    # find libm
    ctx.check_with(
        ctx.check,
        "m",
        features='c cprogram',
        lib='m',
        uselib_store='m',
        **kwargs
        )

    # find dl
    ctx.check_with(
        ctx.check,
        "dl",
        features='c cprogram',
        lib='dl',
        uselib_store='dl',
        **kwargs
        )

    # find pthread
    ctx.check_with(
        ctx.check,
        "pthread",
        features='c cprogram',
        lib='pthread',
        uselib_store='pthread',
        **kwargs
        )

    # find libz
    ctx.check_with(
        ctx.check,
        "zlib",
        features='c cprogram',
        header_name="zlib.h",
        lib='z',
        uselib_store='z',
        **kwargs
        )

    extra_paths = waflib.Utils.to_list(kwargs.get('extra_paths',[]))
    if ctx.env.GDB_HOME:
        gdb = waflib.Utils.subst_vars('${GDB_HOME}', ctx.env)
        extra_paths.append(gdb)
        pass

    # find libiberty
    iberty_mandatory = kwargs.get('iberty_mandatory', False)
    if ctx.is_darwin():
        iberty_mandatory = kwargs.get('iberty_mandatory', False)
        pass
    iberty_kwargs = dict(kwargs)
    iberty_kwargs['mandatory'] = iberty_mandatory
    iberty_kwargs['extra_paths'] = extra_paths

    ctx.check_with(
        ctx.check,
        "iberty",
        features='c cstlib',
        header_name="libiberty.h",
        stlib='iberty',
        uselib_store='iberty',
        **iberty_kwargs
        )
    if ctx.env.LIBPATH_iberty and 0:
        ctx.env.STLIBPATH_iberty = ctx.env.LIBPATH_iberty
        ctx.env.STLIB_iberty = ctx.env.LIB_iberty
        ctx.env.LIB_iberty = []
        ctx.env.LIBPATH_iberty = []
        pass

    # find bfd
    bfd_mandatory = kwargs.get('bfd_mandatory', True)
    if ctx.is_darwin():
        bfd_mandatory = kwargs.get('bfd_mandatory', False)
        pass
    bfd_kwargs = dict(kwargs)
    bfd_kwargs['mandatory'] = bfd_mandatory
    bfd_kwargs['extra_paths'] = extra_paths

    ctx.check_with(
        ctx.check,
        "bfd",
        features='c cstlib',
        defines=['PACKAGE="package-name"','PACKAGE_VERSION="package-version"',],
        header_name="bfd.h",
        stlib='bfd',
        uselib_store='bfd',
        use='dl iberty',
        **bfd_kwargs
        )
    ctx.env.DEFINES_bfd = []

    # find rt
    if not ctx.is_darwin():
        ctx.check_with(
            ctx.check,
            "rt",
            features='c cprogram',
            lib='rt',
            uselib_store='rt',
            **kwargs
            )
        pass

    # test bfd
    ctx.check_cc(
        msg="Checking bfd_init",
        okmsg="ok",
        features='c cstlib',
        fragment='''\
        #ifndef PACKAGE
        # define PACKAGE "package-name"
        #endif
        #ifndef PACKAGE_VERSION
        # define PACKAGE_VERSION 1
        #endif
        #include "bfd.h"

        int test_bfd_init() {
          bfd_init();
          bfd_error_type err = bfd_get_error();
          return (int)err;
        }
        ''',
        use=['z', 'bfd', 'iberty', 'dl'],
        mandatory= bfd_mandatory,
        )

    ctx.env.HWAF_FOUND_POSIXLIBS = 1
    return

## EOF ##
<|endoftext|>


<commit_before>"""Rasterio"""

from __future__ import absolute_import

from collections import namedtuple
import logging
try:
    from logging import NullHandler
except ImportError:  # pragma: no cover
    class NullHandler(logging.Handler):
        def emit(self, record):
            pass
import warnings

from rasterio._base import (
    eval_window, window_shape, window_index, gdal_version)
from rasterio.dtypes import (
    bool_, ubyte, uint8, uint16, int16, uint32, int32, float32, float64,
    complex_, check_dtype)
from rasterio.env import ensure_env, Env
from rasterio.compat import string_types
from rasterio.profiles import default_gtiff_profile
from rasterio.transform import Affine, guard_transform
from rasterio.vfs import parse_path
from rasterio import windows

# These modules are imported from the Cython extensions, but are also import
# here to help tools like cx_Freeze find them automatically
from rasterio import _err, coords, enums, vfs

# Classes in rasterio._io are imported below just before we need them.

__all__ = [
    'band', 'open', 'copy', 'pad']
__version__ = "0.35.1"
__gdal_version__ = gdal_version()

# Rasterio attaches NullHandler to the 'rasterio' logger and its
# descendents. See
# https://docs.python.org/2/howto/logging.html#configuring-logging-for-a-library
# Applications must attach their own handlers in order to see messages.
# See rasterio/rio/main.py for an example.
log = logging.getLogger(__name__)
log.addHandler(NullHandler())

@ensure_env
def open(path, mode='r', driver=None, width=None, height=None,
         count=None, crs=None, transform=None, dtype=None, nodata=None,
         **kwargs):
    """Open file at ``path`` in ``mode`` 'r' (read), 'r+' (read and
    write), or 'w' (write) and return a dataset Reader or Updater
    object.

    In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL
    docs or ``gdal_translate --help`` on the command line),
    ``width`` (number of pixels per line) and ``height`` (number of
    lines), the ``count`` number of bands in the new file must be
    specified.  Additionally, the data type for bands such as
    ``rasterio.ubyte`` for 8-bit bands or ``rasterio.uint16`` for
    16-bit bands must be specified using the ``dtype`` argument.

    Parameters
    ----------
    mode: string
        "r" (read), "r+" (read/write), or "w" (write)
    driver: string
        driver code specifying the format name (e.g. "GTiff" or
        "JPEG"). See GDAL docs at
        http://www.gdal.org/formats_list.html (optional, required
        for writing).
    width: int
        number of pixels per line
        (optional, required for write)
    height: int
        number of lines
        (optional, required for write)
    count: int > 0
        number of bands
        (optional, required for write)
    dtype: rasterio.dtype
        the data type for bands such as ``rasterio.ubyte`` for
        8-bit bands or ``rasterio.uint16`` for 16-bit bands
        (optional, required for write)
    crs: dict or string
        Coordinate reference system
        (optional, recommended for write)
    transform: Affine instance
        Affine transformation mapping the pixel space to geographic
        space (optional, recommended for writing).
    nodata: number
        Defines pixel value to be interpreted as null/nodata
        (optional, recommended for write)

    Returns
    -------
    A ``DatasetReader`` or ``DatasetUpdater`` object.

    Notes
    -----
    In write mode, you must specify at least ``width``, ``height``,
    ``count`` and ``dtype``.

    A coordinate reference system for raster datasets in write mode
    can be defined by the ``crs`` argument. It takes Proj4 style
    mappings like

    .. code::

      {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84',
       'no_defs': True}

    An affine transformation that maps ``col,row`` pixel coordinates
    to ``x,y`` coordinates in the coordinate reference system can be
    specified using the ``transform`` argument. The value should be
    an instance of ``affine.Affine``

    .. code:: python

        >>> from affine import Affine
        >>> transform = Affine(0.5, 0.0, -180.0, 0.0, -0.5, 90.0)

    These coefficients are shown in the figure below.

    .. code::

      | x |   | a  b  c | | c |
      | y | = | d  e  f | | r |
      | 1 |   | 0  0  1 | | 1 |

      a: rate of change of X with respect to increasing column,
         i.e. pixel width
      b: rotation, 0 if the raster is oriented "north up"
      c: X coordinate of the top left corner of the top left pixel
      d: rotation, 0 if the raster is oriented "north up"
      e: rate of change of Y with respect to increasing row,
         usually a negative number (i.e. -1 * pixel height) if
         north-up.
      f: Y coordinate of the top left corner of the top left pixel

    A 6-element sequence of the affine transformation matrix
    coefficients in ``c, a, b, f, d, e`` order, (i.e. GDAL
    geotransform order) will be accepted until 1.0 (deprecated).

    A virtual filesystem can be specified. The ``vfs`` parameter may
    be an Apache Commons VFS style string beginning with "zip://" or
    "tar://"". In this case, the ``path`` must be an absolute path
    within that container.

    """
    if not isinstance(path, string_types):
        raise TypeError("invalid path: {0!r}".format(path))
    if mode and not isinstance(mode, string_types):
        raise TypeError("invalid mode: {0!r}".format(mode))
    if driver and not isinstance(driver, string_types):
        raise TypeError("invalid driver: {0!r}".format(driver))
    if dtype and not check_dtype(dtype):
        raise TypeError("invalid dtype: {0!r}".format(dtype))
    if transform:
        transform = guard_transform(transform)
    elif 'affine' in kwargs:
        affine = kwargs.pop('affine')
        transform = guard_transform(affine)

    # Get AWS credentials if we're attempting to access a raster
    # on S3.
    pth, archive, scheme = parse_path(path)
    if scheme == 's3':
        Env().get_aws_credentials()
        log.debug("AWS credentials have been obtained")

    # Create dataset instances and pass the given env, which will
    # be taken over by the dataset's context manager if it is not
    # None.
    if mode == 'r':
        from rasterio._io import RasterReader
        s = RasterReader(path)
    elif mode == 'r+':
        from rasterio._io import writer
        s = writer(path, mode)
    elif mode == 'r-':
        from rasterio._base import DatasetReader
        s = DatasetReader(path)
    elif mode == 'w':
        from rasterio._io import writer
        s = writer(path, mode, driver=driver,
                   width=width, height=height, count=count,
                   crs=crs, transform=transform, dtype=dtype,
                   nodata=nodata, **kwargs)
    else:
        raise ValueError(
            "mode string must be one of 'r', 'r+', or 'w', not %s" % mode)
    s.start()
    return s

@ensure_env
def copy(src, dst, **kw):
    """Copy a source raster to a new destination with driver specific
    creation options.

    Parameters
    ----------
    src: string
        an existing raster file
    dst: string
        valid path to output file.

    Returns
    -------
    None

    Raises
    ------
    ValueError:
        If source path is not a valid Dataset

    Notes
    -----
    A ``driver`` keyword argument with value like 'GTiff' or 'JPEG' is
    used to control the output format.

    This is the one way to create write-once files like JPEGs.
    """
    from rasterio._copy import RasterCopier
    return RasterCopier()(src, dst, **kw)

def drivers(**kwargs):
    """Create a gdal environment with registered drivers and creation
    options.

    This function is deprecated; please use ``env.Env`` instead.

    Parameters
    ----------
    **kwargs:: keyword arguments
        Configuration options that define GDAL driver behavior

        See https://trac.osgeo.org/gdal/wiki/ConfigOptions

    Returns
    -------
    GDALEnv responsible for managing the environment.

    Notes
    -----
    Use as a context manager, ``with rasterio.drivers(): ...``
    """
    warnings.warn("Deprecated; Use env.Env instead", DeprecationWarning)
    return Env(**kwargs)

Band = namedtuple('Band', ['ds', 'bidx', 'dtype', 'shape'])

def band(ds, bidx):
    """Wraps a dataset and a band index up as a 'Band'

    Parameters
    ----------
    ds: rasterio.RasterReader
        Open rasterio dataset
    bidx: int
        Band number, index starting at 1

    Returns
    -------
    a rasterio.Band
    """
    return Band(
        ds,
        bidx,
        set(ds.dtypes).pop(),
        ds.shape)

def pad(array, transform, pad_width, mode=None, **kwargs):
    """pad array and adjust affine transform matrix.

    Parameters
    ----------
    array: ndarray
        Numpy ndarray, for best results a 2D array
    transform: Affine transform
        transform object mapping pixel space to coordinates
    pad_width: int
        number of pixels to pad array on all four
    mode: str or function
        define the method for determining padded values

    Returns
    -------
    (array, transform): tuple
        Tuple of new array and affine transform

    Notes
    -----
    See numpy docs for details on mode and other kwargs:
    http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.pad.html
    """
    import numpy as np
    transform = guard_transform(transform)
    padded_array = np.pad(array, pad_width, mode, **kwargs)
    padded_trans = list(transform)
    padded_trans[2] -= pad_width * padded_trans[0]
    padded_trans[5] -= pad_width * padded_trans[4]
    return padded_array, Affine(*padded_trans[:6])

def get_data_window(arr, nodata=None):
    warnings.warn("Deprecated; Use rasterio.windows instead", DeprecationWarning)
    return windows.get_data_window(arr, nodata)

def window_union(data):
    warnings.warn("Deprecated; Use rasterio.windows instead", DeprecationWarning)
    return windows.union(data)

def window_intersection(data):
    warnings.warn("Deprecated; Use rasterio.windows instead", DeprecationWarning)
    return windows.intersection(data)

def windows_intersect(data):
    warnings.warn("Deprecated; Use rasterio.windows instead", DeprecationWarning)
    return windows.intersect(data)
<commit_msg>Remove deprecated drivers()<commit_after>"""Rasterio"""

from __future__ import absolute_import

from collections import namedtuple
import logging
try:
    from logging import NullHandler
except ImportError:  # pragma: no cover
    class NullHandler(logging.Handler):
        def emit(self, record):
            pass
import warnings

from rasterio._base import (
    eval_window, window_shape, window_index, gdal_version)
from rasterio.dtypes import (
    bool_, ubyte, uint8, uint16, int16, uint32, int32, float32, float64,
    complex_, check_dtype)
from rasterio.env import ensure_env, Env
from rasterio.compat import string_types
from rasterio.profiles import default_gtiff_profile
from rasterio.transform import Affine, guard_transform
from rasterio.vfs import parse_path
from rasterio import windows

# These modules are imported from the Cython extensions, but are also import
# here to help tools like cx_Freeze find them automatically
from rasterio import _err, coords, enums, vfs

# Classes in rasterio._io are imported below just before we need them.

__all__ = [
    'band', 'open', 'copy', 'pad']
__version__ = "0.35.1"
__gdal_version__ = gdal_version()

# Rasterio attaches NullHandler to the 'rasterio' logger and its
# descendents. See
# https://docs.python.org/2/howto/logging.html#configuring-logging-for-a-library
# Applications must attach their own handlers in order to see messages.
# See rasterio/rio/main.py for an example.
log = logging.getLogger(__name__)
log.addHandler(NullHandler())

@ensure_env
def open(path, mode='r', driver=None, width=None, height=None,
         count=None, crs=None, transform=None, dtype=None, nodata=None,
         **kwargs):
    """Open file at ``path`` in ``mode`` 'r' (read), 'r+' (read and
    write), or 'w' (write) and return a dataset Reader or Updater
    object.

    In write mode, a driver name such as "GTiff" or "JPEG" (see GDAL
    docs or ``gdal_translate --help`` on the command line),
    ``width`` (number of pixels per line) and ``height`` (number of
    lines), the ``count`` number of bands in the new file must be
    specified.  Additionally, the data type for bands such as
    ``rasterio.ubyte`` for 8-bit bands or ``rasterio.uint16`` for
    16-bit bands must be specified using the ``dtype`` argument.

    Parameters
    ----------
    mode: string
        "r" (read), "r+" (read/write), or "w" (write)
    driver: string
        driver code specifying the format name (e.g. "GTiff" or
        "JPEG"). See GDAL docs at
        http://www.gdal.org/formats_list.html (optional, required
        for writing).
    width: int
        number of pixels per line
        (optional, required for write)
    height: int
        number of lines
        (optional, required for write)
    count: int > 0
        number of bands
        (optional, required for write)
    dtype: rasterio.dtype
        the data type for bands such as ``rasterio.ubyte`` for
        8-bit bands or ``rasterio.uint16`` for 16-bit bands
        (optional, required for write)
    crs: dict or string
        Coordinate reference system
        (optional, recommended for write)
    transform: Affine instance
        Affine transformation mapping the pixel space to geographic
        space (optional, recommended for writing).
    nodata: number
        Defines pixel value to be interpreted as null/nodata
        (optional, recommended for write)

    Returns
    -------
    A ``DatasetReader`` or ``DatasetUpdater`` object.

    Notes
    -----
    In write mode, you must specify at least ``width``, ``height``,
    ``count`` and ``dtype``.

    A coordinate reference system for raster datasets in write mode
    can be defined by the ``crs`` argument. It takes Proj4 style
    mappings like

    .. code::

      {'proj': 'longlat', 'ellps': 'WGS84', 'datum': 'WGS84',
       'no_defs': True}

    An affine transformation that maps ``col,row`` pixel coordinates
    to ``x,y`` coordinates in the coordinate reference system can be
    specified using the ``transform`` argument. The value should be
    an instance of ``affine.Affine``

    .. code:: python

        >>> from affine import Affine
        >>> transform = Affine(0.5, 0.0, -180.0, 0.0, -0.5, 90.0)

    These coefficients are shown in the figure below.

    .. code::

      | x |   | a  b  c | | c |
      | y | = | d  e  f | | r |
      | 1 |   | 0  0  1 | | 1 |

      a: rate of change of X with respect to increasing column,
         i.e. pixel width
      b: rotation, 0 if the raster is oriented "north up"
      c: X coordinate of the top left corner of the top left pixel
      d: rotation, 0 if the raster is oriented "north up"
      e: rate of change of Y with respect to increasing row,
         usually a negative number (i.e. -1 * pixel height) if
         north-up.
      f: Y coordinate of the top left corner of the top left pixel

    A 6-element sequence of the affine transformation matrix
    coefficients in ``c, a, b, f, d, e`` order, (i.e. GDAL
    geotransform order) will be accepted until 1.0 (deprecated).

    A virtual filesystem can be specified. The ``vfs`` parameter may
    be an Apache Commons VFS style string beginning with "zip://" or
    "tar://"". In this case, the ``path`` must be an absolute path
    within that container.

    """
    if not isinstance(path, string_types):
        raise TypeError("invalid path: {0!r}".format(path))
    if mode and not isinstance(mode, string_types):
        raise TypeError("invalid mode: {0!r}".format(mode))
    if driver and not isinstance(driver, string_types):
        raise TypeError("invalid driver: {0!r}".format(driver))
    if dtype and not check_dtype(dtype):
        raise TypeError("invalid dtype: {0!r}".format(dtype))
    if transform:
        transform = guard_transform(transform)
    elif 'affine' in kwargs:
        affine = kwargs.pop('affine')
        transform = guard_transform(affine)

    # Get AWS credentials if we're attempting to access a raster
    # on S3.
    pth, archive, scheme = parse_path(path)
    if scheme == 's3':
        Env().get_aws_credentials()
        log.debug("AWS credentials have been obtained")

    # Create dataset instances and pass the given env, which will
    # be taken over by the dataset's context manager if it is not
    # None.
    if mode == 'r':
        from rasterio._io import RasterReader
        s = RasterReader(path)
    elif mode == 'r+':
        from rasterio._io import writer
        s = writer(path, mode)
    elif mode == 'r-':
        from rasterio._base import DatasetReader
        s = DatasetReader(path)
    elif mode == 'w':
        from rasterio._io import writer
        s = writer(path, mode, driver=driver,
                   width=width, height=height, count=count,
                   crs=crs, transform=transform, dtype=dtype,
                   nodata=nodata, **kwargs)
    else:
        raise ValueError(
            "mode string must be one of 'r', 'r+', or 'w', not %s" % mode)
    s.start()
    return s

@ensure_env
def copy(src, dst, **kw):
    """Copy a source raster to a new destination with driver specific
    creation options.

    Parameters
    ----------
    src: string
        an existing raster file
    dst: string
        valid path to output file.

    Returns
    -------
    None

    Raises
    ------
    ValueError:
        If source path is not a valid Dataset

    Notes
    -----
    A ``driver`` keyword argument with value like 'GTiff' or 'JPEG' is
    used to control the output format.

    This is the one way to create write-once files like JPEGs.
    """
    from rasterio._copy import RasterCopier
    return RasterCopier()(src, dst, **kw)

Band = namedtuple('Band', ['ds', 'bidx', 'dtype', 'shape'])

def band(ds, bidx):
    """Wraps a dataset and a band index up as a 'Band'

    Parameters
    ----------
    ds: rasterio.RasterReader
        Open rasterio dataset
    bidx: int
        Band number, index starting at 1

    Returns
    -------
    a rasterio.Band
    """
    return Band(
        ds,
        bidx,
        set(ds.dtypes).pop(),
        ds.shape)

def pad(array, transform, pad_width, mode=None, **kwargs):
    """pad array and adjust affine transform matrix.

    Parameters
    ----------
    array: ndarray
        Numpy ndarray, for best results a 2D array
    transform: Affine transform
        transform object mapping pixel space to coordinates
    pad_width: int
        number of pixels to pad array on all four
    mode: str or function
        define the method for determining padded values

    Returns
    -------
    (array, transform): tuple
        Tuple of new array and affine transform

    Notes
    -----
    See numpy docs for details on mode and other kwargs:
    http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.pad.html
    """
    import numpy as np
    transform = guard_transform(transform)
    padded_array = np.pad(array, pad_width, mode, **kwargs)
    padded_trans = list(transform)
    padded_trans[2] -= pad_width * padded_trans[0]
    padded_trans[5] -= pad_width * padded_trans[4]
    return padded_array, Affine(*padded_trans[:6])

def get_data_window(arr, nodata=None):
    warnings.warn("Deprecated; Use rasterio.windows instead", DeprecationWarning)
    return windows.get_data_window(arr, nodata)

def window_union(data):
    warnings.warn("Deprecated; Use rasterio.windows instead", DeprecationWarning)
    return windows.union(data)

def window_intersection(data):
    warnings.warn("Deprecated; Use rasterio.windows instead", DeprecationWarning)
    return windows.intersection(data)

def windows_intersect(data):
    warnings.warn("Deprecated; Use rasterio.windows instead", DeprecationWarning)
    return windows.intersect(data)
<|endoftext|>