<commit_before>"""VCD Value tracker."""

import re
from typing import Tuple, Optional, Union
from hdltools.vcd import VCDScope
from hdltools.vcd.parser import BaseVCDParser, VCDParserError
from hdltools.vcd.mixins import VCDTriggerMixin
from hdltools.patterns import Pattern
from hdltools.vcd.trigger import VCDTriggerDescriptor
from hdltools.vcd.history import VCDValueHistory, VCDValueHistoryEntry

# TODO: multi value tracker
# FIXME: avoid expensive duplications of data
class VCDValueTracker(BaseVCDParser, VCDTriggerMixin):
    """VCD Value tracker.

    Track a tagged value through system hierarchy.
    """

    def __init__(
        self,
        track: Pattern,
        restrict_src: Optional[Union[Tuple[str], VCDScope]] = None,
        restrict_dest: Optional[Union[Tuple[str], VCDScope]] = None,
        inclusive_src=False,
        inclusive_dest=False,
        ignore_signals: Optional[Tuple[str]] = None,
        ignore_scopes: Optional[Tuple[str]] = None,
        anchors: Optional[Tuple[str, str]] = None,
        preconditions: Optional[Tuple[VCDTriggerDescriptor]] = None,
        postconditions: Optional[Tuple[VCDTriggerDescriptor]] = None,
        time_range: Optional[Tuple[int, int]] = None,
        track_all: bool = False,
    ):
        """Initialize."""
        super().__init__()
        if not isinstance(track, Pattern):
            raise TypeError("track must be a Pattern object")
        self._track_value = track
        self._track_all = track_all
        self._track_history = VCDValueHistory()
        self._complete_value_history = VCDValueHistory()
        self._full_history = VCDValueHistory()
        self._stmt_count = 0
        if isinstance(restrict_src, tuple):
            restrict_src = VCDScope(*restrict_src)
        if isinstance(restrict_dest, tuple):
            restrict_dest = VCDScope(*restrict_dest)
        self._restrict_src = restrict_src
        self._restrict_dest = restrict_dest
        self._inclusive_src = inclusive_src
        self._inclusive_dest = inclusive_dest
        if ignore_signals is not None:
            self._ignore_sig = [re.compile(ign) for ign in ignore_signals]
        else:
            self._ignore_sig = None
        if ignore_scopes is not None:
            self._ignore_scope = [re.compile(ign) for ign in ignore_scopes]
        else:
            self._ignore_scope = None

        # source, destination anchors
        src_anchor, dest_anchor = (
            anchors if anchors is not None else (None, None)
        )
        self._src_anchor = (
            re.compile(src_anchor) if src_anchor is not None else None
        )
        self._dest_anchor = (
            re.compile(dest_anchor) if dest_anchor is not None else None
        )
        self._maybe_src = None
        self._maybe_dest = None
        self._wait_precondition = False
        self._wait_postcondition = False
        self._postconditions = []

        if time_range is not None:
            if not isinstance(time_range, (tuple, list)):
                raise TypeError("time_range must be a list")
            if len(time_range) != 2:
                raise ValueError("time_range must have 2 elements exactly")
            start, end = time_range
            if not isinstance(start, int) or not isinstance(end, int):
                raise TypeError("start and end in time_range must be integers")
            self._hist_start = start
            self._hist_end = end
        else:
            self._hist_start = None
            self._hist_end = None

        if postconditions is not None:
            if isinstance(postconditions, VCDTriggerDescriptor):
                self._postconditions.append(postconditions)
            else:
                for postcondition in postconditions:
                    if not isinstance(postcondition, VCDTriggerDescriptor):
                        raise TypeError(
                            "precondition must be a VCDTriggerDescriptor object"
                        )
                    self._postconditions.append(postcondition)
        if preconditions is not None:
            self._wait_precondition = True
            if isinstance(preconditions, VCDTriggerDescriptor):
                self.add_trigger_level(preconditions)
            else:
                for precondition in preconditions:
                    if not isinstance(precondition, VCDTriggerDescriptor):
                        raise TypeError(
                            "precondition must be a VCDTriggerDescriptor object"
                        )
                    self.add_trigger_level(precondition)

            # arm trigger
            self.trigger_callback = self._precondition_callback
            self.arm_trigger()

    # FIXME: this is a placeholder
    def _precondition_callback(self):
        """Precondition callback."""
        print("DEBUG: reached preconditions")
        self._wait_precondition = False
        # setup postconditions
        if self._postconditions:
            self._wait_postcondition = True
            self.trigger_reset()
            for postcondition in self._postconditions:
                self.add_trigger_level(postcondition)

            self.trigger_callback = self._postcondition_callback
            self.arm_trigger()

    def _postcondition_callback(self):
        """Postcondition callback."""
        print("DEBUG: reached postconditions; stopping")
        self._wait_postcondition = False
        self._abort_parser()

    def _parse_progress(self):
        """Track parsing progress."""
        self._stmt_count += 1
        # print("DEBUG: #lines = {}".format(self._current_line))

    def header_statement_handler(self, stmt, fields):
        """Handle header statements.

        Build variable-scope map.
        """
        self._parse_progress()

    def initial_value_handler(self, stmt, fields):
        """Handle initial values."""
        self._parse_progress()
        var = self.variables[fields["var"]]
        if self._track_all:
            self._add_to_history(var.scope, var.name, 0)
        if self._track_value.match(fields["value"]):
            # found
            self._add_to_tracked_history(var.scope, var.name, 0)
            self._add_to_value_history(var.scope, var.name, 0)

    def value_change_handler(self, stmt, fields):
        """Handle value change."""
        self._parse_progress()
        var = self.variables[fields["var"]]
        if self._track_all:
            self._add_to_history(var.scope, var.name, self.current_time)
        # handle start time
        if self._track_value.match(fields["value"]):
            # add to complete tracking history
            self._add_to_value_history(var.scope, var.name, self.current_time)
        if (
            self._hist_start is not None
            and self.current_time < self._hist_start
        ):
            return
        if self._hist_end is not None and self.current_time > self._hist_end:
            # done
            self._abort_parser()
        if self._wait_precondition and self._triggered is False:
            return
        var_scope = var.scope
        in_src_scope = self._restrict_src is not None and (
            var_scope == self._restrict_src
            or (self._restrict_src.contains(var_scope) and self._inclusive_src)
        )

        in_dest_scope = self._restrict_dest is not None and (
            var_scope == self._restrict_dest
            or (
                self._restrict_dest.contains(var_scope)
                and self._inclusive_dest
            )
        )
        if (self._restrict_src is not None and not in_src_scope) and (
            self._restrict_dest is not None and not in_dest_scope
        ):
            return
        if self._track_value.match(fields["value"]):
            if self._ignore_sig is not None:
                for patt in self._ignore_sig:
                    if (
                        patt.match(self.variables[fields["var"]].name)
                        is not None
                    ):
                        # ignore
                        return
            print("DEBUG: current time = {}".format(self.current_time))
            print(
                "DEBUG: found value match, variable is {}".format(
                    self.variables[fields["var"]]
                )
            )
            if fields["var"] not in self.variables:
                raise VCDParserError(
                    'unknown variable in change event: "{}"'.format(
                        fields["var"]
                    )
                )
            idx = self._add_to_tracked_history(
                var.scope, var.name, self.current_time
            )
            # FIXME: make sure that anchors are not used without scope restriction
            if in_src_scope:
                if self._src_anchor is not None and self._maybe_dest is None:
                    if (
                        self._src_anchor.match(
                            self.variables[fields["var"]].name
                        )
                        is not None
                    ):
                        # new probable source
                        self._maybe_src = idx
                elif self._maybe_dest is None:
                    # anything that appears is probable source
                    self._maybe_src = idx

            if in_dest_scope:
                if self._maybe_dest is None and self._maybe_src is not None:
                    if (
                        self._dest_anchor is not None
                        and self._dest_anchor.match(
                            self.variables[fields["var"]].name
                        )
                        is not None
                    ):
                        self._maybe_dest = idx
                    elif self._dest_anchor is None:
                        self._maybe_dest = idx

    @property
    def history(self):
        """Get tracking history."""
        return self._track_history

    @property
    def full_history(self):
        """Get full history if available."""
        if self._track_all:
            return self._full_history
        return self.history

    @property
    def full_value_history(self):
        """Get full value match history."""
        return self._complete_value_history

    @property
    def maybe_src(self):
        """Get probable source."""
        return self._maybe_src

    @property
    def maybe_dest(self):
        """Get probable destination."""
        return self._maybe_dest

    def _add_to_value_history(self, scope, signal, time):
        """Add to value history."""
        self._complete_value_history.add_entry(
            VCDValueHistoryEntry(scope, signal, time)
        )
        return len(self._full_history) - 1

    def _add_to_history(self, scope, signal, time):
        """Add to history."""
        self._full_history.add_entry(VCDValueHistoryEntry(scope, signal, time))
        return len(self._full_history) - 1

    def _add_to_tracked_history(self, scope, signal, time):
        """Add to history."""
        self._track_history.add_entry(
            VCDValueHistoryEntry(scope, signal, time)
        )
        return len(self._track_history) - 1

    def parse(self, data):
        """Parse."""
        self._stmt_count = 0
        return super().parse(data)
<commit_msg>Only print when explicitly debugging<commit_after>"""VCD Value tracker."""

import re
from typing import Tuple, Optional, Union
from hdltools.vcd import VCDScope
from hdltools.vcd.parser import BaseVCDParser, VCDParserError
from hdltools.vcd.mixins import VCDTriggerMixin
from hdltools.patterns import Pattern
from hdltools.vcd.trigger import VCDTriggerDescriptor
from hdltools.vcd.history import VCDValueHistory, VCDValueHistoryEntry

# TODO: multi value tracker
# FIXME: avoid expensive duplications of data
class VCDValueTracker(BaseVCDParser, VCDTriggerMixin):
    """VCD Value tracker.

    Track a tagged value through system hierarchy.
    """

    def __init__(
        self,
        track: Pattern,
        restrict_src: Optional[Union[Tuple[str], VCDScope]] = None,
        restrict_dest: Optional[Union[Tuple[str], VCDScope]] = None,
        inclusive_src=False,
        inclusive_dest=False,
        ignore_signals: Optional[Tuple[str]] = None,
        ignore_scopes: Optional[Tuple[str]] = None,
        anchors: Optional[Tuple[str, str]] = None,
        preconditions: Optional[Tuple[VCDTriggerDescriptor]] = None,
        postconditions: Optional[Tuple[VCDTriggerDescriptor]] = None,
        time_range: Optional[Tuple[int, int]] = None,
        track_all: bool = False,
        debug: bool = False
    ):
        """Initialize."""
        super().__init__(debug=debug)
        if not isinstance(track, Pattern):
            raise TypeError("track must be a Pattern object")
        self._track_value = track
        self._track_all = track_all
        self._track_history = VCDValueHistory()
        self._complete_value_history = VCDValueHistory()
        self._full_history = VCDValueHistory()
        self._stmt_count = 0
        if isinstance(restrict_src, tuple):
            restrict_src = VCDScope(*restrict_src)
        if isinstance(restrict_dest, tuple):
            restrict_dest = VCDScope(*restrict_dest)
        self._restrict_src = restrict_src
        self._restrict_dest = restrict_dest
        self._inclusive_src = inclusive_src
        self._inclusive_dest = inclusive_dest
        if ignore_signals is not None:
            self._ignore_sig = [re.compile(ign) for ign in ignore_signals]
        else:
            self._ignore_sig = None
        if ignore_scopes is not None:
            self._ignore_scope = [re.compile(ign) for ign in ignore_scopes]
        else:
            self._ignore_scope = None

        # source, destination anchors
        src_anchor, dest_anchor = (
            anchors if anchors is not None else (None, None)
        )
        self._src_anchor = (
            re.compile(src_anchor) if src_anchor is not None else None
        )
        self._dest_anchor = (
            re.compile(dest_anchor) if dest_anchor is not None else None
        )
        self._maybe_src = None
        self._maybe_dest = None
        self._wait_precondition = False
        self._wait_postcondition = False
        self._postconditions = []

        if time_range is not None:
            if not isinstance(time_range, (tuple, list)):
                raise TypeError("time_range must be a list")
            if len(time_range) != 2:
                raise ValueError("time_range must have 2 elements exactly")
            start, end = time_range
            if not isinstance(start, int) or not isinstance(end, int):
                raise TypeError("start and end in time_range must be integers")
            self._hist_start = start
            self._hist_end = end
        else:
            self._hist_start = None
            self._hist_end = None

        if postconditions is not None:
            if isinstance(postconditions, VCDTriggerDescriptor):
                self._postconditions.append(postconditions)
            else:
                for postcondition in postconditions:
                    if not isinstance(postcondition, VCDTriggerDescriptor):
                        raise TypeError(
                            "precondition must be a VCDTriggerDescriptor object"
                        )
                    self._postconditions.append(postcondition)
        if preconditions is not None:
            self._wait_precondition = True
            if isinstance(preconditions, VCDTriggerDescriptor):
                self.add_trigger_level(preconditions)
            else:
                for precondition in preconditions:
                    if not isinstance(precondition, VCDTriggerDescriptor):
                        raise TypeError(
                            "precondition must be a VCDTriggerDescriptor object"
                        )
                    self.add_trigger_level(precondition)

            # arm trigger
            self.trigger_callback = self._precondition_callback
            self.arm_trigger()

    # FIXME: this is a placeholder
    def _precondition_callback(self):
        """Precondition callback."""
        if self._debug:
            print("DEBUG: reached preconditions")
        self._wait_precondition = False
        # setup postconditions
        if self._postconditions:
            self._wait_postcondition = True
            self.trigger_reset()
            for postcondition in self._postconditions:
                self.add_trigger_level(postcondition)

            self.trigger_callback = self._postcondition_callback
            self.arm_trigger()

    def _postcondition_callback(self):
        """Postcondition callback."""
        if self._debug:
            print("DEBUG: reached postconditions; stopping")
        self._wait_postcondition = False
        self._abort_parser()

    def _parse_progress(self):
        """Track parsing progress."""
        self._stmt_count += 1
        # print("DEBUG: #lines = {}".format(self._current_line))

    def header_statement_handler(self, stmt, fields):
        """Handle header statements.

        Build variable-scope map.
        """
        self._parse_progress()

    def initial_value_handler(self, stmt, fields):
        """Handle initial values."""
        self._parse_progress()
        var = self.variables[fields["var"]]
        if self._track_all:
            self._add_to_history(var.scope, var.name, 0)
        if self._track_value.match(fields["value"]):
            # found
            self._add_to_tracked_history(var.scope, var.name, 0)
            self._add_to_value_history(var.scope, var.name, 0)

    def value_change_handler(self, stmt, fields):
        """Handle value change."""
        self._parse_progress()
        var = self.variables[fields["var"]]
        if self._track_all:
            self._add_to_history(var.scope, var.name, self.current_time)
        # handle start time
        if self._track_value.match(fields["value"]):
            # add to complete tracking history
            self._add_to_value_history(var.scope, var.name, self.current_time)
        if (
            self._hist_start is not None
            and self.current_time < self._hist_start
        ):
            return
        if self._hist_end is not None and self.current_time > self._hist_end:
            # done
            self._abort_parser()
        if self._wait_precondition and self._triggered is False:
            return
        var_scope = var.scope
        in_src_scope = self._restrict_src is not None and (
            var_scope == self._restrict_src
            or (self._restrict_src.contains(var_scope) and self._inclusive_src)
        )

        in_dest_scope = self._restrict_dest is not None and (
            var_scope == self._restrict_dest
            or (
                self._restrict_dest.contains(var_scope)
                and self._inclusive_dest
            )
        )
        if (self._restrict_src is not None and not in_src_scope) and (
            self._restrict_dest is not None and not in_dest_scope
        ):
            return
        if self._track_value.match(fields["value"]):
            if self._ignore_sig is not None:
                for patt in self._ignore_sig:
                    if (
                        patt.match(self.variables[fields["var"]].name)
                        is not None
                    ):
                        # ignore
                        return
            if self._debug:
                print("DEBUG: current time = {}".format(self.current_time))
                print(
                    "DEBUG: found value match, variable is {}".format(
                        self.variables[fields["var"]]
                    )
                )
            if fields["var"] not in self.variables:
                raise VCDParserError(
                    'unknown variable in change event: "{}"'.format(
                        fields["var"]
                    )
                )
            idx = self._add_to_tracked_history(
                var.scope, var.name, self.current_time
            )
            # FIXME: make sure that anchors are not used without scope restriction
            if in_src_scope:
                if self._src_anchor is not None and self._maybe_dest is None:
                    if (
                        self._src_anchor.match(
                            self.variables[fields["var"]].name
                        )
                        is not None
                    ):
                        # new probable source
                        self._maybe_src = idx
                elif self._maybe_dest is None:
                    # anything that appears is probable source
                    self._maybe_src = idx

            if in_dest_scope:
                if self._maybe_dest is None and self._maybe_src is not None:
                    if (
                        self._dest_anchor is not None
                        and self._dest_anchor.match(
                            self.variables[fields["var"]].name
                        )
                        is not None
                    ):
                        self._maybe_dest = idx
                    elif self._dest_anchor is None:
                        self._maybe_dest = idx

    @property
    def history(self):
        """Get tracking history."""
        return self._track_history

    @property
    def full_history(self):
        """Get full history if available."""
        if self._track_all:
            return self._full_history
        return self.history

    @property
    def full_value_history(self):
        """Get full value match history."""
        return self._complete_value_history

    @property
    def maybe_src(self):
        """Get probable source."""
        return self._maybe_src

    @property
    def maybe_dest(self):
        """Get probable destination."""
        return self._maybe_dest

    def _add_to_value_history(self, scope, signal, time):
        """Add to value history."""
        self._complete_value_history.add_entry(
            VCDValueHistoryEntry(scope, signal, time)
        )
        return len(self._full_history) - 1

    def _add_to_history(self, scope, signal, time):
        """Add to history."""
        self._full_history.add_entry(VCDValueHistoryEntry(scope, signal, time))
        return len(self._full_history) - 1

    def _add_to_tracked_history(self, scope, signal, time):
        """Add to history."""
        self._track_history.add_entry(
            VCDValueHistoryEntry(scope, signal, time)
        )
        return len(self._track_history) - 1

    def parse(self, data):
        """Parse."""
        self._stmt_count = 0
        return super().parse(data)
<|endoftext|>


<commit_before>from Tag import Tag
import time
from datetime import datetime

__author__ = "Peter Wolf"
__mail__ = "pwolf2310@gmail.com"
__date__ = "2016-12-25"

DATE_FORMAT = "%Y-%m-%d %H:%M:%S"

class Item:

    """ An item retrieved from pr0gramm.com """

    def __init__(self, id):
        self.id = id
        self.tags = []
        self.promoted_stamp = None
        self.user = None
        self.created = None

        self.image_link = ""
        self.image_width = -1
        self.image_height = -1
        self.thumb_link = ""
        self.full_size_link = None
        self.source = None
        self.audio = False

        self.upvotes = -1
        self.downvotes = -1
        self.flags = 0

    def __str__(self):
        return "Item {0}, Promoted: {1}, Created: {3}, User: {2}".format(
            self.id, self.promoted_stamp, self.user,
            time.strftime(DATE_FORMAT, time.localtime(self.created)))

    def __lt__(self, other):
        return self.id < other.id

    def __gt__(self, other):
        return self.id > other.id

    def __eq__(self, other):
        return self.id == other.id

    def __ne__(self, other):
        return not self.__eq__(other)

    def description(self):
        return "Item {0}, Promoted: {1}, Created: {3}, User: {2}\n".format(
            self.id, self.promoted_stamp, self.user,
            time.strftime(DATE_FORMAT, time.localtime(self.created))) \
            + "Image: {0} ({1}x{2})\n".format(
            self.image_link, self.image_width, self.image_height) \
            + "Thumb: {0}\n".format(self.thumb_link) \
            + "Full Size: {0}\n".format(self.full_size_link) \
            + "Source: {0}\n".format(self.source) \
            + "Flags: {0}, {1} Upvotes, {2} Downvotes\n".format(
                self.flags, self.upvotes, self.downvotes) \
            + "Tags: {}".format(", ".join([str(tag) for tag in self.tags]))

    def isImage(self):
        return self.image_link.endswith(".jpg") \
            or self.image_link.endswith(".png")

    def isVideo(self):
        return self.image_link.endswith(".mp4") \
            or self.image_link.endswith(".gif")

    def getAge(self):
        return datetime.now() - datetime.fromtimestamp(self.created)

    def setTagsFromJSON(self, json_tags):
        self.tags = []
        for json_tag in json_tags:
            self.tags.append(
                Tag(
                    json_tag["id"],
                    json_tag["confidence"],
                    json_tag["tag"]))

    @staticmethod
    def parseFromJSON(json_item):
        parsed_item = Item(json_item["id"])
        parsed_item.promoted_stamp = json_item["promoted"]
        parsed_item.user = json_item["user"]
        parsed_item.created = json_item["created"]
        parsed_item.image_link = json_item["image"]
        parsed_item.image_width = json_item["width"]
        parsed_item.image_height = json_item["height"]
        parsed_item.thumb_link = json_item["thumb"]
        parsed_item.full_size_link = json_item["fullsize"]
        parsed_item.source = json_item["source"]
        parsed_item.audio = json_item["audio"]
        parsed_item.upvotes = json_item["up"]
        parsed_item.downvotes = json_item["down"]
        parsed_item.flags = json_item["flags"]
        return parsed_item

    @staticmethod
    def mockItem():
        mock = Item(1679829)
        mock.promoted_stamp = 204476
        mock.user = "ExampleUser"
        mock.created = 1482583310
        mock.image_link = "2016/12/24/058d591eb1eddbd3.mp4"
        mock.image_width = 640
        mock.image_height = 360
        mock.thumb_link = "2016/12/24/058d591eb1eddbd3.jpg"
        mock.full_size_link = ""
        mock.source = ""
        mock.audio = False
        mock.upvotes = 699
        mock.downvotes = 11
        mock.flags = 1
        return mock
<commit_msg>added getter to get the relevant id for retrieving newer/older<commit_after>from Tag import Tag
import time
from datetime import datetime

__author__ = "Peter Wolf"
__mail__ = "pwolf2310@gmail.com"
__date__ = "2016-12-25"

DATE_FORMAT = "%Y-%m-%d %H:%M:%S"

class Item:

    """ An item retrieved from pr0gramm.com """

    def __init__(self, id):
        self.id = id
        self.tags = []
        self.promoted_stamp = None
        self.user = None
        self.created = None

        self.image_link = ""
        self.image_width = -1
        self.image_height = -1
        self.thumb_link = ""
        self.full_size_link = None
        self.source = None
        self.audio = False

        self.upvotes = -1
        self.downvotes = -1
        self.flags = 0

    def __str__(self):
        return "Item {0}, Promoted: {1}, Created: {3}, User: {2}".format(
            self.id, self.promoted_stamp, self.user,
            time.strftime(DATE_FORMAT, time.localtime(self.created)))

    def __lt__(self, other):
        return self.id < other.id

    def __gt__(self, other):
        return self.id > other.id

    def __eq__(self, other):
        return self.id == other.id

    def __ne__(self, other):
        return not self.__eq__(other)

    def description(self):
        return "Item {0}, Promoted: {1}, Created: {3}, User: {2}\n".format(
            self.id, self.promoted_stamp, self.user,
            time.strftime(DATE_FORMAT, time.localtime(self.created))) \
            + "Image: {0} ({1}x{2})\n".format(
            self.image_link, self.image_width, self.image_height) \
            + "Thumb: {0}\n".format(self.thumb_link) \
            + "Full Size: {0}\n".format(self.full_size_link) \
            + "Source: {0}\n".format(self.source) \
            + "Flags: {0}, {1} Upvotes, {2} Downvotes\n".format(
                self.flags, self.upvotes, self.downvotes) \
            + "Tags: {}".format(", ".join([str(tag) for tag in self.tags]))

    def isImage(self):
        return self.image_link.endswith(".jpg") \
            or self.image_link.endswith(".png")

    def isVideo(self):
        return self.image_link.endswith(".mp4") \
            or self.image_link.endswith(".gif")

    def getAge(self):
        return datetime.now() - datetime.fromtimestamp(self.created)

    def getSortId(self):
        return self.promoted_stamp

    def setTagsFromJSON(self, json_tags):
        self.tags = []
        for json_tag in json_tags:
            self.tags.append(
                Tag(
                    json_tag["id"],
                    json_tag["confidence"],
                    json_tag["tag"]))

    @staticmethod
    def parseFromJSON(json_item):
        parsed_item = Item(json_item["id"])
        parsed_item.promoted_stamp = json_item["promoted"]
        parsed_item.user = json_item["user"]
        parsed_item.created = json_item["created"]
        parsed_item.image_link = json_item["image"]
        parsed_item.image_width = json_item["width"]
        parsed_item.image_height = json_item["height"]
        parsed_item.thumb_link = json_item["thumb"]
        parsed_item.full_size_link = json_item["fullsize"]
        parsed_item.source = json_item["source"]
        parsed_item.audio = json_item["audio"]
        parsed_item.upvotes = json_item["up"]
        parsed_item.downvotes = json_item["down"]
        parsed_item.flags = json_item["flags"]
        return parsed_item

    @staticmethod
    def mockItem():
        mock = Item(1679829)
        mock.promoted_stamp = 204476
        mock.user = "ExampleUser"
        mock.created = 1482583310
        mock.image_link = "2016/12/24/058d591eb1eddbd3.mp4"
        mock.image_width = 640
        mock.image_height = 360
        mock.thumb_link = "2016/12/24/058d591eb1eddbd3.jpg"
        mock.full_size_link = ""
        mock.source = ""
        mock.audio = False
        mock.upvotes = 699
        mock.downvotes = 11
        mock.flags = 1
        return mock
<|endoftext|>


<commit_before>"""
    **Author :** *Jay Krishna*

    This module detects the presence of signal sent by beacon. Dynamic thresholding is applied based upon leading & lagging cells.

    Approach
    ----------------------------

    * Signal is broken down in chunks of one second each.
    * At each point of smaller signal threshold is calculated based upon average of lagging & leading reference cells after removing guard cells from both sides.
    * Point where APRS signal is suppossed to start is found & checked against peak induced by random noise.

    Reference
    ------------------------------

    `Barkat, Mourad & Varshney, P.K (1987). On adaptive cell-averaging CFAR (Constant False-Alarm Rate) radar signal detection. Final Technical Report, Jun. 1984 - Dec. 1986 Syracuse Univ., NY. Dept. of Electrical and Computer Engineering <https://goo.gl/15t64a>`_

"""

import numpy as np
from scipy import signal
import math

from Modules import SignalData

def merge(peak, signal):
    """

        Parameters
        -----------------------
            peak : list
                Points of presence of beacon.
            signal : ndarray
                Numpy array of signal.

        Returns
        -------------------------
            final_peak : list
                Points of presence of beacon after merging nearby peaks.

    """

    final_peak = []
    start = 0

    for end in range(1, peak.shape[0]):
        if(peak[end] - peak[end - 1] < 200):
            pass
        else:
            point = peak[start] + np.argmax(signal[peak[start]:peak[end - 1]])
            final_peak.append(point)
            start = end

    if(start == 0):
        point = peak[start] + np.argmax(signal[peak[start]:peak[end - 1]])
        final_peak.append(point)

    if(peak[start] > final_peak[-1]):
        point = peak[start] + np.argmax(signal[peak[start]:peak[end - 1]])
        final_peak.append(point)

    return final_peak

def radar_detect(radar, signal):
    """

        Parameters
        -----------------------
            radar : ndarray
                Threshold values calculated at each point.
            signal : ndarray
                Numpy array of signal.

        Returns
        -------------------------
            peak : list
                Points of presence of beacon.

    """

    peak = []
    for i in range(signal.shape[0]):

        if(signal[i] > radar[i]):
            peak.append(i)

    peak = np.array(peak, dtype=int)

    if(peak.shape[0] > 1):
        peak = merge(peak, signal)

    return peak

def cfar(signal, refLength=1000, guardLength=100, p=0.01):
    """
        Parameters
        -----------------------
            signal : ndarray
                Numpy complex array of signal.
            refLength : int
                Length of reference cells
            guardLength : int
                Length of guard cells
            p : float
                Accepted probability of false alarm.

        Returns
        -----------------------
            point : int
                Starting point of aprs signal if present.

    """

    N = 2 * refLength
    alpha = (math.pow(p, -1 / N) - 1) * N

    cfarWin = np.ones(((refLength + guardLength) * 2 + 1, 1))
    cfarWin[refLength + 1:refLength + 1 + 2 * guardLength] = 0
    cfarWin = cfarWin / sum(cfarWin)
    signal = np.reshape(signal, (signal.shape[0], 1))
    noiseLevel = signal.fftconvolve(signal, cfarWin, 'same')
    cfarThreshold = noiseLevel * alpha

    cfarThreshold[:refLength] = cfarThreshold[:refLength] * 3
    cfarThreshold[cfarThreshold.shape[0] -
                  refLength:] = cfarThreshold[cfarThreshold.shape[0] - refLength:] * 3

    peak = radar_detect(cfarThreshold, signal)

    del noiseLevel, cfarWin, signal

    return peak

def check(SignaIInfo, signal):
    """

        Parameters
        -----------------------
            SignalInfo : object
                Instance of class SignalData having meta-data of file and signal.
            signal : ndarray
                Numpy complex array of signal.

        Returns
        ------------------------------
            points : list
                List of starting index of aprs signal.

    """

    value = SignaIInfo.getvalues()

    fs = value[3]
    chunksize = int(fs)
    chunknumber = int((signal.shape[0]) // chunksize)

    points = []

    for i in range(chunknumber):
        start = i * chunksize
        end = start + chunksize

        hay = np.absolute(signal[start:end])
        point = cfar(hay)

        for peak in point:
            final_point = start + peak
            points.append(final_point)

    return points
<commit_msg>Added docstrings<commit_after>"""
    **Author :** *Jay Krishna*

    This module detects the presence of signal sent by beacon. Dynamic thresholding is applied based upon leading & lagging cells.

    Approach
    ----------------------------

    * Signal is broken down in chunks of one second each.
    * At each point of smaller signal threshold is calculated based upon average of lagging & leading reference cells after removing guard cells from both sides.
    * Point where APRS signal is suppossed to start is found & checked against peak induced by random noise.

    Reference
    ------------------------------

    `Barkat, Mourad & Varshney, P.K (1987). On adaptive cell-averaging CFAR (Constant False-Alarm Rate) radar signal detection. Final Technical Report, Jun. 1984 - Dec. 1986 Syracuse Univ., NY. Dept. of Electrical and Computer Engineering <https://goo.gl/15t64a>`_

"""

import numpy as np
from scipy import signal
import math

from Modules import SignalData

def merge(peak, signal):
    """

        Points detected very close to each other are merged and
        classified as same peak.

        Parameters
        -----------------------
            peak : list
                Points of presence of beacon.
            signal : ndarray
                Numpy array of signal.

        Returns
        -------------------------
            final_peak : list
                Points of presence of beacon after merging nearby peaks.

    """

    final_peak = []
    start = 0

    for end in range(1, peak.shape[0]):
        if(peak[end] - peak[end - 1] < 200):
            pass
        else:
            point = peak[start] + np.argmax(signal[peak[start]:peak[end - 1]])
            final_peak.append(point)
            start = end

    if(start == 0):
        point = peak[start] + np.argmax(signal[peak[start]:peak[end - 1]])
        final_peak.append(point)

    if(peak[start] > final_peak[-1]):
        point = peak[start] + np.argmax(signal[peak[start]:peak[end - 1]])
        final_peak.append(point)

    return final_peak

def radar_detect(radar, signal):
    """

        Based upon the values calculated start of APRS signal is detected while taking care of false results
        due to spikes induced by noise.

        Parameters
        -----------------------
            radar : ndarray
                Threshold values calculated at each point.
            signal : ndarray
                Numpy array of signal.

        Returns
        -------------------------
            peak : list
                Points of presence of beacon.

    """

    peak = []
    for i in range(signal.shape[0]):

        if(signal[i] > radar[i]):
            peak.append(i)

    peak = np.array(peak, dtype=int)

    if(peak.shape[0] > 1):
        peak = merge(peak, signal)

    return peak

def cfar(signal, refLength=1000, guardLength=100, p=0.01):
    """

        Calculates threshold value for each point using leading & lagging cells
        while discarding leading & lagging guard cells.

        Parameters
        -----------------------
            signal : ndarray
                Numpy complex array of signal.
            refLength : int
                Length of reference cells
            guardLength : int
                Length of guard cells
            p : float
                Accepted probability of false alarm.

        Returns
        -----------------------
            point : int
                Starting point of aprs signal if present.

    """

    N = 2 * refLength
    alpha = (math.pow(p, -1 / N) - 1) * N

    cfarWin = np.ones(((refLength + guardLength) * 2 + 1, 1))
    cfarWin[refLength + 1:refLength + 1 + 2 * guardLength] = 0
    cfarWin = cfarWin / sum(cfarWin)
    signal = np.reshape(signal, (signal.shape[0], 1))
    noiseLevel = signal.fftconvolve(signal, cfarWin, 'same')
    cfarThreshold = noiseLevel * alpha

    cfarThreshold[:refLength] = cfarThreshold[:refLength] * 3
    cfarThreshold[cfarThreshold.shape[0] -
                  refLength:] = cfarThreshold[cfarThreshold.shape[0] - refLength:] * 3

    peak = radar_detect(cfarThreshold, signal)

    del noiseLevel, cfarWin, signal

    return peak

def check(SignaIInfo, signal):
    """

        Breaks the signal into smaller chunks and send them
        sequentially for APRS signal detection.

        Parameters
        -----------------------
            SignalInfo : object
                Instance of class SignalData having meta-data of file and signal.
            signal : ndarray
                Numpy complex array of signal.

        Returns
        ------------------------------
            points : list
                List of starting index of aprs signal.

    """

    value = SignaIInfo.getvalues()

    fs = value[3]
    chunksize = int(fs)
    chunknumber = int((signal.shape[0]) // chunksize)

    points = []

    for i in range(chunknumber):
        start = i * chunksize
        end = start + chunksize

        hay = np.absolute(signal[start:end])
        point = cfar(hay)

        for peak in point:
            final_point = start + peak
            points.append(final_point)

    return points
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Node Classes.

* :any:`Node`: a simple tree node
* :any:`NodeMixin`: extends any python class to a tree node.
"""

from __future__ import print_function
from .iterators import PreOrderIter

class NodeMixin(object):

    separator = "/"

    u"""
    The :any:`NodeMixin` class extends any Python class to a tree node.

    The only tree relevant information is the `parent` attribute.
    If `None` the :any:`NodeMixin` is root node.
    If set to another node, the :any:`NodeMixin` becomes the child of it.

    >>> from anytree import Node, RenderTree
    >>> class MyBaseClass(object):
    ...     foo = 4
    >>> class MyClass(MyBaseClass, NodeMixin):  # Add Node feature
    ...     def __init__(self, name, length, width, parent=None):
    ...         super(MyClass, self).__init__()
    ...         self.name = name
    ...         self.length = length
    ...         self.width = width
    ...         self.parent = parent

    >>> my0 = MyClass('my0', 0, 0)
    >>> my1 = MyClass('my1', 1, 0, parent=my0)
    >>> my2 = MyClass('my2', 0, 2, parent=my0)

    >>> for pre, _, node in RenderTree(my0):
    ...     treestr = u"%s%s" % (pre, node.name)
    ...     print(treestr.ljust(8), node.length, node.width)
    my0      0 0
    ├── my1  1 0
    └── my2  0 2
    """

    @property
    def parent(self):
        u"""
        Parent Node.

        On set, the node is detached from any previous parent node and attached
        to the new node.

        >>> from anytree import Node, RenderTree
        >>> udo = Node("Udo")
        >>> marc = Node("Marc")
        >>> lian = Node("Lian", parent=marc)
        >>> print(RenderTree(udo))
        Node('/Udo')
        >>> print(RenderTree(marc))
        Node('/Marc')
        └── Node('/Marc/Lian')

        **Attach**

        >>> marc.parent = udo
        >>> print(RenderTree(udo))
        Node('/Udo')
        └── Node('/Udo/Marc')
            └── Node('/Udo/Marc/Lian')

        **Detach**

        To make a node to a root node, just set this attribute to `None`.

        >>> marc.is_root
        False
        >>> marc.parent = None
        >>> marc.is_root
        True
        """
        try:
            return self._parent
        except AttributeError:
            return None

    @parent.setter
    def parent(self, value):
        try:
            parent = self._parent
        except AttributeError:
            parent = None
        if value is None:
            # make this node to root node
            self.__detach(parent)
        elif parent is not value:
            # change parent node
            self.__check_loop(value)
            self.__detach(parent)
            self.__attach(value)
        else:
            # keep parent
            pass
        # apply
        self._parent = value

    def __check_loop(self, node):
        if node is self:
            msg = "Cannot set parent. %r cannot be parent of itself."
            raise LoopError(msg % self)
        if self in node.path:
            msg = "Cannot set parent. %r is parent of %r."
            raise LoopError(msg % (self, node))

    def __detach(self, parent):
        if parent:
            self._pre_detach(parent)
            parentchildren = parent._children
            assert self in parentchildren, "Tree internal data is corrupt."
            parentchildren.remove(self)
            self._post_detach(parent)

    def __attach(self, parent):
        self._pre_attach(parent)
        parentchildren = parent._children
        assert self not in parentchildren, "Tree internal data is corrupt."
        parentchildren.append(self)
        self._post_attach(parent)

    @property
    def _children(self):
        try:
            return self.__children
        except AttributeError:
            self.__children = []
            return self.__children

    @property
    def children(self):
        """
        All child nodes.

        >>> dan = Node("Dan")
        >>> jet = Node("Jet", parent=dan)
        >>> jan = Node("Jan", parent=dan)
        >>> joe = Node("Joe", parent=dan)
        >>> dan.children
        (Node('/Dan/Jet'), Node('/Dan/Jan'), Node('/Dan/Joe'))
        """
        return tuple(self._children)

    @property
    def path(self):
        """
        Path of this `Node`.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.path
        (Node('/Udo'),)
        >>> marc.path
        (Node('/Udo'), Node('/Udo/Marc'))
        >>> lian.path
        (Node('/Udo'), Node('/Udo/Marc'), Node('/Udo/Marc/Lian'))
        """
        return self._path

    @property
    def _path(self):
        path = []
        node = self
        while node:
            path.insert(0, node)
            node = node.parent
        return tuple(path)

    @property
    def anchestors(self):
        """
        All parent nodes and their parent nodes.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.anchestors
        ()
        >>> marc.anchestors
        (Node('/Udo'),)
        >>> lian.anchestors
        (Node('/Udo'), Node('/Udo/Marc'))
        """
        return self._path[:-1]

    @property
    def ancestors(self):
        """
        All parent nodes and their parent nodes.

        This is simply a fix for the `anchestors` typo.
        """
        return self.anchestors

    @property
    def descendants(self):
        """
        All child nodes and all their child nodes.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> loui = Node("Loui", parent=marc)
        >>> soe = Node("Soe", parent=lian)
        >>> udo.descendants
        (Node('/Udo/Marc'), Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Lian/Soe'), Node('/Udo/Marc/Loui'))
        >>> marc.descendants
        (Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Lian/Soe'), Node('/Udo/Marc/Loui'))
        >>> lian.descendants
        (Node('/Udo/Marc/Lian/Soe'),)
        """
        return tuple(PreOrderIter(self))[1:]

    @property
    def root(self):
        """
        Tree Root Node.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.root
        Node('/Udo')
        >>> marc.root
        Node('/Udo')
        >>> lian.root
        Node('/Udo')
        """
        if self.parent:
            return self._path[0]
        else:
            return self

    @property
    def siblings(self):
        """
        Tuple of nodes with the same parent.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> loui = Node("Loui", parent=marc)
        >>> lazy = Node("Lazy", parent=marc)
        >>> udo.siblings
        ()
        >>> marc.siblings
        ()
        >>> lian.siblings
        (Node('/Udo/Marc/Loui'), Node('/Udo/Marc/Lazy'))
        >>> loui.siblings
        (Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Lazy'))
        """
        parent = self.parent
        if parent is None:
            return tuple()
        else:
            return tuple([node for node in parent._children if node != self])

    @property
    def is_leaf(self):
        """
        `Node` has no childrean (External Node).

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.is_leaf
        False
        >>> marc.is_leaf
        False
        >>> lian.is_leaf
        True
        """
        return len(self._children) == 0

    @property
    def is_root(self):
        """
        `Node` is tree root.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.is_root
        True
        >>> marc.is_root
        False
        >>> lian.is_root
        False
        """
        return self.parent is None

    @property
    def height(self):
        """
        Number of edges on the longest path to a leaf `Node`.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.height
        2
        >>> marc.height
        1
        >>> lian.height
        0
        """
        if self._children:
            return max([child.height for child in self._children]) + 1
        else:
            return 0

    @property
    def depth(self):
        """
        Number of edges to the root `Node`.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.depth
        0
        >>> marc.depth
        1
        >>> lian.depth
        2
        """
        return len(self._path) - 1

    def _pre_detach(self, parent):
        """Method call before detaching from `parent`."""
        pass

    def _post_detach(self, parent):
        """Method call after detaching from `parent`."""
        pass

    def _pre_attach(self, parent):
        """Method call before attaching to `parent`."""
        pass

    def _post_attach(self, parent):
        """Method call after attaching to `parent`."""
        pass

class Node(NodeMixin, object):

    def __init__(self, name, parent=None, **kwargs):
        u"""
        A simple tree node with a `name` and any `kwargs`.

        >>> from anytree import Node, RenderTree
        >>> root = Node("root")
        >>> s0 = Node("sub0", parent=root)
        >>> s0b = Node("sub0B", parent=s0, foo=4, bar=109)
        >>> s0a = Node("sub0A", parent=s0)
        >>> s1 = Node("sub1", parent=root)
        >>> s1a = Node("sub1A", parent=s1)
        >>> s1b = Node("sub1B", parent=s1, bar=8)
        >>> s1c = Node("sub1C", parent=s1)
        >>> s1ca = Node("sub1Ca", parent=s1c)

        >>> print(RenderTree(root))
        Node('/root')
        ├── Node('/root/sub0')
        │   ├── Node('/root/sub0/sub0B', bar=109, foo=4)
        │   └── Node('/root/sub0/sub0A')
        └── Node('/root/sub1')
            ├── Node('/root/sub1/sub1A')
            ├── Node('/root/sub1/sub1B', bar=8)
            └── Node('/root/sub1/sub1C')
                └── Node('/root/sub1/sub1C/sub1Ca')
        """
        self.name = name
        self.parent = parent
        self.__dict__.update(kwargs)

    @property
    def name(self):
        """Name."""
        return self._name

    @name.setter
    def name(self, value):
        self._name = value

    def __repr__(self):
        classname = self.__class__.__name__
        args = ["%r" % self.separator.join([""] + [str(node.name) for node in self.path])]
        for key, value in filter(lambda item: not item[0].startswith("_"),
                                 sorted(self.__dict__.items(),
                                        key=lambda item: item[0])):
            args.append("%s=%r" % (key, value))
        return "%s(%s)" % (classname, ", ".join(args))

class LoopError(RuntimeError):

    """Tree contains infinite loop."""

    pass
<commit_msg>Add deprecation warning for anchestors.<commit_after># -*- coding: utf-8 -*-
"""
Node Classes.

* :any:`Node`: a simple tree node
* :any:`NodeMixin`: extends any python class to a tree node.
"""

from __future__ import print_function
from .iterators import PreOrderIter
import warnings

class NodeMixin(object):

    separator = "/"

    u"""
    The :any:`NodeMixin` class extends any Python class to a tree node.

    The only tree relevant information is the `parent` attribute.
    If `None` the :any:`NodeMixin` is root node.
    If set to another node, the :any:`NodeMixin` becomes the child of it.

    >>> from anytree import Node, RenderTree
    >>> class MyBaseClass(object):
    ...     foo = 4
    >>> class MyClass(MyBaseClass, NodeMixin):  # Add Node feature
    ...     def __init__(self, name, length, width, parent=None):
    ...         super(MyClass, self).__init__()
    ...         self.name = name
    ...         self.length = length
    ...         self.width = width
    ...         self.parent = parent

    >>> my0 = MyClass('my0', 0, 0)
    >>> my1 = MyClass('my1', 1, 0, parent=my0)
    >>> my2 = MyClass('my2', 0, 2, parent=my0)

    >>> for pre, _, node in RenderTree(my0):
    ...     treestr = u"%s%s" % (pre, node.name)
    ...     print(treestr.ljust(8), node.length, node.width)
    my0      0 0
    ├── my1  1 0
    └── my2  0 2
    """

    @property
    def parent(self):
        u"""
        Parent Node.

        On set, the node is detached from any previous parent node and attached
        to the new node.

        >>> from anytree import Node, RenderTree
        >>> udo = Node("Udo")
        >>> marc = Node("Marc")
        >>> lian = Node("Lian", parent=marc)
        >>> print(RenderTree(udo))
        Node('/Udo')
        >>> print(RenderTree(marc))
        Node('/Marc')
        └── Node('/Marc/Lian')

        **Attach**

        >>> marc.parent = udo
        >>> print(RenderTree(udo))
        Node('/Udo')
        └── Node('/Udo/Marc')
            └── Node('/Udo/Marc/Lian')

        **Detach**

        To make a node to a root node, just set this attribute to `None`.

        >>> marc.is_root
        False
        >>> marc.parent = None
        >>> marc.is_root
        True
        """
        try:
            return self._parent
        except AttributeError:
            return None

    @parent.setter
    def parent(self, value):
        try:
            parent = self._parent
        except AttributeError:
            parent = None
        if value is None:
            # make this node to root node
            self.__detach(parent)
        elif parent is not value:
            # change parent node
            self.__check_loop(value)
            self.__detach(parent)
            self.__attach(value)
        else:
            # keep parent
            pass
        # apply
        self._parent = value

    def __check_loop(self, node):
        if node is self:
            msg = "Cannot set parent. %r cannot be parent of itself."
            raise LoopError(msg % self)
        if self in node.path:
            msg = "Cannot set parent. %r is parent of %r."
            raise LoopError(msg % (self, node))

    def __detach(self, parent):
        if parent:
            self._pre_detach(parent)
            parentchildren = parent._children
            assert self in parentchildren, "Tree internal data is corrupt."
            parentchildren.remove(self)
            self._post_detach(parent)

    def __attach(self, parent):
        self._pre_attach(parent)
        parentchildren = parent._children
        assert self not in parentchildren, "Tree internal data is corrupt."
        parentchildren.append(self)
        self._post_attach(parent)

    @property
    def _children(self):
        try:
            return self.__children
        except AttributeError:
            self.__children = []
            return self.__children

    @property
    def children(self):
        """
        All child nodes.

        >>> dan = Node("Dan")
        >>> jet = Node("Jet", parent=dan)
        >>> jan = Node("Jan", parent=dan)
        >>> joe = Node("Joe", parent=dan)
        >>> dan.children
        (Node('/Dan/Jet'), Node('/Dan/Jan'), Node('/Dan/Joe'))
        """
        return tuple(self._children)

    @property
    def path(self):
        """
        Path of this `Node`.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.path
        (Node('/Udo'),)
        >>> marc.path
        (Node('/Udo'), Node('/Udo/Marc'))
        >>> lian.path
        (Node('/Udo'), Node('/Udo/Marc'), Node('/Udo/Marc/Lian'))
        """
        return self._path

    @property
    def _path(self):
        path = []
        node = self
        while node:
            path.insert(0, node)
            node = node.parent
        return tuple(path)

    @property
    def ancestors(self):
        """
        All parent nodes and their parent nodes.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.anchestors
        ()
        >>> marc.anchestors
        (Node('/Udo'),)
        >>> lian.anchestors
        (Node('/Udo'), Node('/Udo/Marc'))
        """
        return self._path[:-1]

    @property
    def anchestors(self):
        """
        All parent nodes and their parent nodes - see :any:`anchestors`.

        The attribute `anchestors` is just a typo of `ancestors`. Please use `ancestors`.
        This attribute will be removed in the 2.0.0 release.
        """
        warnings.warn(".anchestors was a typo and will be removed in version 2.0.0", DeprecationWarning)
        return self.ancestors

    @property
    def descendants(self):
        """
        All child nodes and all their child nodes.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> loui = Node("Loui", parent=marc)
        >>> soe = Node("Soe", parent=lian)
        >>> udo.descendants
        (Node('/Udo/Marc'), Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Lian/Soe'), Node('/Udo/Marc/Loui'))
        >>> marc.descendants
        (Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Lian/Soe'), Node('/Udo/Marc/Loui'))
        >>> lian.descendants
        (Node('/Udo/Marc/Lian/Soe'),)
        """
        return tuple(PreOrderIter(self))[1:]

    @property
    def root(self):
        """
        Tree Root Node.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.root
        Node('/Udo')
        >>> marc.root
        Node('/Udo')
        >>> lian.root
        Node('/Udo')
        """
        if self.parent:
            return self._path[0]
        else:
            return self

    @property
    def siblings(self):
        """
        Tuple of nodes with the same parent.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> loui = Node("Loui", parent=marc)
        >>> lazy = Node("Lazy", parent=marc)
        >>> udo.siblings
        ()
        >>> marc.siblings
        ()
        >>> lian.siblings
        (Node('/Udo/Marc/Loui'), Node('/Udo/Marc/Lazy'))
        >>> loui.siblings
        (Node('/Udo/Marc/Lian'), Node('/Udo/Marc/Lazy'))
        """
        parent = self.parent
        if parent is None:
            return tuple()
        else:
            return tuple([node for node in parent._children if node != self])

    @property
    def is_leaf(self):
        """
        `Node` has no childrean (External Node).

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.is_leaf
        False
        >>> marc.is_leaf
        False
        >>> lian.is_leaf
        True
        """
        return len(self._children) == 0

    @property
    def is_root(self):
        """
        `Node` is tree root.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.is_root
        True
        >>> marc.is_root
        False
        >>> lian.is_root
        False
        """
        return self.parent is None

    @property
    def height(self):
        """
        Number of edges on the longest path to a leaf `Node`.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.height
        2
        >>> marc.height
        1
        >>> lian.height
        0
        """
        if self._children:
            return max([child.height for child in self._children]) + 1
        else:
            return 0

    @property
    def depth(self):
        """
        Number of edges to the root `Node`.

        >>> udo = Node("Udo")
        >>> marc = Node("Marc", parent=udo)
        >>> lian = Node("Lian", parent=marc)
        >>> udo.depth
        0
        >>> marc.depth
        1
        >>> lian.depth
        2
        """
        return len(self._path) - 1

    def _pre_detach(self, parent):
        """Method call before detaching from `parent`."""
        pass

    def _post_detach(self, parent):
        """Method call after detaching from `parent`."""
        pass

    def _pre_attach(self, parent):
        """Method call before attaching to `parent`."""
        pass

    def _post_attach(self, parent):
        """Method call after attaching to `parent`."""
        pass

class Node(NodeMixin, object):

    def __init__(self, name, parent=None, **kwargs):
        u"""
        A simple tree node with a `name` and any `kwargs`.

        >>> from anytree import Node, RenderTree
        >>> root = Node("root")
        >>> s0 = Node("sub0", parent=root)
        >>> s0b = Node("sub0B", parent=s0, foo=4, bar=109)
        >>> s0a = Node("sub0A", parent=s0)
        >>> s1 = Node("sub1", parent=root)
        >>> s1a = Node("sub1A", parent=s1)
        >>> s1b = Node("sub1B", parent=s1, bar=8)
        >>> s1c = Node("sub1C", parent=s1)
        >>> s1ca = Node("sub1Ca", parent=s1c)

        >>> print(RenderTree(root))
        Node('/root')
        ├── Node('/root/sub0')
        │   ├── Node('/root/sub0/sub0B', bar=109, foo=4)
        │   └── Node('/root/sub0/sub0A')
        └── Node('/root/sub1')
            ├── Node('/root/sub1/sub1A')
            ├── Node('/root/sub1/sub1B', bar=8)
            └── Node('/root/sub1/sub1C')
                └── Node('/root/sub1/sub1C/sub1Ca')
        """
        self.name = name
        self.parent = parent
        self.__dict__.update(kwargs)

    @property
    def name(self):
        """Name."""
        return self._name

    @name.setter
    def name(self, value):
        self._name = value

    def __repr__(self):
        classname = self.__class__.__name__
        args = ["%r" % self.separator.join([""] + [str(node.name) for node in self.path])]
        for key, value in filter(lambda item: not item[0].startswith("_"),
                                 sorted(self.__dict__.items(),
                                        key=lambda item: item[0])):
            args.append("%s=%r" % (key, value))
        return "%s(%s)" % (classname, ", ".join(args))

class LoopError(RuntimeError):

    """Tree contains infinite loop."""

    pass
<|endoftext|>


<commit_before>import numpy.random as rand
from os.path import exists
from os import makedirs, listdir

class Card:
    '''
    Base class for all cards
    These are values that are assumed to be correct to work correctly
    cardName = str
    cardTier = int
    cardTheme = Theme
    '''

    def __init__(self, cardName, cardTier, cardTheme):
        self.cardName = cardName
        self.cardTier = cardTier
        self.cardTheme = cardTheme

class Theme:
    '''
    themeName = str
    themeCardNames = tuple (pool of theme-specific card names)
    themeTiers = tuple (pool of theme-specific card tiers)
    themeTierChances = tuple (chances for the corresponding theme tier)
    ~(should be same length as themeTiers)
    '''
    def __init__(self, themeName):
        self.themeName = themeName
        self.themeCardNames = self.readCardNames()
        self.themeTiers = self.readTierNames()
        self.themeTierChances = self.readTierChances()

    def readCardNames(self):
        with open('themes/{0}/cnames.txt'.format(self.themeName), 'r') as cardNames:
            cardNameList = [x.strip() for x in cardNames.readlines()]
        return tuple(cardNameList)

    def readTierNames(self):
        with open('themes/{0}/tnames.txt'.format(self.themeName), 'r') as tierNames:
            tierNameList = [x.strip() for x in tierNames.readlines()]
        return tuple(tierNameList)

    def readTierChances(self):
        with open('themes/{0}/tchances.txt'.format(self.themeName), 'r') as tierChances:
            tierChanceList = [float(x) for x in tierChances.readlines()]
        return tuple(tierChanceList)

    def pickTier(self):
        tier = rand.choice(self.themeTiers, 1, p=self.themeTierChances)[0]
        return tier

    def pickName(self):
        name = rand.choice(self.themeCardNames)
        return name

    def makeCard(self):
        return Card(self.pickName(), self.pickTier(), self.themeName)

    def __bool__(self):
        return True

class Pack:
    '''
    Base class for all packs
    These are values that are assumed to be correct to work correctly
    packPrice = int (0->X)
    cardsInPack = int (1->X)
    cardTierChances = None/tuple (lowest rarity -> highest rarity)(add up to 1)
    ~corresponds to the basic theme, set to 0 for no chance of that tier
    themeCardChance = None/int (0->1)
    packTheme = None/Theme (this is an extra theme in addition to the default basic theme)
    '''
    def __init__(self, packName):
        self.packName = packName
        self.packPrice, self.cardAmt, self.themeCardChance, self.maxThemed = self.readConfigs()
        self.basicChances = self.readBasicChances()
        self.basicTheme, self.extraTheme = self.readThemes()

    def openPack(self):
        cardList = []
        themeCt = 0
        for x in range(self.cardAmt):
            if rand.random() <= self.themeCardChance and themeCt < self.maxThemed:
                cardList.append(Theme(self.extraTheme).makeCard())
                themeCt += 1
            else:
                cardList.append(Theme(self.basicTheme).makeCard())
        return tuple(cardList)

    def readConfigs(self):
        #[packPrice, packCardAmt, themeCardChance, maxThemeCards]
        configs = []
        with open('packs/{0}/pconfigs.txt'.format(self.packName), 'r') as configFile:
            for config in configFile:
                config = config.strip()
                try:
                    configs.append(int(config))
                except ValueError:
                    configs.append(float(config))
        return configs

    def readBasicChances(self):
        bclist = []
        with open('packs/{0}/basicChances.txt'.format(self.packName), 'r') as bcFile:
            for bc in bcFile.readlines():
                bclist.append(float(bc.strip()))
        return tuple(bclist)

    def readThemes(self):
        with open('packs/{0}/themes.txt'.format(self.packName), 'r') as themeFile:
            themeList = [theme.strip() for theme in themeFile]
        return tuple(themeList)

def inpConf(inpstr):
    conf = False
    while not conf:
        reply = input(inpstr)
        confinp= input('Confirm "{0}" Y/N: '.format(reply))[0].lower()
        if confinp == 'n':
            conf = False
        elif confinp == 'y':
            return str(reply)
        else:
            print('Invalid input: {0} . Please try again'.format(reply))

def createTheme():
    cardNames = []
    tierNames = []
    cardName = ''
    tierName = ''
    tierChances = []
    tierChance = 0
    breakLoop = False
    usedChance = 0
    themeName = inpConf('Input Theme name: ')
    fileDir = 'themes/'+themeName+'/'
    while not breakLoop:
        cardName = inpConf('Input card name (-- to exit): ')
        if cardName == '--':
            breakLoop = True
        else:
            cardNames.append(cardName)
    breakLoop = False
    while not breakLoop:
        tierName = inpConf('Input Tier name (-- to exit): ')
        if tierName == '--':
            breakLoop = True
        else:
            tierNames.append(tierName)
    breakLoop = False
    while not breakLoop:
        tierChances = []
        for tierName in tierNames:
            try:
                tierChance = float(inpConf('Rarity for tier: {0} . {1:.3f} remaining chance. '.format(tierName, 100-usedChance*100)))/100
                usedChance += tierChance
                tierChances.append(tierChance)
                if usedChance > 1:
                    print('Cannot use over 100 chance!')
                    break
            except:
                print('Invalid value: {0}'.format(x))
                break
        if len(tierNames) == len(tierChances):
            breakLoop = True
    if not exists(fileDir):
        makedirs(fileDir)
    with open(fileDir+'cnames.txt', 'w') as cNameFile:
        for idx, cName in enumerate(cardNames):
            if idx < len(cardNames)-1:
                cNameFile.write(str(cName)+'\n')
            else:
                cNameFile.write(str(cName))
    with open(fileDir+'tnames.txt', 'w') as tNameFile:
        for idx, tName in enumerate(tierNames):
            if idx < len(tierNames)-1:
                tNameFile.write(str(tName)+'\n')
            else:
                tNameFile.write(str(tName))
    with open(fileDir+'tchances.txt', 'w') as tChanceFile:
        for idx, tChance in enumerate(tierChances):
            if idx < len(tierChances)-1:
                tChanceFile.write(str(tChance)+'\n')
            else:
                tChanceFile.write(str(tChance))

def editTheme():
    isTheme = False
    themeList = listdir('themes')
    themeStr = ', '.join(themeList)[0:]
    usedChance = 0
    validChoice = False
    while not isTheme:
        themeName = inpConf('{0}\nInput the exact name of the theme you are editing: '.format(themeStr))
        if themeName in themeList:
            isTheme = True
        else:
            print('Invalid theme:', themeName)
    fileDir = 'themes/'+themeName+'/'
    with open(fileDir+'cnames.txt', 'r') as cNameFile:
        cardNames =  [name.strip() for name in cNameFile.readlines()]
    cardNamesL = [name.lower() for name in cardNames]
    while True:
        cardNamesL = [name.lower() for name in cardNames]
        cardNameStr = ', '.join(cardNames)
        validChoice = False
        cardChoice = inpConf('(E)diting, (A)dding, or (D)eleting a card name (-- to quit): ').lower()
        if cardChoice[0] == 'e':
            print(cardNameStr)
            nameChoice = inpConf('Which name are you editing: ')
            validChoice = True
        elif cardChoice[0] == 'a':
            nameChoice = inpConf('Which name are you adding: ')
            validChoice = True
        elif cardChoice[0] == 'd':
            print(cardNameStr)
            nameChoice = inpConf('Which name are you deleting: ')
            validChoice = True
        elif cardChoice == '--':
            validChoice = False
            break
        else:
            validChoice = False
        if validChoice:
            if cardChoice == 'a':
                if not nameChoice.lower() in cardNamesL:
                    cardNames.append(nameChoice)
                else:
                    print('Card name already exists!')
            elif nameChoice.lower() in cardNamesL:
                nameIndex = cardNamesL.index(nameChoice.lower())
                if cardChoice == 'e':
                    cardNames[nameIndex] = inpConf('Input card name: ')
                elif cardChoice == 'd':
                    del cardNames[nameIndex]
                else:
                    print('editTheme error', cardNames, nameChoice)
            else:
                print('Name',nameChoice,'not found.')
        else:
            print('Invalid input:', cardChoice)

        with open(fileDir+'cnames.txt', 'w') as cNameFile:
            for idx, cName in enumerate(cardNames):
                if idx < len(cardNames)-1:
                    cNameFile.write(cName+'\n')
                else:
                    cNameFile.write(cName)

def createPack():
    baseTheme = 'Basic'
    baseThemeTiers = Theme(baseTheme).themeTiers
    baseThemeChances = []
    themeCardChance = 0
    maxThemeCards = 0
    usedChance = 0
    packCardAmt = 0
    packPrice = 0
    breakLoop = False
    packName = inpConf('Input Pack name: ')
    packPrice = int(inpConf('Input Pack price: '))
    packCardAmt = int(inpConf('Input amout of cards in this Pack: '))
    fileDir = 'packs/'+packName+'/'
    while not breakLoop:
        for tierName in baseThemeTiers:
            tierChance = float(inpConf('Rarity for {0} tier: {1} . {2:.2f} remaining chance. '.format(baseTheme, tierName, 100-usedChance*100)))/100
            usedChance += tierChance
            baseThemeChances.append(tierChance)
            if usedChance > 1:
                print('Cannot use over 100 chance!')
                break
        if len(baseThemeTiers) == len(baseThemeChances):
            breakLoop = True
    extraTheme = inpConf('Name of extra theme (-- for none): ')
    if extraTheme == '--':
        extraTheme == None
    else:
        themeCardChance = int(inpConf('Input theme card chance: '))/100
        maxThemeCards = int(inpConf('Input max theme cards per pack: '))

    if not exists(fileDir):
        makedirs(fileDir)
    with open(fileDir+'themes.txt', 'w') as themeNames:
        themeNames.write(baseTheme+'\n')
        themeNames.write(extraTheme)
    with open(fileDir+'basicChances.txt', 'w') as basicChanceFile:
        for idx, bChance in enumerate(baseThemeChances):
            if len(baseThemeChances)-1 != idx:
                basicChanceFile.write(str(bChance)+'\n')
            else:
                basicChanceFile.write(str(bChance))
    with open(fileDir+'pconfigs.txt', 'w') as pConfigFile:
        pconfigs = [packPrice, packCardAmt, themeCardChance, maxThemeCards]
        for idx, config in enumerate(pconfigs):
            if len(pconfigs)-1 != idx:
                pConfigFile.write(str(config)+'\n')
            else:
                pConfigFile.write(str(config))

def readThemes():
    themes = {themeName : Theme(themeName) for themeName in listdir('themes')}
    return themes

def readPacks():
    packs = {packName : Pack(packName) for packName in listdir('packs')}
    return packs

themes = readThemes()

packs = readPacks()
<commit_msg>[!!] Creating my own RNG<commit_after>import time
from numpy import random as rand
time.clock()
from os.path import exists
from os import makedirs, listdir

class Card:
    '''
    Base class for all cards
    These are values that are assumed to be correct to work correctly
    cardName = str
    cardTier = int
    cardTheme = Theme
    '''

    def __init__(self, cardName, cardTier, cardTheme):
        self.cardName = cardName
        self.cardTier = cardTier
        self.cardTheme = cardTheme

class Theme:
    '''
    themeName = str
    themeCardNames = tuple (pool of theme-specific card names)
    themeTiers = tuple (pool of theme-specific card tiers)
    themeTierChances = tuple (chances for the corresponding theme tier)
    ~(should be same length as themeTiers)
    '''
    def __init__(self, themeName):
        self.themeName = themeName
        self.themeCardNames = self.readCardNames()
        self.themeTiers = self.readTierNames()
        self.themeTierChances = self.readTierChances()

    def readCardNames(self):
        with open('themes/{0}/cnames.txt'.format(self.themeName), 'r') as cardNames:
            cardNameList = [x.strip() for x in cardNames.readlines()]
        return tuple(cardNameList)

    def readTierNames(self):
        with open('themes/{0}/tnames.txt'.format(self.themeName), 'r') as tierNames:
            tierNameList = [x.strip() for x in tierNames.readlines()]
        return tuple(tierNameList)

    def readTierChances(self):
        with open('themes/{0}/tchances.txt'.format(self.themeName), 'r') as tierChances:
            tierChanceList = [float(x) for x in tierChances.readlines()]
        return tuple(tierChanceList)

    def pickTier(self):
        tier = rand.choice(self.themeTiers, 1, p=self.themeTierChances)[0]
        return tier

    def pickName(self):
        name = rand.choice(self.themeCardNames)
        return name

    def makeCard(self):
        return Card(self.pickName(), self.pickTier(), self.themeName)

    def __bool__(self):
        return True

class Pack:
    '''
    Base class for all packs
    These are values that are assumed to be correct to work correctly
    packPrice = int (0->X)
    cardsInPack = int (1->X)
    cardTierChances = None/tuple (lowest rarity -> highest rarity)(add up to 1)
    ~corresponds to the basic theme, set to 0 for no chance of that tier
    themeCardChance = None/int (0->1)
    packTheme = None/Theme (this is an extra theme in addition to the default basic theme)
    '''
    def __init__(self, packName):
        self.packName = packName
        self.packPrice, self.cardAmt, self.themeCardChance, self.maxThemed = self.readConfigs()
        self.basicChances = self.readBasicChances()
        self.basicTheme, self.extraTheme = self.readThemes()

    def openPack(self):
        cardList = []
        themeCt = 0
        for x in range(self.cardAmt):
            if rand.random() <= self.themeCardChance and themeCt < self.maxThemed:
                cardList.append(Theme(self.extraTheme).makeCard())
                themeCt += 1
            else:
                cardList.append(Theme(self.basicTheme).makeCard())
        return tuple(cardList)

    def readConfigs(self):
        #[packPrice, packCardAmt, themeCardChance, maxThemeCards]
        configs = []
        with open('packs/{0}/pconfigs.txt'.format(self.packName), 'r') as configFile:
            for config in configFile:
                config = config.strip()
                try:
                    configs.append(int(config))
                except ValueError:
                    configs.append(float(config))
        return configs

    def readBasicChances(self):
        bclist = []
        with open('packs/{0}/basicChances.txt'.format(self.packName), 'r') as bcFile:
            for bc in bcFile.readlines():
                bclist.append(float(bc.strip()))
        return tuple(bclist)

    def readThemes(self):
        with open('packs/{0}/themes.txt'.format(self.packName), 'r') as themeFile:
            themeList = [theme.strip() for theme in themeFile]
        return tuple(themeList)

def inpConf(inpstr):
    conf = False
    while not conf:
        reply = input(inpstr)
        confinp= input('Confirm "{0}" Y/N: '.format(reply))[0].lower()
        if confinp == 'n':
            conf = False
        elif confinp == 'y':
            return str(reply)
        else:
            print('Invalid input: {0} . Please try again'.format(reply))

def createTheme():
    cardNames = []
    tierNames = []
    cardName = ''
    tierName = ''
    tierChances = []
    tierChance = 0
    breakLoop = False
    usedChance = 0
    themeName = inpConf('Input Theme name: ')
    fileDir = 'themes/'+themeName+'/'
    while not breakLoop:
        cardName = inpConf('Input card name (-- to exit): ')
        if cardName == '--':
            breakLoop = True
        else:
            cardNames.append(cardName)
    breakLoop = False
    while not breakLoop:
        tierName = inpConf('Input Tier name (-- to exit): ')
        if tierName == '--':
            breakLoop = True
        else:
            tierNames.append(tierName)
    breakLoop = False
    while not breakLoop:
        tierChances = []
        for tierName in tierNames:
            try:
                tierChance = float(inpConf('Rarity for tier: {0} . {1:.3f} remaining chance. '.format(tierName, 100-usedChance*100)))/100
                usedChance += tierChance
                tierChances.append(tierChance)
                if usedChance > 1:
                    print('Cannot use over 100 chance!')
                    break
            except:
                print('Invalid value: {0}'.format(x))
                break
        if len(tierNames) == len(tierChances):
            breakLoop = True
    if not exists(fileDir):
        makedirs(fileDir)
    with open(fileDir+'cnames.txt', 'w') as cNameFile:
        for idx, cName in enumerate(cardNames):
            if idx < len(cardNames)-1:
                cNameFile.write(str(cName)+'\n')
            else:
                cNameFile.write(str(cName))
    with open(fileDir+'tnames.txt', 'w') as tNameFile:
        for idx, tName in enumerate(tierNames):
            if idx < len(tierNames)-1:
                tNameFile.write(str(tName)+'\n')
            else:
                tNameFile.write(str(tName))
    with open(fileDir+'tchances.txt', 'w') as tChanceFile:
        for idx, tChance in enumerate(tierChances):
            if idx < len(tierChances)-1:
                tChanceFile.write(str(tChance)+'\n')
            else:
                tChanceFile.write(str(tChance))

def editTheme():
    isTheme = False
    themeList = listdir('themes')
    themeStr = ', '.join(themeList)[0:]
    usedChance = 0
    validChoice = False
    while not isTheme:
        themeName = inpConf('{0}\nInput the exact name of the theme you are editing: '.format(themeStr))
        if themeName in themeList:
            isTheme = True
        else:
            print('Invalid theme:', themeName)
    fileDir = 'themes/'+themeName+'/'
    with open(fileDir+'cnames.txt', 'r') as cNameFile:
        cardNames =  [name.strip() for name in cNameFile.readlines()]
    cardNamesL = [name.lower() for name in cardNames]
    while True:
        cardNamesL = [name.lower() for name in cardNames]
        cardNameStr = ', '.join(cardNames)
        validChoice = False
        cardChoice = inpConf('(E)diting, (A)dding, or (D)eleting a card name (-- to quit): ').lower()
        if cardChoice[0] == 'e':
            print(cardNameStr)
            nameChoice = inpConf('Which name are you editing: ')
            validChoice = True
        elif cardChoice[0] == 'a':
            nameChoice = inpConf('Which name are you adding: ')
            validChoice = True
        elif cardChoice[0] == 'd':
            print(cardNameStr)
            nameChoice = inpConf('Which name are you deleting: ')
            validChoice = True
        elif cardChoice == '--':
            validChoice = False
            break
        else:
            validChoice = False
        if validChoice:
            if cardChoice == 'a':
                if not nameChoice.lower() in cardNamesL:
                    cardNames.append(nameChoice)
                else:
                    print('Card name already exists!')
            elif nameChoice.lower() in cardNamesL:
                nameIndex = cardNamesL.index(nameChoice.lower())
                if cardChoice == 'e':
                    cardNames[nameIndex] = inpConf('Input card name: ')
                elif cardChoice == 'd':
                    del cardNames[nameIndex]
                else:
                    print('editTheme error', cardNames, nameChoice)
            else:
                print('Name',nameChoice,'not found.')
        else:
            print('Invalid input:', cardChoice)

        with open(fileDir+'cnames.txt', 'w') as cNameFile:
            for idx, cName in enumerate(cardNames):
                if idx < len(cardNames)-1:
                    cNameFile.write(cName+'\n')
                else:
                    cNameFile.write(cName)

def createPack():
    baseTheme = 'Basic'
    baseThemeTiers = Theme(baseTheme).themeTiers
    baseThemeChances = []
    themeCardChance = 0
    maxThemeCards = 0
    usedChance = 0
    packCardAmt = 0
    packPrice = 0
    breakLoop = False
    packName = inpConf('Input Pack name: ')
    packPrice = int(inpConf('Input Pack price: '))
    packCardAmt = int(inpConf('Input amout of cards in this Pack: '))
    fileDir = 'packs/'+packName+'/'
    while not breakLoop:
        for tierName in baseThemeTiers:
            tierChance = float(inpConf('Rarity for {0} tier: {1} . {2:.2f} remaining chance. '.format(baseTheme, tierName, 100-usedChance*100)))/100
            usedChance += tierChance
            baseThemeChances.append(tierChance)
            if usedChance > 1:
                print('Cannot use over 100 chance!')
                break
        if len(baseThemeTiers) == len(baseThemeChances):
            breakLoop = True
    extraTheme = inpConf('Name of extra theme (-- for none): ')
    if extraTheme == '--':
        extraTheme == None
    else:
        themeCardChance = int(inpConf('Input theme card chance: '))/100
        maxThemeCards = int(inpConf('Input max theme cards per pack: '))

    if not exists(fileDir):
        makedirs(fileDir)
    with open(fileDir+'themes.txt', 'w') as themeNames:
        themeNames.write(baseTheme+'\n')
        themeNames.write(extraTheme)
    with open(fileDir+'basicChances.txt', 'w') as basicChanceFile:
        for idx, bChance in enumerate(baseThemeChances):
            if len(baseThemeChances)-1 != idx:
                basicChanceFile.write(str(bChance)+'\n')
            else:
                basicChanceFile.write(str(bChance))
    with open(fileDir+'pconfigs.txt', 'w') as pConfigFile:
        pconfigs = [packPrice, packCardAmt, themeCardChance, maxThemeCards]
        for idx, config in enumerate(pconfigs):
            if len(pconfigs)-1 != idx:
                pConfigFile.write(str(config)+'\n')
            else:
                pConfigFile.write(str(config))

def readThemes():
    themes = {themeName : Theme(themeName) for themeName in listdir('themes')}
    return themes

def readPacks():
    packs = {packName : Pack(packName) for packName in listdir('packs')}
    return packs

themes = readThemes()

packs = readPacks()

seedTime = time.clock()
seedTimeMod = time.clock()*16

testInputList = ['50%','30%','10%','5%','3%','1.5%','.5%']
testWeightList = [.5,.3,.1,.05,.03,.015,.005]

results = {x:0 for x in testInputList}
<|endoftext|>


<commit_before>from django.contrib import admin
from models import Repo, UserRights, GroupRights

class RepoAdmin(admin.ModelAdmin):
  list_display = ['name', 'vcs']
  list_filter = ['vcs']
  search_fields = ['name']

  def get_readonly_fields(self, request, obj=None):
    if obj:
      return ['vcs']
    else:
      return []

class UserRightsAdmin(admin.ModelAdmin):
  list_display = ['repo', 'user']
  search_fields = ['repo__name', 'user__username']

class GroupRightsAdmin(admin.ModelAdmin):
  list_display = ['repo', 'group']
  search_fields = ['repo__name', 'group__name']

admin.site.register(Repo, RepoAdmin)
admin.site.register(UserRights, UserRightsAdmin)
admin.site.register(GroupRights, GroupRightsAdmin)
<commit_msg>improve admin interface<commit_after>from django.contrib import admin
from models import Repo, UserRights, GroupRights

class RepoAdmin(admin.ModelAdmin):
  list_display = ['__unicode__', 'vcs']
  list_filter = ['vcs']
  search_fields = ['name']

  def get_readonly_fields(self, request, obj=None):
    if obj:
      return ['vcs']
    else:
      return []

class UserRightsAdmin(admin.ModelAdmin):
  list_display = ['__unicode__', 'repo', 'user', 'rights']
  search_fields = ['repo__name', 'user__username']

class GroupRightsAdmin(admin.ModelAdmin):
  list_display = ['__unicode__', 'repo', 'group', 'rights']
  search_fields = ['repo__name', 'group__name']

admin.site.register(Repo, RepoAdmin)
admin.site.register(UserRights, UserRightsAdmin)
admin.site.register(GroupRights, GroupRightsAdmin)
<|endoftext|>


<commit_before>import molecule
import UCONGA_analyse
from os import path
import numpy

def align_to(mol_to_align, ref_mol, allow_inversion, center_id):
    '''
    Aligns one molecule to another
    '''
    ref_coords = numpy.array([i.coords for i in ref_mol.atoms
                              if i.get_id() in center_id])
    to_align_center = numpy.array([i.coords for i in mol_to_align.atoms
                                   if i.get_id() in center_id])
    mol_to_align.translate(-1*to_align_center.mean(axis=0))
    coords_to_align = numpy.array([i.coords for i in mol_to_align.atoms
                                   if i.get_id() in center_id])
    aligner = UCONGA_analyse.align(coords_to_align, ref_coords, allow_inversion)
    aligned_coords = mol_to_align.coord_matrix().dot(aligner)
    new_mol = mol_to_align.copy()
    for each_atom, each_new_coords in zip(new_mol.atoms, aligned_coords):
        each_atom.coords = each_new_coords
    return new_mol

if __name__ == '__main__':
    import argparse
    description = '''
    UCONGA: Universal CONformer Generation and Analysis
    ----------------------------------------------------
    A tool to align different conformers as a utility for UCONGA_analyse
    ----------------------------------------------------
    Nathaniel Gunby, Dr. Deborah Crittenden, Dr. Sarah Masters
    Department of Chemistry
    University of Canterbury
    Christchurch
    New Zealand
    '''
    i_help = 'Treat enantiomeric conformers as identical? (Default = No)'
    f_help = ('File format to output results in: cml, xyz, gms (GAMESS input ' +
              'geometry), nw (nwchem input geometry), gauss (Gaussian input geometry)')
    c_help = 'Atom ids to use for alignment (default = all heavy atoms)'
    parser = argparse.ArgumentParser(description=description,
                                     formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('-i', '--allow_inversion', help=i_help, action='store_true')
    parser.add_argument('-f', '--output_format', help=f_help, default='cml')
    parser.add_argument('-c', '--center_id', help=c_help, action='append', type=int)
    parser.add_argument('ref_file', help='cml file containing the reference ' +
                        'conformer that all others will be aligned to')
    parser.add_argument('input_files', help='cml files containing the other ' +
                        'conformers to be algigned', nargs='+')
    args = parser.parse_args()
    input_names = args.input_files
    if len(input_names) == 1 and '*' in input_names[0]:
        # If the shell is dumb (powershell/cmd.exe), glob input files ourselves
        from glob import glob
        input_names = glob(input_names[0])
    mols = [molecule.from_cml(i) for i in input_names]
    ref_mol = molecule.from_cml(args.ref_file)
    ref_num_atoms = len(ref_mol.atoms)
    if args.center_id:
        center_ids = [i - 1 for i in args.center_id]
    else:
        center_ids = [i.get_id() for i in ref_mol.atoms if i.num > 1]
    for each_id in center_ids:
        if not (0 <= each_id < ref_num_atoms):
            raise ValueError('The atom id to align molecules at must be a valid ' +
                             'atom id for the molecule, i.e. an integer between ' +
                             'between 1 and %d inclusive.' % ref_num_atoms)
    for each_mol in mols:
        if len(each_mol.atoms) != ref_num_atoms:
            raise ValueError('Not all molecules to be aligned have the same ' +
                             'number of atoms. Please retry with conformers ' +
                             'of only one molecule')
    ref_center = numpy.array([i.coords for i in ref_mol.atoms
                              if i.get_id() in center_ids])
    ref_mol.translate(-1*ref_center.mean(axis=0))
    input_names = [path.split(i) for i in input_names]
    out_names = [path.join(i[0], 'Aligned_{0}.{1}'.format(i[1], args.output_format))
                 for i in input_names]
    for each_mol, each_name in zip(mols, out_names):
        aligned_mol = align_to(each_mol, ref_mol, args.allow_inversion, center_ids)
        with open(each_name, 'w') as each_file:
            if args.output_format == 'cml':
                each_file.write(aligned_mol.to_cml())
            else:
                each_file.write(aligned_mol.to_xyz(args.output_format))
    ref_dirname, ref_fname = path.split(args.ref_file)
    with open(path.join(ref_dirname, 'Aligned_{0}.{1}'.format(ref_fname, args.output_format)), 'w') as f:
        if args.output_format == 'cml':
            f.write(ref_mol.to_cml())
        else:
            f.write(ref_mol.to_xyz(args.output_format))
<commit_msg>Standardise docstrings in UCONGA_align.py<commit_after>import molecule
import UCONGA_analyse
from os import path
import numpy

def align_to(mol_to_align, ref_mol, allow_inversion, center_id):
    '''
    Aligns one molecule to another
    Accepts:
        A molecule object to move
        A molecule object to hold fixed
        Whether inversion is allowed (alternatively, whether enantiomers should
                                      be treated as identical or not)
        A list of atom ids to base the alignment on
    '''
    ref_coords = numpy.array([i.coords for i in ref_mol.atoms
                              if i.get_id() in center_id])
    to_align_center = numpy.array([i.coords for i in mol_to_align.atoms
                                   if i.get_id() in center_id])
    mol_to_align.translate(-1*to_align_center.mean(axis=0))
    coords_to_align = numpy.array([i.coords for i in mol_to_align.atoms
                                   if i.get_id() in center_id])
    aligner = UCONGA_analyse.align(coords_to_align, ref_coords, allow_inversion)
    aligned_coords = mol_to_align.coord_matrix().dot(aligner)
    new_mol = mol_to_align.copy()
    for each_atom, each_new_coords in zip(new_mol.atoms, aligned_coords):
        each_atom.coords = each_new_coords
    return new_mol

if __name__ == '__main__':
    import argparse
    description = '''
    UCONGA: Universal CONformer Generation and Analysis
    ----------------------------------------------------
    A tool to align different conformers as a utility for UCONGA_analyse
    ----------------------------------------------------
    Nathaniel Gunby, Dr. Deborah Crittenden, Dr. Sarah Masters
    Department of Chemistry
    University of Canterbury
    Christchurch
    New Zealand
    '''
    i_help = 'Treat enantiomeric conformers as identical? (Default = No)'
    f_help = ('File format to output results in: cml, xyz, gms (GAMESS input ' +
              'geometry), nw (nwchem input geometry), gauss (Gaussian input geometry)')
    c_help = 'Atom ids to use for alignment (default = all heavy atoms)'
    parser = argparse.ArgumentParser(description=description,
                                     formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('-i', '--allow_inversion', help=i_help, action='store_true')
    parser.add_argument('-f', '--output_format', help=f_help, default='cml')
    parser.add_argument('-c', '--center_id', help=c_help, action='append', type=int)
    parser.add_argument('ref_file', help='cml file containing the reference ' +
                        'conformer that all others will be aligned to')
    parser.add_argument('input_files', help='cml files containing the other ' +
                        'conformers to be algigned', nargs='+')
    args = parser.parse_args()
    input_names = args.input_files
    if len(input_names) == 1 and '*' in input_names[0]:
        # If the shell is dumb (powershell/cmd.exe), glob input files ourselves
        from glob import glob
        input_names = glob(input_names[0])
    mols = [molecule.from_cml(i) for i in input_names]
    ref_mol = molecule.from_cml(args.ref_file)
    ref_num_atoms = len(ref_mol.atoms)
    if args.center_id:
        center_ids = [i - 1 for i in args.center_id]
    else:
        center_ids = [i.get_id() for i in ref_mol.atoms if i.num > 1]
    for each_id in center_ids:
        if not (0 <= each_id < ref_num_atoms):
            raise ValueError('The atom id to align molecules at must be a valid ' +
                             'atom id for the molecule, i.e. an integer between ' +
                             'between 1 and %d inclusive.' % ref_num_atoms)
    for each_mol in mols:
        if len(each_mol.atoms) != ref_num_atoms:
            raise ValueError('Not all molecules to be aligned have the same ' +
                             'number of atoms. Please retry with conformers ' +
                             'of only one molecule')
    ref_center = numpy.array([i.coords for i in ref_mol.atoms
                              if i.get_id() in center_ids])
    ref_mol.translate(-1*ref_center.mean(axis=0))
    input_names = [path.split(i) for i in input_names]
    out_names = [path.join(i[0], 'Aligned_{0}.{1}'.format(i[1], args.output_format))
                 for i in input_names]
    for each_mol, each_name in zip(mols, out_names):
        aligned_mol = align_to(each_mol, ref_mol, args.allow_inversion, center_ids)
        with open(each_name, 'w') as each_file:
            if args.output_format == 'cml':
                each_file.write(aligned_mol.to_cml())
            else:
                each_file.write(aligned_mol.to_xyz(args.output_format))
    ref_dirname, ref_fname = path.split(args.ref_file)
    with open(path.join(ref_dirname, 'Aligned_{0}.{1}'.format(ref_fname, args.output_format)), 'w') as f:
        if args.output_format == 'cml':
            f.write(ref_mol.to_cml())
        else:
            f.write(ref_mol.to_xyz(args.output_format))
<|endoftext|>


<commit_before>__version__ = "0.0.1"
<commit_msg>Bumped the version number<commit_after>__version__ = "0.0.2"
<|endoftext|>