import random
import matplotlib.patches as patches
import matplotlib.pyplot as plt
from helpers import *
class SmokeMachine:
    def __init__(self, axes, position, direction, intensity=0.5, initial_speed=4):
        self.position = position
        self.direction = direction
        self.intensity = intensity
        self.axes = axes
        self.initial_speed = initial_speed
        self.smokes = []
        self.plotted = 0
        self.variableParam = ""

        if(direction==W or direction==E):
            self.variableParam = "y"
        elif( direction==N or direction==S):
            self.variableParam = "x"
        else:
            pass

    def generateSmokes(self,num):
        count=0
        while count<num:
            pos=[self.position[0],self.position[1]]
            if(self.variableParam=="x"):
                pos[0] = random.randint(0,150)
            else:
                pos[1] = random.randint(0,100)
            smoke = Smoke(position=pos,radius=1,intensity=1,color="#848884",movement_direction=reverseDirection(self.direction),speed=self.initial_speed)
            # smoke.plotSmoke(self.axes)
            self.smokes.append(smoke)
            count += 1
        # print(f"{num} new smokes, total: {len(self.smokes)}")

    def plotSmokes(self,num):

        i=0

        while i<num and self.plotted<len(self.smokes):
            # print(f"c:{self.plotted}, i:{i}")
            self.smokes[self.plotted].plotSmoke(self.axes)
            self.plotted += 1
            i += 1

    def moveSmokes(self):
        # if(self.smokes)
        print("move smoke")
        for i in range(self.plotted):
            if(self.smokes[i] != None):
                self.smokes[i].move()

class Smoke:
    def __init__(self, position, radius, intensity, color, movement_direction, speed):
        self.position = position
        self.radius = radius
        self.intensity = intensity
        self.color = color
        self.direction = movement_direction
        self.circle = None
        self.speed = speed

    def move(self,deviate=True):

        print(f"going-->{self.direction} {self.position}")

        self.position = movement(self.position,self.direction,self.speed)
        self.circle.center = ((self.position[0],self.position[1]))
        if(self.position[0]>150 or self.position[0]<0 or self.position[1]>100 or self.position[1]<0):
            self.direction = reverseDirection(self.direction)
            print("limittt",self.direction)
        # self.direction = randomizeDirection(self.direction)

        # increase size and decrease intensity with time and movement

        if(self.intensity>0.01):
            self.intensity -= 0.01
            self.circle.set_alpha(self.intensity)
            # self.removeSmoke()
        self.radius += 0.1
        self.circle.set_radius(self.radius)

    def plotSmoke(self,axes):
        self.circle = plt.Circle(self.position,self.radius,color=self.color,alpha=self.intensity,linestyle=":")

        axes.add_patch(self.circle)

    def removeSmoke(self):
        self.circle.set_visible(False)
        self.circle.remove()


from tkinter import *
from tkinter import ttk
import math
import sys

myApp = Tk()
myApp.title(" Program ")
myApp.geometry("1000x1200")

tasktabs=ttk.Notebook(myApp)

NewWorkLab=Label(myApp,text="Name: ")
NewWorkLab.grid(row=0,column=2, sticky="W", padx=5,pady=5)

NewWorkEntry=Entry(myApp)
NewWorkEntry.grid(row=0,column=3,sticky="W", padx=5,pady=5)

def AddNewWork():

    TabName=ttk.Frame(tasktabs)
    tasktabs.add(TabName,text=NewWorkEntry.get())

    NewTree= ttk.Treeview(TabName,height=40)
    NewTree['show'] = 'headings'

    NewTree["columns"]=("1","2","3","4","5","6")

    NewTree.column("1", width=20)
    NewTree.column("2", width=320)
    NewTree.column("3", width=40)
    NewTree.column("4", width=80)
    NewTree.column("5", width=80)
    NewTree.column("6", width=80)

    NewTree.heading("1", text="ID")
    NewTree.heading("2", text="Activities")
    NewTree.heading("3", text="Unit")
    NewTree.heading("4", text="Quantity")
    NewTree.heading("5", text="Unit Cost")
    NewTree.heading("6", text="Total Cost")

    NewTree.grid(row=2,column=0,pady=10,padx=0)

AddWorkButton=Button(myApp,text=' Add ', command=AddNewWork)
AddWorkButton.grid(row=0,column=4, sticky="W", padx=5, pady=5)

tasktabs.grid(row=1,column=0,columnspan=4,padx=5)

myApp.mainloop()


def print_even(my_list):
    """
    Given a list of integers, print only the even numbers
    """
    for i in my_list:
        if i%2 == 0:
            print(i)
    return

# Test case
print_even([1, 2, 3, 4, 6, 9,10])

def square(my_object):
    """
    Use assert or try/except to check if the input can be squared
    """
    try:
        my_object = int(my_object)
        print(my_object**2)
    except:
        print("Cannot square since not a number")
    return

# # Test cases
square(3)
square('hello')

def madlib(adjective_1, adjective_2, adjective_3, noun_1):
    """
    This definition should take in 4 strings, format them into the string below, and print the final string.
    The (adjective_1) man entered the (adjective_2) building to visit a very (adjective_3) man. "Sit down, Mr. Smith, can I interest you in any good (noun_1)?
    """
    final_string = "The " + adjective_1 + " man entered the " + adjective_2 + " building to visit a very " + adjective_3 + " man. \"Sit down, Mr. Smith, can I interest you in any good " + noun_1 + "?"
    return final_string

# # Test case
print(madlib('tall', 'nice', 'tall', 'cat food'))  # should print:  The tall man entered the nice building to visit a very tall man. "Sit down, Mr. Smith, can I interest you in any good cat food?

def stop_at_x(my_list, x):
    """
    This definition should sequentially print every item in my_list until the item x is reached
    """
    for indec in my_list:
        if indec == x:
            break
        print(indec)
    return indec

# # Test cases
stop_at_x([1, 2, 3, 9, 1, 2, 3], 9)  # should print 1, and then 2, then 3, then stop before 9 is printed

# use the range(10) function, instead of: i=0, i<10, i++
for i in range(10):
    print(i)

# range(start, stop, step)
for i in range(20, 30, 2):
    print(i)

# # while loops
# i = 0
# while i < 10:
#     print(i)
#     i = i + 1  # not i++
#

# skip to the next iteration of a loop with CONTINUE
for i in range(100):
    if i%2 == 0:
        continue
    print(i)

#
# exit a loop entierly with BREAK
for i in range(5):
    for j in range(1000000000000000000000000000000000000):
        if j > 3:
            break
        print(i,j)

# looping over arrays is easy
x = [1, 2, 3, 4, 5]
length = len(x)
print(length)
for i in range(length):
    print(i)

# use enumerate to loop over an iterable and count each loop
x = ['one', 'two', 'three', 'four']
for i, word in enumerate(x):
    print(i, word)

print(x[:])
print(x[1:-1])
print(x[1:-2])

# use zip() to loop over two iterables, it will always stop at the shorter of the two
x = [2, 3, 4, 5, 6, 7, 8, 9]
print(x[1:4])
print(x[3:5])
print(x[3:])
print(x[:3])
y = ['even', 'odd', 'even']

for a, b in zip(x, y):
    print(a, b)

# Definitions: we will discuss generators, *args, and **kwargs after exam 2
def dbl(x):
    return x*2

print(dbl(30))

b = [10.0, 'girls & boys', (2+0j), 3.14159, 21, 1000, 1877383, 'love', 'hate']
print(b[1:-1])
# to be done yet
# ASSERT is used mostly for testing
# x = 0
# assert x == 1, 'x is not 1'
#

# # this is similar to
# if x != 1:
#     raise AssertionError('x is not 1')

# try/except work similar to if/else statements
x = 'yes'
try:
    x = int(x)
except:
    print('cannot convert to int')
    exit(1)


# Features:
# 0. highest tile
# 1. number of sets of horizontally adjacent tiles
# 2. number of sets of vertically adjacent tiles
# 3. highest tile of horizontally adjacent tiles
# 4. highest tile of vertically adjacent tiles
# 5. number of blanks in top left quadrant
# 6. number of blanks in top right quadrant
# 7. number of blanks in btm left quadrant
# 8. number of blanks in btm right quadrant

def getFeatures(b):
    feats = [max(b)] + [0]*8

    # horizontal then vertical
    strips = [b[i:i+4] for i in range(0, 16, 4)], [[b[i] for i in range(j, 16, 4)] for j in range(4)]

    # feats 1 to 4
    for i in range(2):
        for j in range(4):
            strip = strips[i][j]

            # if the whole strip is blank do nothing
            if sum(strip) == 0:
                continue

            # remove blanks
            strip = [tile for tile in strip if tile != 0]

            # get adjacent repeated tile stats
            for k in range(len(strip) - 1):
                if strip[k] == strip[k+1]:
                    strip[k+1] = 0
                    feats[1 + i] += 1
                    feats[3 + i] = max(feats[3 + i], strip[k])

    # feats 5 to 8
    pos = [0,2,8,10]
    for i in range(4):
        mark = pos[i]
        feats[5 + i] = (b[mark:mark+2] + b[mark+4:mark+6]).count(0)

    return feats


import collections
import csv
import io
import itertools
import os
import warnings
from typing import cast

import pytest
import pytest_cases.filters
# pytest_cases.fixture used as helper functions. Must be imported otherwise, the
# function is not discovered during test collection.
from test_gaggle.case_ankicard import *  # pylint: disable=wildcard-import,unused-wildcard-import # pyright: ignore [reportMissingImports]
from .conftest import new_header_gaggle_format, new_field_names_remove_reserved, falsy_values_hashable  # pylint: disable=relative-beyond-top-level
import unittest.mock

from gaggle import gaggle
from gaggle import exceptions

_CASES = 'test_gaggle.case_ankicard'

TSV_FILE_ENCODING = gaggle._ANKI_EXPORT_ENCODING
TSV_FILE_DIALECT = gaggle._ANKI_EXPORT_CONTENT_DIALECT
EXCLUSIVE_OPEN_PARAMS = gaggle.EXCLUSIVE_OPEN_PARAMS
READ_PARAMS = gaggle.READ_PARAMS
WRITE_PARAMS: gaggle.OpenOptions = {
    'mode': 'w',
    'encoding': TSV_FILE_ENCODING,
    'newline': ''
}

@pytest_cases.fixture
@pytest_cases.parametrize('property_name', [
    'guid',
    'note_type',
    'deck_name',
    'tags',
])
def reserved_names_as_property_name(property_name):
  return property_name

@pytest_cases.fixture
@pytest_cases.parametrize(
    'field_name', [falsy_values_hashable, 'This field name does not exist'])
def nonexistent_field_names(field_name):
  return field_name

@pytest_cases.fixture
@pytest_cases.parametrize_with_cases(
    'anki_card_components',
    cases=_CASES,
    has_tag=['WellFormed', 'AnkiCardComponents'])
def generate_field_dict_well_formed(anki_card_components):
  generated_field_dict = gaggle._generate_field_dict(
      anki_card_components.field_names, anki_card_components.fields,
      anki_card_components.reserved_names,
      set(anki_card_components.reserved_names.values()))
  components = anki_card_components
  return generated_field_dict, components

@pytest_cases.fixture
@pytest_cases.parametrize_with_cases(
    'anki_card_components_constructor',
    cases=_CASES,
    has_tag=['AnkiCardComponentsConstructor'])
def generate_unique_field_names_constructor(anki_card_components_constructor,):

  def generate_unique_field_names_helper(field_names=None):
    anki_card_components = anki_card_components_constructor(
        field_names=field_names)
    return list(
        gaggle._generate_unique_field_names(
            anki_card_components.field_names, anki_card_components.fields,
            anki_card_components.reserved_names,
            set(anki_card_components.reserved_names.values()))
    ), anki_card_components.expected_field_names

  return generate_unique_field_names_helper

class TestAnkiCardInit:

  @pytest.mark.filterwarnings('ignore')
  @pytest_cases.parametrize_with_cases(
      'fields',
      cases=_CASES,
      has_tag=['Fields'],
      prefix='fields',
  )
  @pytest_cases.parametrize_with_cases(
      'field_names',
      cases=_CASES,
      filter=pytest_cases.filters.has_tag('FieldNames')
      & ~pytest_cases.filters.has_tag('UsageBeforeAssignment'),
      prefix='field_names',
  )
  @pytest_cases.parametrize_with_cases(
      'has_html',
      cases=_CASES,
      has_tag=['HasHtml', 'Well-Formed'],
      prefix='has_html',
  )
  @pytest_cases.parametrize_with_cases(
      'tags_idx',
      cases=_CASES,
      has_tag=['TagsIdx'],
      prefix='tags_idx',
  )
  @pytest_cases.parametrize_with_cases(
      'note_type_idx',
      cases=_CASES,
      has_tag=['NoteTypeIdx'],
      prefix='note_type_idx',
  )
  @pytest_cases.parametrize_with_cases(
      'deck_idx',
      cases=_CASES,
      has_tag=['GuidIdx'],
      prefix='guid_idx',
  )
  @pytest_cases.parametrize_with_cases(
      'guid_idx',
      cases=_CASES,
      has_tag=['DeckIdx'],
      prefix='deck_idx',
  )
  def test_anki_card_init_valid_arguments(
      self,
      fields,
      field_names,
      has_html,
      tags_idx,
      note_type_idx,
      deck_idx,
      guid_idx,
  ):
    card = gaggle.AnkiCard(fields, field_names, has_html, tags_idx,
                           note_type_idx, deck_idx, guid_idx)
    assert card

@pytest_cases.parametrize_with_cases(
    'anki_card', cases=_CASES, has_tag=['FullySpecified', 'AnkiCard'])
def test_reserved_names_specified_returns_value(
    anki_card,
    reserved_names_as_property_name,
):
  assert hasattr(anki_card, reserved_names_as_property_name)

@pytest_cases.parametrize_with_cases(
    'anki_card', cases=_CASES, has_tag=['Minimum', 'AnkiCard'])
def test_reserved_names_not_specified_raises_key_error(
    anki_card,
    reserved_names_as_property_name,
):
  with pytest.raises(KeyError):
    hasattr(anki_card, reserved_names_as_property_name)

@pytest.mark.filterwarnings('ignore')
@pytest_cases.parametrize_with_cases(
    'anki_card_components',
    cases=_CASES,
    has_tag=['WellFormed', 'AnkiCardComponents'])
def test_get_field_existing_field(anki_card_components,):
  anki_card = anki_card_components.new_anki_card()
  for expected_field_name, expected_field_value in zip(
      anki_card_components.expected_field_names,
      anki_card_components.fields,
      strict=True,
  ):
    assert anki_card.get_field(expected_field_name) == expected_field_value

@pytest.mark.filterwarnings('ignore')
@pytest_cases.parametrize_with_cases(
    'anki_card', cases=_CASES, has_tag=['WellFormed', 'AnkiCard'])
def test_get_field_non_existing_field(anki_card, nonexistent_field_names):
  with pytest.raises(KeyError):
    anki_card.get_field(nonexistent_field_names)

@pytest.mark.filterwarnings('ignore')
@pytest_cases.parametrize_with_cases(
    'anki_card_components',
    cases=_CASES,
    has_tag=['WellFormed', 'AnkiCardComponents'])
def test_as_str_list_content_matches(anki_card_components):
  anki_card = anki_card_components.new_anki_card()
  test_set = collections.Counter(anki_card.as_str_list())
  expected_set = collections.Counter(anki_card_components.expected_fields)
  assert test_set == expected_set

@pytest.mark.filterwarnings('ignore')
@pytest_cases.parametrize_with_cases(
    'anki_card_components',
    cases=_CASES,
    has_tag=['WellFormed', 'AnkiCardComponents'])
def test_as_str_list_order_matches(anki_card_components):
  anki_card = anki_card_components.new_anki_card()
  expected_fields = anki_card_components.expected_fields
  assert anki_card.as_str_list() == expected_fields

def format_as_tsv(fields):
  """Formatting expected of a TSV line.

  Values delimited by tab (i.e. '\t'), finished with a os dependent line
  seperator.
  """
  expected_output = '\t'.join(fields)
  return f'{expected_output}{os.linesep}'

class TestWriteAsTsv:

  @pytest.mark.filterwarnings('ignore')
  @pytest_cases.parametrize_with_cases(
      'anki_card_components',
      cases=_CASES,
      has_tag=['WellFormed', 'AnkiCardComponents'])
  def test_write_as_tsv_formatted_correctly_one_line(
      self,
      anki_card_components,
  ):
    anki_card = anki_card_components.new_anki_card()
    expected_write_output = format_as_tsv(anki_card_components.expected_fields)
    mock_open = unittest.mock.mock_open()
    with unittest.mock.patch('builtins.open', mock_open):
      with open('myfile.txt', **WRITE_PARAMS) as f:
        w = csv.writer(f, dialect=TSV_FILE_DIALECT)
        anki_card.write_as_tsv(w)
      mock_open().write.assert_called_once_with(expected_write_output)

  @pytest.mark.filterwarnings('ignore')
  @pytest_cases.parametrize_with_cases(
      'anki_card_components_one',
      cases=_CASES,
      has_tag=['WellFormed', 'AnkiCardComponents'])
  @pytest_cases.parametrize_with_cases(
      'anki_card_components_two',
      cases=_CASES,
      has_tag=['WellFormed', 'AnkiCardComponents'])
  def test_write_as_tsv_formatted_correctly_multiple_lines(
      self,
      mocker,
      anki_card_components_one,
      anki_card_components_two,
  ):
    anki_card_one = anki_card_components_one.new_anki_card()
    anki_card_two = anki_card_components_two.new_anki_card()
    expected_write_output_one = format_as_tsv(
        anki_card_components_one.expected_fields)
    expected_write_output_two = format_as_tsv(
        anki_card_components_two.expected_fields)
    mock_open = mocker.patch('builtins.open', mocker.mock_open())
    with open('myfile.txt', **WRITE_PARAMS) as f:
      w = csv.writer(f, dialect=TSV_FILE_DIALECT)
      anki_card_one.write_as_tsv(w)
      anki_card_two.write_as_tsv(w)
    expected_write_calls = [
        mocker.call(expected_write_output_one),
        mocker.call(expected_write_output_two)
    ]
    mock_open().write.assert_has_calls(expected_write_calls)

  @pytest.mark.filterwarnings('ignore')
  @pytest_cases.parametrize_with_cases(
      'anki_card', cases=_CASES, has_tag=['WellFormed', 'AnkiCard'])
  def test_write_as_tsv_no_write_permission_raises_unsupported_operation(
      self,
      mocker,
      anki_card,
  ):
    mock_open = mocker.patch('builtins.open', mocker.mock_open())
    mock_open().write.side_effect = io.UnsupportedOperation
    with open('myfile.txt', **READ_PARAMS) as f:
      w = csv.writer(f, dialect=TSV_FILE_DIALECT)
      with pytest.raises(io.UnsupportedOperation):
        anki_card.write_as_tsv(w)
    mock_open()

def has_html_expected_bool(has_html_as_string):
  if has_html_as_string == 'true':
    return True
  elif has_html_as_string == 'false':
    return False
  else:
    raise ValueError

class TestHasHtml:

  @pytest_cases.parametrize_with_cases(
      'has_html',
      cases=_CASES,
      has_tag=['HasHtml', 'Well-Formed'],
      prefix='has_html')
  def test_parse_anki_header_bool_valid_input(self, has_html):
    expected_bool = has_html_expected_bool(has_html)
    assert gaggle._parse_anki_header_bool(has_html) == expected_bool

  @pytest_cases.parametrize_with_cases(
      'has_html',
      cases=_CASES,
      has_tag=['HasHtml', 'Malformed'],
      prefix='has_html')
  def test_parse_anki_header_bool_invalid_value_raises_value_error(
      self, has_html):
    with pytest.raises(ValueError):
      gaggle._parse_anki_header_bool(has_html)

class TestGenerateFieldDict:

  @pytest.mark.filterwarnings('ignore')
  def test_generate_field_dict_returns_ordered_dict(
      self,
      generate_field_dict_well_formed,
  ):
    field_dict, anki_card_components = generate_field_dict_well_formed
    del anki_card_components  # Unused
    assert isinstance(field_dict, collections.OrderedDict)

  @pytest.mark.filterwarnings('ignore')
  def test_generate_field_dict_preserves_order_fields(
      self,
      generate_field_dict_well_formed,
  ):
    field_dict, anki_card_components = generate_field_dict_well_formed
    expected_values = anki_card_components.expected_fields
    for test_value, expected_value in zip(field_dict.values(), expected_values):
      assert test_value == expected_value

  @pytest.mark.filterwarnings('ignore')
  def test_generate_field_dict_preserves_order_field_names(
      self,
      generate_field_dict_well_formed,
  ):
    field_dict, anki_card_components = generate_field_dict_well_formed
    expected_names = anki_card_components.expected_field_names
    for test_value, expected_name in zip(field_dict.keys(), expected_names):
      assert test_value == expected_name

def get_code_line(filename, lineno):
  with open(filename, encoding='utf-8') as f:
    return next(itertools.islice(f, lineno - 1, lineno))

class TestGenerateUniqueFieldNames:

  @pytest.mark.slow
  @pytest.mark.io
  @pytest_cases.parametrize_with_cases(
      'anki_card_components',
      cases=_CASES,
      has_tag=['ModifiedFullySpecified', 'AnkiCardComponents'])
  def test_generate_unique_field_names_warning_points_to_anki_card_initialisation(
      self, anki_card_components):
    with warnings.catch_warnings(record=True) as records:
      anki_card_components.new_anki_card()
    for record in records:
      assert 'AnkiCard(' in get_code_line(record.filename, record.lineno)

  @pytest.mark.filterwarnings('ignore')
  @pytest_cases.parametrize_with_cases(
      'field_names',
      cases=_CASES,
      filter=~pytest_cases.filters.has_tag('UsageBeforeAssignment'),
      prefix='field_names')
  def test_generate_unique_field_names_length_matches_fields_length(
      self,
      field_names,
      generate_unique_field_names_constructor,
  ):
    """This test also guarantees that generated field_names are unique."""
    test_field_names, expected_field_names = generate_unique_field_names_constructor(
        field_names)
    assert len(test_field_names) == len(expected_field_names)

  @pytest.mark.filterwarnings('ignore')
  @pytest_cases.parametrize_with_cases(
      'field_names',
      cases=_CASES,
      filter=~pytest_cases.filters.has_tag('UsageBeforeAssignment'),
      prefix='field_names',
  )
  def test_generate_unique_field_names_replaces_field_names(
      self,
      field_names,
      generate_unique_field_names_constructor,
  ):
    test_field_names, expected_field_names = generate_unique_field_names_constructor(
        field_names)
    assert test_field_names == expected_field_names

  @pytest_cases.parametrize_with_cases(
      'field_names',
      cases=_CASES,
      has_tag=['Well-Formed'],
      prefix='field_names')
  def test_generate_unique_field_names_well_formed_no_warnings(
      self,
      field_names,
      generate_unique_field_names_constructor,
  ):
    with warnings.catch_warnings():
      warnings.simplefilter('error')
      generate_unique_field_names_constructor(field_names)

  @pytest_cases.parametrize_with_cases(
      'field_names', cases=_CASES, has_tag=['Surplus'], prefix='field_names')
  def test_generate_unique_field_names_longer_field_names_raises_leftover_argument_warning(
      self,
      field_names,
      generate_unique_field_names_constructor,
  ):
    with pytest.warns(exceptions.LeftoverArgumentWarning):
      generate_unique_field_names_constructor(field_names=field_names)

  @pytest_cases.parametrize_with_cases(
      'field_names', cases=_CASES, has_tag=['Surplus'], prefix='field_names')
  def test_generate_unique_field_names_longer_field_names_multiple_extra_raises_one_warning(
      self,
      field_names,
      generate_unique_field_names_constructor,
  ):
    with pytest.warns(exceptions.LeftoverArgumentWarning) as record:
      generate_unique_field_names_constructor(field_names=field_names)
    assert len(record) == 1

  @pytest_cases.parametrize_with_cases(
      'field_names', cases=_CASES, has_tag=['Surplus'], prefix='field_names')
  def test_generate_unique_field_names_longer_field_names_multiple_extra_returns_all_extra(
      self,
      field_names,
      generate_unique_field_names_constructor,
  ):
    with pytest.warns(exceptions.LeftoverArgumentWarning) as record:
      test_field_names, expected_field_names = generate_unique_field_names_constructor(
          field_names)
      del test_field_names  # unused
    surplus_starting_index = len(expected_field_names)
    warning = record[0].message
    warning = cast(exceptions.LeftoverArgumentWarning, warning)
    actual_extra_field_names = warning.leftovers
    expected_extra_field_names = ' '.join(field_names[surplus_starting_index:])
    assert actual_extra_field_names == expected_extra_field_names

  @pytest_cases.parametrize_with_cases(
      'field_names',
      cases=_CASES,
      has_tag=['HeaderNameMismatch'],
      prefix='field_names')
  def test_generate_unique_field_names_mismatched_reserved_name_raises_header_field_name_mismatch_warning(
      self,
      field_names,
      generate_unique_field_names_constructor,
  ):
    with pytest.warns(exceptions.HeaderFieldNameMismatchWarning):
      generate_unique_field_names_constructor(field_names=field_names)

  @pytest_cases.parametrize_with_cases(
      'field_names',
      cases=_CASES,
      has_tag=['HeaderNameMismatch'],
      prefix='field_names')
  def test_generate_unique_field_names_multiple_mismatched_reserved_name_raises_multiple_header_field_name_mismatch_warning(
      self,
      field_names,
      generate_unique_field_names_constructor,
  ):
    with pytest.warns(exceptions.HeaderFieldNameMismatchWarning) as record:
      test_field_names, expected_field_names = generate_unique_field_names_constructor(
          field_names)
      del test_field_names  # unused
    # Right hand side is the number of field_names which were altered
    number_mismatches = len(set(expected_field_names) - set(field_names))
    assert len(record) == number_mismatches

  @pytest_cases.parametrize_with_cases(
      'field_names',
      cases=_CASES,
      has_tag=['DuplicateReservedFieldNames'],
      prefix='field_names')
  def test_generate_unique_field_names_duplicate_reserved_name_raises_duplicate_warning(
      self,
      field_names,
      generate_unique_field_names_constructor,
  ):
    with pytest.warns(exceptions.DuplicateWarning):
      generate_unique_field_names_constructor(field_names=field_names)

  @pytest_cases.parametrize_with_cases(
      'field_names',
      cases=_CASES,
      has_tag=['DuplicateReservedFieldNames'],
      prefix='field_names')
  def test_generate_unique_field_names_multiple_duplicate_reserved_name_raises_multiple_duplicate_warning(
      self,
      field_names,
      generate_unique_field_names_constructor,
  ):
    with pytest.warns(exceptions.DuplicateWarning) as record:
      test_field_names, expected_field_names = generate_unique_field_names_constructor(
          field_names)
      del test_field_names  # unused
    number_duplicate = len(expected_field_names) - len(set(field_names))
    assert len(record) == number_duplicate

  @pytest_cases.parametrize_with_cases(
      'field_names',
      cases=_CASES,
      has_tag=['UsageAfterAssignment'],
      prefix='field_names')
  def test_generate_unique_field_names_duplicate_default_name_after_assignment_raises_duplicate_warning(
      self,
      field_names,
      generate_unique_field_names_constructor,
  ):
    with pytest.warns(exceptions.DuplicateWarning):
      generate_unique_field_names_constructor(field_names=field_names)

  @pytest_cases.parametrize_with_cases(
      'field_names',
      cases=_CASES,
      has_tag=['UsageAfterAssignment'],
      prefix='field_names')
  def test_generate_unique_field_names_multiple_duplicate_default_name_after_assignment_raises_multiple_duplicate_warning(
      self,
      field_names,
      generate_unique_field_names_constructor,
  ):
    with pytest.warns(exceptions.DuplicateWarning) as record:
      test_field_names, expected_field_names = generate_unique_field_names_constructor(
          field_names)
      del test_field_names  # unused
    number_duplicate = len(expected_field_names) - len(set(field_names))
    assert len(record) == number_duplicate

  @pytest_cases.parametrize_with_cases(
      'field_names',
      cases=_CASES,
      has_tag=['UsageBeforeAssignment'],
      prefix='field_names')
  def test_generate_unique_field_names_duplicate_default_name_before_assignment_raises_value_error(
      self,
      field_names,
      generate_unique_field_names_constructor,
  ):
    with pytest.raises(ValueError):
      generate_unique_field_names_constructor(field_names=field_names)

  @pytest_cases.parametrize_with_cases(
      'field_names',
      cases=_CASES,
      has_tag=['UsageBeforeAssignment'],
      prefix='field_names')
  def test_generate_unique_field_names_multiple_duplicate_default_name_before_assignment_raises_single_value_error(
      self,
      field_names,
      generate_unique_field_names_constructor,
  ):
    with pytest.raises(ValueError):
      generate_unique_field_names_constructor(field_names=field_names)

@pytest.mark.slow
@pytest.mark.io
@pytest_cases.parametrize('field_names',
                          [None, new_field_names_remove_reserved])
@pytest_cases.parametrize('header', [None, new_header_gaggle_format])
def test_create_cards_from_tsv_well_formed_arguments(
    case_anki_export_file_no_header_well_formed_content, field_names, header):
  # TODO: This is a minimal test suite for create_cards_from_tsv
  #   See: https://github.com/ImplyingICheck/Gaggle/issues/32
  test_file_path = case_anki_export_file_no_header_well_formed_content
  with open(test_file_path, **READ_PARAMS) as f:
    deck = gaggle.create_cards_from_tsv(
        f, field_names=field_names, header=header)
  assert deck


import re

fname = '2015-06.txt'

def execute(instruction):
    for x in range(int(instruction[1]), int(instruction[3]) + 1):
        for y in range(int(instruction[2]), int(instruction[4]) + 1):
            if instruction[0] == 'turn on':
                grid1[x][y] = 1
                grid2[x][y] += 1
            if instruction[0] == 'turn off':
                grid1[x][y] = 0
                grid2[x][y] -= 1
                if grid2[x][y] < 0:
                    grid2[x][y] = 0
            if instruction[0] == 'toggle':
                if grid1[x][y] == 0:
                    grid1[x][y] = 1
                else:
                    grid1[x][y] = 0
                grid2[x][y] += 2

pattern = re.compile(r'(turn on|turn off|toggle) (\d+),(\d+) through (\d+),(\d+)')
instructions = pattern.sub(r'\1,\2,\3,\4,\5', open(fname).read()).splitlines()
instructions = [x.split(',') for x in instructions]
grid1 = [[0 for _ in range(1000)] for _ in range(1000)]
grid2 = [[0 for _ in range(1000)] for _ in range(1000)]
for instruction in instructions:
    execute(instruction)

print()
print("event 2015 day 6 part 1 answer: ", sum([sum(i) for i in grid1]))

print()
print("event 2015 day 6 part 2 answer: ", sum([sum(i) for i in grid2]))


#########################################################################
## Project: ICON Vote Stagnancy Investigation                          ##
## Date: July 2020                                                     ##
## Author: Tono / Sung Wook Chung (Transcranial Solutions)             ##
## transcranial.solutions@gmail.com                                    ##
##                                                                     ##
## This programme is distributed in the hope that it will be useful,   ##
## but WITHOUT ANY WARRANTY, without even the implied warranty of      ##
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       ##
## GNU General Public License for more details.                        ##
#########################################################################

# Need to run it in sequence as it needs data from previous script (04_aggregate_data.py)

import pandas as pd
# import numpy as np
import matplotlib.pyplot as plt
# import matplotlib.ticker as ticker
# import scipy.stats as sp
import seaborn as sns
import os

desired_width = 320
pd.set_option('display.width', desired_width)
pd.set_option('display.max_columns', 10)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Plotting ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
#### plotting
# number of voters by voter age

# better to average it
total_voting_days_plot = agg_df.groupby(['delegator', 'total_voting_months']).agg('mean').reset_index()
total = float(len(total_voting_days_plot))  # one person per row (this is for % in the figure)
total_voting_days_plot = total_voting_days_plot.groupby('total_voting_months')['delegator'].count().reset_index()

# barplot
sns.set(style="darkgrid")
plt.style.use("dark_background")
ax = plt.subplots(figsize=(8, 6))
ax = sns.barplot(x="total_voting_months",
                 y="delegator",
                 data=total_voting_days_plot,
                 edgecolor="white", palette=sns.cubehelix_palette(len(total_voting_days_plot), start=.5, rot=-.75)) #, color="b")
ax.grid(False)
ax.set_xlabel('Voter Age (months)', fontsize=12, labelpad=10, weight='bold')
ax.set_ylabel('Wallets', fontsize=12, labelpad=10, weight='bold')

ax.set_title('Number of Wallets by Voting Duration', fontsize=14, weight='bold')
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)

all_height = []
for p in ax.patches:
    height = p.get_height()
    ax.text(p.get_x() + p.get_width() / 2.,
            height + 30,
            '{0: .0%}'.format(height / total),
            ha="center")
    all_height.append(height)

ax.set(ylim=(0, max(all_height) + max(all_height)*0.1))

plt.tight_layout()

# saving
plt.savefig(os.path.join(resultsPath, '01_wallet_count_by_voter_age.png'))


import json

out=open('aaa.json',"w")
dataDict = {'company': 123123121, 'country': "1231231231", 'product': str(123123123)}

json_str = json.dumps(dataDict, ensure_ascii=False, indent=2)
out.write(json_str)
out.flush()
out.close()
print(1)
def aaa():
    global aa
    aa="asd"

def bbb():
    print(aa)

aaa()
bbb()
print(aa)


from os import listdir
from os.path import isfile, join
from pandas import DataFrame

basedir = 'C:/Users/BA388496/Documents/Learning/Technologies/Datasets/aclImdb'

# getting all file under the given path
def get_files(path):
    files = [(path + f) for f in listdir(path) if isfile(join(path, f))]
    return files

# getting train data
def get_train_data():
    train_neg = basedir + '/train/neg/'
    train_pos = basedir + '/train/pos/'

    train_data = []
    for file in get_files(train_neg):
        f = open(file,encoding='utf8')
        train_data.append([f.readlines()[0],0])

    for file in get_files(train_pos):
        f = open(file,encoding='utf8')
        train_data.append([f.readlines()[0],1])

    return DataFrame(train_data, columns=['review','class'])

# getting test data
def get_test_data():
    test_neg = basedir + '/test/neg/'
    test_pos = basedir + '/test/pos/'

    test_data = []
    for file in get_files(test_neg):
        f = open(file,encoding='utf8')
        test_data.append([f.readlines()[0],0])

    for file in get_files(test_pos):
        f = open(file,encoding='utf8')
        test_data.append([f.readlines()[0],1])

    return DataFrame(test_data, columns=['review','class'])


#!/usr/bin/env python3
"""
Objects

author: jy
"""

import copy
import pandas as pd
import networkx as nx
from fatez.lib import GRN_Basic
import fatez.tool.JSON as JSON

class CRE(GRN_Basic):
	"""
	Class to store information of a cis-regulatory element (CRE).
	"""
	def __init__(self,
		chr:str = None,
		position:list = [0, 0],
		strand:str = '+',
		peaks:float = 0.0,
		**kwargs,
		):
		"""
		:param chr: <str Default = None>
			Chromosomal location of the CRE

		:param position: <list Default = [0.0]>
			Genomic position of the CRE.
			[Start position, End position]

		:param strand: <str Default = '+'>
			Which strand the CRE is located.

		:param peaks: <float Default = None>
			Peak-calling result of the CRE.
		"""
		super(CRE, self).__init__()
		self.id = chr + ':' + str(position[0]) + '-' + str(position[1])
		self.chr = chr
		self.position = position
		self.strand = strand
		self.peaks = peaks
		# if there are other args
		for key in kwargs: setattr(self, key, kwargs[key])

class Gene(GRN_Basic):
	"""
	Class to store information of a Gene.
	"""
	def __init__(self,
		id:str = None,
		# symbol:str = None,
		# type:str = 'Gene',
		# gff_coordinates:list = list(),
		rna_exp:float = 0.0,
		peaks:float = 0.0,
		promoter_peaks:float = 0.0,
		# cre_regions:list = list(),
		**kwargs
		):
		"""
		:param id: <str Default = None>
			Ensembl ID.

		:param symbol: <str Default = None>
			Gene Symbol.

		:param type: <str Default = 'Gene'>
			If the gene is known to be Transcription Factor, change it to 'TF'.

		:param gff_coordinates: <list Default = None>
			The locations of corresponding record in the refernece GFF file.

		:param rna_exp: <float Default = 0.0>
			Transcriptomic expression of gene.

		:param peaks: <float Default = 0.0>
			Peak-calling result of the gene.

		:param promoter_peaks: <float Default = 0.0>
			Peak-calling result of the promoter region of gene.

		:param cre_regions: <list[CRE_IDS] Default = Empty List>
			List of CREs interacting with the gene.
			Note: Based on database like 4DGenome.
		"""
		super(Gene, self).__init__()
		self.id = id
		# self.symbol = symbol
		# self.type = type
		# self.gff_coordinates = gff_coordinates
		self.rna_exp = rna_exp
		self.peaks = peaks
		self.promoter_peaks = promoter_peaks
		# self.cre_regions = cre_regions
		# if there are other args
		for key in kwargs: setattr(self, key, kwargs[key])

class GRP(GRN_Basic):
	"""
	Class to store information of a Gene Regulatory Pathway(GRP).
	"""
	def __init__(self,
		reg_source:Gene = Gene(),
		reg_target:Gene = Gene(),
		reversable:bool = False,
		exp_cor:float = 0.0,
		motif_enrich:float = 0.0,
		**kwargs
		):
		"""
		:param reg_source: <class fatez.lib.grn.Gene>
			The object of propective regulatory source gene.

		:param reg_target: <class fatez.lib.grn.Gene>
			The object of propective regulatory target gene.

		:param reversable: <bool Default = False>
			Whether the target gene can also regulate expression of source gene.
			Note: The reverse GRP is expected to be a seperate object!

		:param exp_cor: <float Default = 0.0>
			The expression correlation between source gene and target gene.

		:param motif_enrich: <float Default = 0.0>
			Enrichment of source gene's motifs to regulate target gene.
		"""
		super(GRP, self).__init__()
		if type(reg_source) == str and type(reg_target) == str:
			self.id = reg_source + '_' + reg_target
		else:
			self.id = reg_source.id + '_' + reg_target.id
		self.reg_source = reg_source
		self.reg_target = reg_target
		self.reversable = reversable
		self.exp_cor = exp_cor
		self.motif_enrich = motif_enrich
		# if there are other args
		for key in kwargs: setattr(self, key, kwargs[key])

	def as_dict(self):
		"""
		Cast object into dict type.

		:return: <class 'dict'>
		"""
		answer = copy.deepcopy(self.__dict__)
		answer['reg_source'] = self.reg_source.id
		answer['reg_target'] = self.reg_target.id
		return answer

class GRN(GRN_Basic):
	"""
	Class for representing Gene Regulatory Network(GRN).

	Attributes:
		:self.genes: Dictionary of Gene() objects in the GRN
		:self.grps: Dictionary of GRP() objects in the GRN
	"""
	def __init__(self, id:str = None, **kwargs):
		"""
		:param id: <str Default = None>
			The ID for GRN object.
		"""
		super(GRN, self).__init__()
		self.id = id
		self.genes = dict()
		self.grps = dict()
		# if there are other args
		for key in kwargs: setattr(self, key, kwargs[key])

	def add_gene(self, gene:Gene = None):
		"""
		Add a new gene into GRN.

		:param gene: <class fatez.lib.grn.Gene>
			The Gene object to add.
		"""
		assert gene.id not in self.genes
		self.genes[gene.id] = gene
		return

	def add_grp(self, grp:GRP = None):
		"""
		Add a new GRP into GRN.

		:param grp: <class fatez.lib.grn.GRP>
			The GRP object to add.
		"""
		assert grp.id not in self.grps
		self.grps[grp.id] = grp
		return

	def as_dict(self):
		"""
		Cast object into dict type.

		:return: <class 'dict'>
		"""
		answer = {
			'genes': {id:record.as_dict() for id, record in self.genes.items()},
			'grps': {id:record.as_dict() for id, record in self.grps.items()},
		}
		for key in self.__dict__:
			if key == 'genes' or key == 'grps':
				continue
			elif key == 'cres':
				answer[key] = {
					id:record.as_dict() for id, record in self.cres.items()
				}
			else:
				answer[key] = self.__dict__[key]
		return answer

	def as_digraph(self):
		"""
		Cast object into networkx DiGraph type.

		:return: <class 'networkx.classes.digraph.DiGraph'>
		"""
		graph = nx.DiGraph()
		for grp_id in self.grps.keys():
			source = self.grps[grp_id].reg_source
			target = self.grps[grp_id].reg_target

			# add regulatory source and target genes to nodes
			if not graph.has_node(source.id):
				graph.add_node(source.id, **source.as_dict())
			if not graph.has_node(target.id):
				graph.add_node(target.id, **target.as_dict())

			# add GRP as an edge
			graph.add_edge(source.id, target.id, **self.grps[grp_id].as_dict())
		return graph

	def save(self, save_path:str = None, indent:int = 4):
		"""
		Save current GRN into a JSON file.

		:param save_path: <str Default = 'out.js'>
	        Path to save the output file.

	    :param indent: <int Default = 4>
	        Length of each indent.
		"""
		JSON.encode(data=self.as_dict(), save_path=save_path, indent=indent)
		return

	def load(self, load_path:str = None):
		"""
		Load GRN from a given JSON file.

		:param save_path: <str Default = 'out.js'>
	        Path to save the output file.

	    :param indent: <int Default = 4>
	        Length of each indent.
		"""
		data = JSON.decode(path = load_path)
		self.id = data['id']
		# Load genes first
		for id, rec in data['genes'].items():
			self.genes[id] = Gene(**rec)
		# Then load GRPs
		for id, rec in data['grps'].items():
			self.grps[id] = GRP(**rec)
			# Change reg source and target back to objects
			self.grps[id].reg_source = self.genes[self.grps[id].reg_source]
			self.grps[id].reg_target = self.genes[self.grps[id].reg_target]
		# Check CREs
		if 'cres' in data:
			self.cres = dict()
			for id, rec in data['cres'].items():
				self.cres[id] = CRE(**rec)
		# Check genetic regions
		if 'regions' in data:
			self.regions = dict()
			for chr, recs in data['regions'].items():
				self.regions[chr] = [x for x in recs]
		# Load other attrs if there is any
		for k in data:
			if k not in ['id','genes','grps','cres','regions']:
				setattr(self, k, data[k])
		return

# def test_grn():
#     toy = GRN(id = 'toy')
#     # fake genes
#     gene_list = [
#         Gene(id = 'a', symbol = 'AAA'),
#         Gene(id = 'b', symbol = 'BBB'),
#         Gene(id = 'c', symbol = 'CCC'),
#     ]
#     # fake grps
#     grp_list = [
#         GRP(reg_source = gene_list[0], reg_target = gene_list[1]),
#         GRP(reg_source = gene_list[0], reg_target = gene_list[2]),
#         GRP(reg_source = gene_list[1], reg_target = gene_list[2]),
#     ]
#     # populate toy GRN
#     for gene in gene_list:
#         toy.add_gene(gene)
#     for grp in grp_list:
#         toy.add_grp(grp)
#
#     toy.as_dict()
#     toy.as_digraph()
#     toy.save('../data/toy.grn.js.gz')
#     # Load new GRN
#     del toy
#     toy_new = GRN()
#     toy_new.load('../data/toy.grn.js.gz')
#     for id, rec in toy_new.grps.items():
#         print(rec.reg_source.symbol)


import pandas as pd
import os
import sys
import csv
import collections
from pylab import *

def df_dict(df):

    dic = {}
    k = df.keys().values
    v = df.values
    for i in range(len(k)):
        dic[k[i]] = v[0][i]
    return dic

def update_dict(x, y):
    for k, v in y.items():
        if k in x:
            o = x[k]
            x[k] = o + v
        else:
            x[k] = v
    return x

def main(argv):
    eps = argv[0]
    # eps = '0.5'
    positive = 39305237
    # eps = '0.3'
    path = 'stats/buffer_info_' + eps + '/files'
    files = os.listdir(path)
    f_n = len(files)
    # dum_real = {}
    idx = {}
    time_dic = {}
    real_idx = {}
    for i in range(1, 21):
        # dr_p = path + '/dum_real_' + str(i) + '.csv'
        index_p = path + '/index_' + str(i) + '.csv'
        time_p = path + '/time_' + str(i) + '.csv'
        real_idx_p = path + '/real_index_' + str(i) + '.csv'

        # dum_real_df = pd.read_csv(dr_p)
        index_df = pd.read_csv(index_p)
        time_df = pd.read_csv(time_p)
        rd_df = pd.read_csv(real_idx_p)
        # dum_real_dic, index_dic, t_dic, real_dic = map(df_dict, [dum_real_df, index_df, time_df, rd_df])
        index_dic, t_dic, real_dic = map(df_dict, [index_df, time_df, rd_df])
        parent_dic = [idx, time_dic, real_idx]
        son_dic = [index_dic, t_dic, real_dic]
        idx, time_dic, real_idx = map(update_dict, parent_dic, son_dic)
        print(str(i))

    with open('stats/buffer_info_' + eps + '/index_' + eps +'.csv', 'w') as _idx:
        writer = csv.DictWriter(_idx, idx.keys())
        writer.writeheader()
        writer.writerow(idx)

    with open('stats/buffer_info_' + eps + '/time_' + eps +'.csv', 'w') as _t:
        writer = csv.DictWriter(_t, time_dic.keys())
        writer.writeheader()
        writer.writerow(time_dic)

    # with open('stats/buffer_info_' + eps + '/dum_real_' + eps +'.csv', 'w') as _t:
    #     writer = csv.DictWriter(_t, dum_real.keys())
    #     writer.writeheader()
    #     writer.writerow(dum_real)

    # real_idx['0.0'] += positive

    sum_idx = sum(i for i in idx.values())
    sum_time = sum(i for i in time_dic.values())
    sum_real = sum(i for i in real_idx.values())

    real_idx1 ={}
    for k, v in real_idx.items():
        real_idx1[float(k)] = v
    real_idx = collections.OrderedDict(sorted(real_idx1.items()))
    a = positive - sum_real
    real_idx[0] += a
    time_dic['0'] += a
    with open('stats/buffer_info_' + eps + '/real_index_' + eps +'.csv', 'w') as _t:
        writer = csv.DictWriter(_t, real_idx.keys())
        writer.writeheader()
        writer.writerow(real_idx)

    sum_idx = sum(i for i in idx.values())
    sum_time = sum(i for i in time_dic.values()) - time_dic['-1']
    sum_real = sum(i for i in real_idx.values())
    idx_pdf = {}
    time_pdf = {}
    real_pdf = {}

    idx_cdf = {}
    time_cdf = {}
    real_cdf = {}
    cdf_idx = 0
    cdf_time = 0
    cdf_real = 0
    for k, v in idx.items():
        r = (v / sum_idx)
        cdf_idx += r
        idx_pdf[k] = r
        idx_cdf[k] = cdf_idx

    for k, v in time_dic.items():
        r = (v / sum_time)
        cdf_time += r
        time_pdf[k] = r
        time_cdf[k] = cdf_time

    for k, v in real_idx.items():
        r = (v / sum_real)
        cdf_real += r
        real_pdf[k] = r
        real_cdf[k] = cdf_real

    with open('stats/buffer_info_' + eps + '/index_pdf_' + eps +'.csv', 'w') as _i_p:
        writer = csv.DictWriter(_i_p, idx_pdf.keys())
        writer.writeheader()
        writer.writerow(idx_pdf)

    with open('stats/buffer_info_' + eps + '/time_pdf_' + eps +'.csv', 'w') as _t_p:
        writer = csv.DictWriter(_t_p, time_pdf.keys())
        writer.writeheader()
        writer.writerow(time_pdf)

    with open('stats/buffer_info_' + eps + '/real_pdf_' + eps +'.csv', 'w') as _r_p:
        writer = csv.DictWriter(_r_p, real_pdf.keys())
        writer.writeheader()
        writer.writerow(real_pdf)

    with open('stats/buffer_info_' + eps + '/index_cdf_' + eps +'.csv', 'w') as _i_c:
        writer = csv.DictWriter(_i_c, idx_cdf.keys())
        writer.writeheader()
        writer.writerow(idx_cdf)

    with open('stats/buffer_info_' + eps + '/time_cdf_' + eps + '.csv', 'w') as _t_c:
        writer = csv.DictWriter(_t_c, time_cdf.keys())
        writer.writeheader()
        writer.writerow(time_cdf)

    with open('stats/buffer_info_' + eps + '/real_cdf_' + eps + '.csv', 'w') as _r_c:
        writer = csv.DictWriter(_r_c, real_cdf.keys())
        writer.writeheader()
        writer.writerow(real_cdf)

if __name__ == '__main__':
    main(sys.argv[1:])
    # main()


# Use the file name mbox-short.txt as the file name
import re
fname = "text.txt"
list_number = []
count = 0
fh = open(fname)
for line in fh:
    if not line.startswith("X-DSPAM-Confidence:"):
        continue
    try:
        number = re.match('(X-DSPAM-Confidence:\s*)(\d*.\d*)', line)
        list_number.append(number.group(2))
        count += 1
        print(line)
    except Exception as e:
        print("error occurred")
new_list = []
for i in list_number:
    i = float(i)
    new_list.append(i)
print(sum(new_list)/len(new_list))
print(count)

notes/Python for Everybody/Python Data Structures/Week 3/Assignment 7.2.py


import dataclasses

import utils

@dataclasses.dataclass
class Fold:
    axis: str
    value: int

def fold_paper(dots, fold):
    new_dots = set()

    for x, y in dots:
        if fold.axis == 'x' and x > fold.value:
            new_dots.add((2 * fold.value - x, y))
        elif fold.axis == 'y' and y > fold.value:
            new_dots.add((x, 2 * fold.value - y))
        else:
            new_dots.add((x, y))

    return new_dots

def get_manual():
    dots, folds = utils.get_input(delimiter=None, line_delimiter='\n\n', cast=str)
    dots = set(tuple(dot) for dot in utils.parse(dots))
    folds = [
        Fold(axis, int(value))
        for axis, value in
        utils.parse(folds, delimiter='=', remove_prefix='fold along ', cast=str)
    ]
    return dots, folds

@utils.part
def part_1():
    dots, folds = get_manual()
    dots = fold_paper(dots, folds[0])
    print(len(dots))

@utils.part
def part_2():
    dots, folds = get_manual()

    for fold in folds:
        dots = fold_paper(dots, fold)

    max_x = max(dot[0] for dot in dots)
    max_y = max(dot[1] for dot in dots)

    for j in range(max_y + 1):
        for i in range(max_x + 1):
            point = (i, j)

            if point in dots:
                print('█', end='')
            else:
                print(' ', end='')

        print('\n')


from dataloader import get_loader
from solver import Solver
import os
import argparse
from torch.backends import cudnn

def main(config):
    # For fast training.
    cudnn.benchmark = True

    if not os.path.exists(config.model_save_dir):
        os.makedirs(config.model_save_dir)
    if not os.path.exists(config.sample_dir):
        os.makedirs(config.sample_dir)
    if not os.path.exists(config.result_dir):
        os.makedirs(config.result_dir)

    # Solver for training and testing VanillaGAN.
    solver = Solver(config)

    if config.mode == "train":
        solver.train()

    elif config.mode == "test":
        solver.test()

if __name__ == "__main__":
    parser = argparse.ArgumentParser()

    # Model Configuration
    parser.add_argument('--image_size', type=int, default=28*28, help='image_size')
    parser.add_argument('--latent_size', type=int, default=100, help='size of latent_vector used in Generator')

    # Miscellaneous Configuration
    parser.add_argument('--mode', type=str, default="train", choices=['train', 'test'])
    parser.add_argument('--num_workers', type=int, default=1)

    # Directories.
    parser.add_argument('--model_save_dir', type=str, default='models')
    parser.add_argument('--sample_dir', type=str, default='samples')
    parser.add_argument('--result_dir', type=str, default='results')

    #Training Configuration
    parser.add_argument('--batch_size', type=int, default=60, help='mini-batch_size')
    parser.add_argument('--num_epochs', type=int, default=100, help='total epochs')
    parser.add_argument('--g_lr', type=float, default=0.0002, help='learning rate for G')
    parser.add_argument('--d_lr', type=float, default=0.0002, help='learning rate for D')

    config = parser.parse_args()
    print(config)
    main(config)


import numpy as np
from scipy.io import loadmat
import warnings
from resampy import resample as resample2
import json

from data_utils import norm_power_wav, envelope, MudNoise, unit_power

from sep_eval import sep_eval as se
from model_stft import Mudv4, Mudv5FF, Mudv5LSTM
import os
import torch
import csv
from beamformers import beamformers as bf
from librosa import stft
import pickle as pkl

CONST = 10 * np.log10(np.exp(1))
warnings.simplefilter(action='ignore', category=FutureWarning)

datadir = '/Data/DATASETS/WSJ/mud_noise/'
codedir = '/Data/Dropbox/PhD/Projects/realmud'
noisedir = '/Data/DATASETS/NoiseX/8k/'

base_dir = codedir  # change this!
training_data_path = datadir + 'tr/debug_mud_v1.h5'  # change this!
validation_data_path = datadir + 'cv/debug_mud_v1.h5'  # change this!

def allign(x, y):
    corr = np.correlate(x - np.mean(x), y - np.mean(y), mode='full')
    lag = corr.argmax() - (len(x) - 1)
    _err_log = "OK"

    if lag > 0:
        x = x[lag:]
        y = y[:-lag]
    else:
        x = x[:]
        y = y[:]
        _err_log = "ERROR: lag {}".format(lag)
    return x, y, _err_log

class Evaluator(object):
    def __init__(self):

        self.model = None
        self.models = []
        self.models_type = []

        self.measures = []
        self.name_measure = []

        self.datasets = []
        self.name_dataset = []

    def add_model(self, name, tpe='cnn'):
        self.models.append(name)
        self.models_type.append(tpe)

    def add_measure(self, measure, name=None):
        if name is None:
            name = 'measure{}'.format(len(self.measures))
        self.name_measure.append(name)
        self.measures.append(measure)

    def add_dataset(self, mix, s1, n, name=None):
        if name is None:
            name = 'dataset{}'.format(len(self.datasets))
        self.name_dataset.append(name)
        self.datasets.append({'mix': mix, 's1': s1, 'n': n})

    @staticmethod
    def single_test(model, mix):
        # doing batches of 4
        batch_size = 4
        out = []
        for i in range(0, len(mix), batch_size):
            _out = model(mix[i:i + batch_size])
            _out = _out.cpu().data.numpy()
            out.append(_out)
        out = np.vstack(out)
        return out

    @staticmethod
    def single_beam(model, mix, s1, n, mask=None):
        rec = mix.data.numpy()
        y = s1.data.numpy()
        noise = n
        all_y_hat = []

        for _rec, _y, _noise in zip(rec, y, noise):
            if mask is not None:
                y_hat = model(_rec, noise=_noise, target=_y, mask=mask)
            else:
                y_hat = model(_rec, noise=_noise, target=_y)

            # calculate best correlation lag
            all_y_hat.append(y_hat)
        return all_y_hat

    @staticmethod
    def load_mask_model(load, base_dir='.'):
        json_dir = base_dir + '/exp/' + load
        with open(json_dir + '/architecture.json', 'r') as fff:
            p = json.load(fff)
            load_path = json_dir + '/net/' + 'cv/'

            model = Mudv4(n_fft=p['nfft'], kernel=(p['kernel1'], p['kernel2']), causal=p['causal'],
                          layers=p['layers'], stacks=p['stacks'], verbose=False)

            mdl_idx = sorted([int(l.split('_')[-1].split('.')[0]) for l in os.listdir(load_path)])[-1]
            model.load_state_dict(torch.load(load_path + 'model_weight_{}.pt'.format(mdl_idx)))
            _ = model.eval()
            return model, p

    @staticmethod
    def load_lstm_model(load, base_dir='.'):
        json_dir = base_dir + '/exp/' + load
        with open(json_dir + '/architecture.json', 'r') as fff:
            p = json.load(fff)
            load_path = json_dir + '/net/' + 'cv/'

            model = Mudv5LSTM(n_fft=p['nfft'], verbose=False)

            mdl_idx = sorted([int(l.split('_')[-1].split('.')[0]) for l in os.listdir(load_path)])[-1]

            model.load_state_dict(torch.load(load_path + 'model_weight_{}.pt'.format(mdl_idx)))
            _ = model.eval()
            return model, p

    @staticmethod
    def load_blstm_model(load, base_dir='.'):
        json_dir = base_dir + '/exp/' + load
        with open(json_dir + '/architecture.json', 'r') as fff:
            p = json.load(fff)
            load_path = json_dir + '/net/' + 'cv/'

            model = Mudv5LSTM(n_fft=p['nfft'], verbose=False, bidir=True)

            mdl_idx = sorted([int(l.split('_')[-1].split('.')[0]) for l in os.listdir(load_path)])[-1]

            model.load_state_dict(torch.load(load_path + 'model_weight_{}.pt'.format(mdl_idx)))
            _ = model.eval()
            return model, p

    @staticmethod
    def load_ff_model(load, base_dir='.'):
        json_dir = base_dir + '/exp/' + load
        with open(json_dir + '/architecture.json', 'r') as fff:
            p = json.load(fff)
            load_path = json_dir + '/net/' + 'cv/'

            model = Mudv5FF(n_fft=p['nfft'], verbose=False)

            mdl_idx = sorted([int(l.split('_')[-1].split('.')[0]) for l in os.listdir(load_path)])[-1]

            model.load_state_dict(torch.load(load_path + 'model_weight_{}.pt'.format(mdl_idx)))
            _ = model.eval()
            return model, p

    def evaluate(self, file_path='./out.csv', mode='w'):

        with open(file_path, mode) as csv_file:
            file_writer = csv.writer(csv_file, delimiter=',')
            # header = ['model', 'dataset', "nfft", "hop", "kernel1", "kernel2", "stacks", "nspk", "layers", "causal", "spkprob", "tr_len", "te_len", "max_len", "noise_train", "frame_train", "noise_test", "frame_test", "dataset"] + self.name_measure
            header = ['model', 'dataset'] + self.name_measure
            file_writer.writerow(header)
            for model, tpe in zip(self.models, self.models_type):
                model_row = [str(model)]

                net = False
                if type(model) == str:
                    print("Loading {}".format(model))
                    if tpe == 'cnn':
                        _model, _p = self.load_mask_model(model)
                    if tpe == 'lstm':
                        _model, _p = self.load_lstm_model(model)
                    if tpe == 'blstm':
                        _model, _p = self.load_blstm_model(model)
                    if tpe == 'ff':
                        _model, _p = self.load_ff_model(model)
                    net = True
                else:
                    _model = model
                # for k, v in _p.items():
                #     model_row.append(v)

                for dataset, name_dataset in zip(self.datasets, self.name_dataset):
                    dataset_row = [name_dataset]
                    if net:
                        _out = self.single_test(_model, dataset['mix'])

                    else:
                        if 'MB_MVDR' in str(model):
                            _out = self.single_beam(_model, dataset['mix'], dataset['s1'], dataset['n'], mask='IRM')
                        else:
                            _out = self.single_beam(_model, dataset['mix'], dataset['s1'], dataset['n'])

                    _s1 = dataset['s1'][:, 0].cpu().data.numpy()

                    collected_measures = []
                    for measure, name_measure in zip(self.measures, self.name_measure):
                        collected_measures.append(measure(_out, _s1))

                    # separate
                    res = np.zeros((len(self.measures), len(collected_measures[0])))
                    for j, m in enumerate(collected_measures):
                        for i, val in enumerate(m):
                            res[j, i] = val
                    for i in range(res.shape[1]):
                        _t = []
                        for j in range(res.shape[0]):
                            _t.append(res[j, i])
                        file_writer.writerow(model_row + dataset_row + _t)
                del _model  # for RAM

def main():
    print("Loading data...")
    # data = pkl.load(open('session_2_enh.pkl', 'rb'))

    # test data
    K = MudNoise(validation_data_path, noisedir=noisedir, task='cv', n_ch=6, verbose=True)

    A, B, C = [], [], []
    for i in range(200):
        a, b, c = K[i]
        A.append(a.unsqueeze(0))
        B.append(b.unsqueeze(0))
        C.append(c)

    _mix = torch.cat(A, 0)
    _s1 = torch.cat(B, 0)
    _n = np.array(C)

    print("Verbose test MIX: {}".format(_mix.shape))
    print("Verbose test S1: {}".format(_s1.shape))
    print("Verbose test noise: {}".format(_n.shape))

    # ACTUAL COMPUTE

    evaluator = Evaluator()

    # evaluator.add_model(bf.MB_MVDR_oracle)
    #
    # evaluator.add_model(bf.SDW_MWF)

    # evaluator.add_model('201903015559_Mudv4_NC_256_4')
    #
    # evaluator.add_model('201903050417_Mudv4_NC_256_6')
    #
    # evaluator.add_model('201903072009_Mudv4_C_256_4')
    #
    # evaluator.add_model('201903072324_Mudv4_C_256_6')
    #
    # evaluator.add_model('201903150615_Mudv4_256_NC')

    # evaluator.add_model('201903152712_Mudv4_C_256_4')

    # evaluator.add_model('201903152912_Mudv4_C_512_4')

    # evaluator.add_model('201903152912_Mudv4_NC_512_4')

    # evaluator.add_model('201903152912_Mudv4_NC_512_6')

    # evaluator.add_model('201903152913_Mudv4_C_512_6')

    evaluator.add_model('201906184113_lstm_likeHay_1_NC', 'lstm')
    evaluator.add_model('201906235713_bidirLSTM_likeKHey_2_NC', 'blstm')

    evaluator.add_model('201906002742_ff_likeHey_3_NC', 'ff')

    evaluator.add_dataset(_mix,  _s1, _n, name='verbose test')

    evaluator.add_measure(se.sdr, name='sdr')
    evaluator.add_measure(se.stoi, name='stoi')
    evaluator.evaluate(file_path='./results_sym_data_lstm_dnn.csv', mode='w')

if __name__ == "__main__":
    main()


# #######################################################################################################################
# Import statements
import os
from id3.media import EncodedBy

from log.Logger import TreeLogger

# #######################################################################################################################
__project__ = 'metapy'
__author__ = 'Vijay Shanker Dubey'

########################################################################################################################
class FrameHeader:
    """
        Represents a music frame.
    """

    def __init__(self):
        content = []

        self.frameId = content[4]
        self.flags = content[5]
        self.size = content[6:10]

########################################################################################################################
class MusicFile:
    """
    Represents a music file as cleanup source
    """

    def __init__(self, file_name):
        self.is_mp3_file = False
        self.file_name = file_name
        self.logger = TreeLogger("Processing file : {0}".format(str(file_name)))
        basename, extension = os.path.splitext(file_name)

        if extension == '.mp3':
            self.is_mp3_file = True
            self.logger.debug('Input file is a valid mp3 file.')

    def list_tags(self):
        logger = self.logger.branch_out()

        if self.is_mp3_file:
            logger.debug('Cleaning Music file tags for : {0}'.format(self.file_name))

            try:
                music_source = open(self.file_name, "r+b", 0)
                try:
                    music_source.seek(0)

                    # Read Tag version
                    version_tag = music_source.read(3)
                    if to_string(version_tag) == 'ID3':
                        self.read_id3_tags(music_source, logger)

                finally:
                    music_source.close()
            except IOError as err:
                logger.debug(err)

    def read_id3_tags(self, file_source, logger):
        """
        Reads the ID3 tags from the file source.

        @param file_source: file to read tags
        @param logger: tree logger; used for logging in the execution context.
        """
        sub_version_tags = file_source.read(3)

        if sub_version_tags[0] == 3 and sub_version_tags[1] == 0:
            tag_version = "ID3v2.{0}.{1}".format(str(sub_version_tags[0]), str(sub_version_tags[1]))
            logger.debug("Music tag format : {0}".format(tag_version))

        data_flag = sub_version_tags[2]

        print(data_flag)

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

def main():
    file_name = 'D:/usr/Music/downloads/03 - 2 States (2014) - Mast Magan [www.DJLUV.in].mp3'

    header = TagHeader(file_name)
    if not header.has_flag("extended"):
        # Read extended flag related data.
        print("extended flag does not exists in the file.")
    print(str(header))

    # Start to read frames in source file
    source = open(file_name, 'rb')
    # frames starts at 10th byte; if no extended header present. Other wise frame start is after the extended header.
    frame_start = 10
    if not header.has_flag("extended"):
        header_size = 10  # Calculate the header value
        frame_start = header_size

    #skip header bytes
    source.seek(frame_start)

if __name__ == '__main__':
    main()


from collections import defaultdict
from aocd import get_data

data = get_data(day=12, year=2021)
data = data.splitlines()

def dfs(currentNode, visited):
    if(currentNode == "end"):
        return True
    elif(currentNode in visited):
        return False
    elif(currentNode in smallCaves):
        visited.append(currentNode)

    pathsCount = 0

    for node in adjacent[currentNode]:
        pathsCount += dfs(node, visited)

    if(currentNode in visited):
        visited.remove(currentNode)
    return pathsCount

edges = []
for line in data:
    edges.append(line.split("-"))

adjacent = defaultdict(list)
smallCaves = []

for edge in edges:
    a = edge[0]
    b = edge[1]
    if(a.islower()):
        smallCaves.append(a)
    if(b.islower()):
        smallCaves.append(b)

    adjacent[a].append(b)
    adjacent[b].append(a)

result = dfs("start", [])
print(result)


from collections import OrderedDict
import torch
from torch import Tensor
from .patches import Patches, inplace_unfold

from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from .bound_general import BoundedModule

class SparseBeta:
    def __init__(self, shape, bias=False, betas=None, device='cpu'):
        self.device = device
        self.val = torch.zeros(shape)
        self.loc = torch.zeros(shape, dtype=torch.long, device=device)
        self.sign = torch.zeros(shape, device=device)
        self.bias = torch.zeros(shape) if bias else None
        if betas:
            for bi in range(len(betas)):
                if betas[bi] is not None:
                    self.val[bi, :len(betas[bi])] = betas[bi]
        self.val = self.val.detach().to(
            device, non_blocking=True).requires_grad_()

    def apply_splits(self, history, key):
        for bi in range(len(history)):
            # Add history splits. (layer, neuron) is the current decision.
            split_locs, split_coeffs = history[bi][key][:2]
            split_len = len(split_locs)
            if split_len > 0:
                self.sign[bi, :split_len] = torch.as_tensor(
                    split_coeffs, device=self.device)
                self.loc[bi, :split_len] = torch.as_tensor(
                    split_locs, device=self.device)
                if self.bias is not None:
                    split_bias = history[bi][key][2]
                    self.bias[bi, :split_len] = torch.as_tensor(
                        split_bias, device=self.device)
        self.loc = self.loc.to(device=self.device, non_blocking=True)
        self.sign = self.sign.to(device=self.device, non_blocking=True)
        if self.bias is not None:
            self.bias = self.bias.to(device=self.device, non_blocking=True)

def get_split_nodes(self: 'BoundedModule', input_split=False):
    self.split_nodes = []
    self.split_activations = {}
    splittable_activations = self.get_splittable_activations()
    self._set_used_nodes(self[self.final_name])
    for layer in self.layers_requiring_bounds:
        split_activations_ = []
        for activation_name in layer.output_name:
            activation = self[activation_name]
            if activation in splittable_activations:
                split_activations_.append(
                    (activation, activation.inputs.index(layer)))
        if split_activations_:
            self.split_nodes.append(layer)
            self.split_activations[layer.name] = split_activations_
    if input_split:
        root = self[self.root_names[0]]
        if root not in self.split_nodes:
            self.split_nodes.append(root)
            self.split_activations[root.name] = []
    return self.split_nodes, self.split_activations

def set_beta(self: 'BoundedModule', enable_opt_interm_bounds, parameters,
             lr_beta, lr_cut_beta, cutter, dense_coeffs_mask):
    """
    Set betas, best_betas, coeffs, dense_coeffs_mask, best_coeffs, biases
    and best_biases.
    """
    coeffs = None
    betas = []
    best_betas = OrderedDict()

    # TODO compute only once
    self.nodes_with_beta = []
    for node in self.split_nodes:
        if not hasattr(node, 'sparse_betas'):
            continue
        self.nodes_with_beta.append(node)
        if enable_opt_interm_bounds:
            for sparse_beta in node.sparse_betas.values():
                if sparse_beta is not None:
                    betas.append(sparse_beta.val)
            best_betas[node.name] = {
                beta_m: sparse_beta.val.detach().clone()
                for beta_m, sparse_beta in node.sparse_betas.items()
            }
        else:
            betas.append(node.sparse_betas[0].val)
            best_betas[node.name] = node.sparse_betas[0].val.detach().clone()

    # Beta has shape (batch, max_splits_per_layer)
    parameters.append({'params': betas.copy(), 'lr': lr_beta, 'batch_dim': 0})

    if self.cut_used:
        self.set_beta_cuts(parameters, lr_cut_beta, betas, best_betas, cutter)

    return betas, best_betas, coeffs, dense_coeffs_mask

def set_beta_cuts(self: 'BoundedModule', parameters, lr_cut_beta, betas,
                  best_betas, cutter):
    # also need to optimize cut betas
    parameters.append({'params': self.cut_beta_params,
                        'lr': lr_cut_beta, 'batch_dim': 0})
    betas += self.cut_beta_params
    best_betas['cut'] = [beta.detach().clone() for beta in self.cut_beta_params]
    if getattr(cutter, 'opt', False):
        parameters.append(cutter.get_parameters())

def reset_beta(self: 'BoundedModule', node, shape, betas, bias=False,
               start_nodes=None):
    # Create only the non-zero beta. For each layer, it is padded to maximal length.
    # We create tensors on CPU first, and they will be transferred to GPU after initialized.
    if self.bound_opts.get('enable_opt_interm_bounds', False):
        node.sparse_betas = {
            key: SparseBeta(
                shape,
                betas=[(betas[j][i] if betas[j] is not None else None)
                        for j in range(len(betas))],
                device=self.device, bias=bias,
            ) for i, key in enumerate(start_nodes)
        }
    else:
        node.sparse_betas = [SparseBeta(
            shape, betas=betas, device=self.device, bias=bias)]

def beta_crown_backward_bound(self: 'BoundedModule', node, lA, uA, start_node=None):
    """Update A and bias with Beta-CROWN.

    Must be explicitly called at the end of "bound_backward".
    """
    # Regular Beta CROWN with single neuron split
    # Each split constraint only has single neuron (e.g., second ReLU neuron > 0).
    A = lA if lA is not None else uA
    lbias = ubias = 0

    def _bias_unsupported():
        raise NotImplementedError('Bias for beta not supported in this case.')

    if type(A) is Patches:
        if not self.bound_opts.get('enable_opt_interm_bounds', False):
            raise NotImplementedError('Sparse beta not supported in the patches mode')
        if node.sparse_betas[start_node.name].bias is not None:
            _bias_unsupported()
        # expand sparse_beta to full beta
        beta_values = (node.sparse_betas[start_node.name].val
                       * node.sparse_betas[start_node.name].sign)
        beta_indices = node.sparse_betas[start_node.name].loc
        node.masked_beta = torch.zeros(2, *node.shape).reshape(2, -1).to(A.patches.dtype)
        node.non_deter_scatter_add(
            node.masked_beta, dim=1, index=beta_indices,
            src=beta_values.to(node.masked_beta.dtype))
        node.masked_beta = node.masked_beta.reshape(2, *node.shape)
        # unfold the beta as patches, size (batch, out_h, out_w, in_c, H, W)
        A_patches = A.patches
        masked_beta_unfolded = inplace_unfold(
            node.masked_beta, kernel_size=A_patches.shape[-2:],
            padding=A.padding, stride=A.stride,
            inserted_zeros=A.inserted_zeros, output_padding=A.output_padding)
        if A.unstable_idx is not None:
            masked_beta_unfolded = masked_beta_unfolded.permute(1, 2, 0, 3, 4, 5)
            # After selection, the shape is (unstable_size, batch, in_c, H, W).
            masked_beta_unfolded = masked_beta_unfolded[A.unstable_idx[1], A.unstable_idx[2]]
        else:
            # Add the spec (out_c) dimension.
            masked_beta_unfolded = masked_beta_unfolded.unsqueeze(0)
        if node.alpha_beta_update_mask is not None:
            masked_beta_unfolded = masked_beta_unfolded[node.alpha_beta_update_mask]
        if uA is not None:
            uA = uA.create_similar(uA.patches + masked_beta_unfolded)
        if lA is not None:
            lA = lA.create_similar(lA.patches - masked_beta_unfolded)
    elif type(A) is Tensor:
        if self.bound_opts.get('enable_opt_interm_bounds', False):
            if node.sparse_betas[start_node.name].bias is not None:
                _bias_unsupported()
            # For matrix mode, beta is sparse.
            beta_values = (
                node.sparse_betas[start_node.name].val
                * node.sparse_betas[start_node.name].sign
            ).expand(A.size(0), -1, -1)
            # node.single_beta_loc has shape [batch, max_single_split].
            # Need to expand at the specs dimension.
            beta_indices = (node.sparse_betas[start_node.name].loc
                            .unsqueeze(0).expand(A.size(0), -1, -1))
            beta_bias = node.sparse_betas[start_node.name].bias
        else:
            # For matrix mode, beta is sparse.
            beta_values = (
                node.sparse_betas[0].val * node.sparse_betas[0].sign
            ).expand(A.size(0), -1, -1)
            # self.single_beta_loc has shape [batch, max_single_split].
            # Need to expand at the specs dimension.
            beta_indices = node.sparse_betas[0].loc.unsqueeze(0).expand(A.size(0), -1, -1)
            beta_bias = node.sparse_betas[0].bias
        # For conv layer, the last dimension is flattened in indices.
        beta_values = beta_values.to(A.dtype)
        if beta_bias is not None:
            beta_bias = beta_bias.expand(A.size(0), -1, -1)
        if node.alpha_beta_update_mask is not None:
            beta_indices = beta_indices[:, node.alpha_beta_update_mask]
            beta_values = beta_values[:, node.alpha_beta_update_mask]
            if beta_bias is not None:
                beta_bias = beta_bias[:, node.alpha_beta_update_mask]
        if uA is not None:
            uA = node.non_deter_scatter_add(
                uA.reshape(uA.size(0), uA.size(1), -1), dim=2,
                index=beta_indices, src=beta_values).view(uA.size())
        if lA is not None:
            lA = node.non_deter_scatter_add(
                lA.reshape(lA.size(0), lA.size(1), -1), dim=2,
                index=beta_indices, src=beta_values.neg()).view(lA.size())
        if beta_bias is not None:
            bias = (beta_values * beta_bias).sum(dim=-1)
            lbias = bias
            ubias = -bias
    else:
        raise RuntimeError(f"Unknown type {type(A)} for A")

    return lA, uA, lbias, ubias

def print_optimized_beta(acts):
    masked_betas = []
    for model in acts:
        masked_betas.append(model.masked_beta)
        if model.history_beta_used:
            print(f'{model.name} history beta', model.new_history_beta.squeeze())
        if model.split_beta_used:
            print(f'{model.name} split beta:', model.split_beta.view(-1))
            print(f'{model.name} bias:', model.split_bias)