# -------------------------------------------------------------------------------------------------
# Imports
# -------------------------------------------------------------------------------------------------

import asyncio
import base64
import sys
import logging
import traceback
from pathlib import Path
import json
import io
from pprint import pprint
import urllib.request

from joblib import Memory
import numpy as np
import websockets
from PIL import Image

from datoviz import Requester, Renderer

logger = logging.getLogger('datoviz')

class Bunch(dict):
    def __init__(self, *args, **kwargs):
        self.__dict__ = self
        super().__init__(*args, **kwargs)

# -------------------------------------------------------------------------------------------------
# CONSTANTS
# -------------------------------------------------------------------------------------------------

CURDIR = Path(__file__).parent.resolve()
WIDTH = 800
HEIGHT = 600
MAX_COUNT = 10_000_000
ALPHA = 128
SIZE = 5
COLOR = 128

DEFAULT_URI = "https://ibl.flatironinstitute.org/public/cortexlab/Subjects/KS023/2019-12-10/001/alf/probe01/"
SESSIONS = {
    "https://ibl.flatironinstitute.org/public/cortexlab/Subjects/KS023/2019-12-10/001/alf/probe01/": {
        "times": "spikes.times.99ed1a2d-bb18-4f86-92f3-23a15b7d9972.npy",
        "clusters": "spikes.clusters.2e3a207d-6b7a-41b3-80b9-d759a6557b55.npy",
        "depths": "spikes.depths.9cbed712-3d4e-44d4-8ec8-f915a884e667.npy"
    },

    "https://ibl.flatironinstitute.org/public/churchlandlab/Subjects/CSHL047/2020-01-20/001/alf/probe00/": {
        "times": "spikes.times.32609666-84f6-4b20-8450-afc311b3e64e.npy",
        "clusters": "spikes.clusters.a44513ba-069e-443a-bcb6-1de2a5071615.npy",
        "depths": "spikes.depths.879aedc4-227d-4234-828e-9d9f78b7323e.npy",
    },

    "https://ibl.flatironinstitute.org/public/mainenlab/Subjects/ZM_2240/2020-01-21/001/alf/probe00/": {
        "times": "spikes.times.be8c4562-f83d-45c3-ba4d-7ac9eec94b85.npy",
        "clusters": "spikes.clusters.33e2b747-8cf9-48d7-9814-69c6aa30cd59.npy",
        "depths": "spikes.depths.7ba042a8-cc40-416f-8390-12b0c8f4009f.npy",
    }
}

# -------------------------------------------------------------------------------------------------
# Data access
# -------------------------------------------------------------------------------------------------

MEMORY = Memory(".")

@MEMORY.cache
def download(url):
    with urllib.request.urlopen(url) as f:
        return io.BytesIO(f.read())

def normalize(x):
    m = x.min()
    M = x.max()
    if m == M:
        logger.warning("degenerate values")
        M = m + 1
    return -1 + 2 * (x - m) / (M - m)

def from_base64(buf):
    r = base64.decodebytes(buf.encode('ascii'))
    return np.frombuffer(r, dtype=np.uint8)

# -------------------------------------------------------------------------------------------------
# Renderer
# -------------------------------------------------------------------------------------------------

MVP_BUFFER = "AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAA=="
VIEWPORT_BUFFER = "AAAAAAAAAAAAAEhEAAAWRAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAwAAWAIAAAAAAAAAAAAAIAMAAFgCAAAAAAAAAAAAAAAAAAAAAAAA"

board_id = 1
graphics_id = 2
mvp_id = 10
viewport_id = 11
vertex_id = 3

def get_data(uri, st_name, sd_name, t0=0, t1=1):
    spike_times = np.load(download(uri + st_name))
    spike_depths = np.load(download(uri + sd_name))
    spike_depths[np.isnan(spike_depths)] = 0

    assert 0 <= t0 and t0 < t1

    # HACK: will need resize_dat request to lift this limitation
    assert spike_times.shape[0] <= MAX_COUNT

    # # DEBUG
    # spike_times = spike_times[:MAX_COUNT]
    # spike_depths = spike_depths[:MAX_COUNT]

    # Select spikes in the time range.
    imin = np.searchsorted(spike_times, t0)
    imax = np.searchsorted(spike_times, t1)

    logger.debug(f"downloaded {len(spike_times)} spikes, keep {imax - imin}")

    spike_times = spike_times[imin:imax]
    spike_depths = spike_depths[imin:imax]

    x = normalize(spike_times)
    y = normalize(spike_depths)

    n = spike_times.shape[0]
    arr = np.zeros(
        n, dtype=[('pos', np.float32, 3), ('color', np.uint8, 4), ('size', np.float32)])

    arr["pos"][:, 0] = x
    arr["pos"][:, 1] = y

    arr["size"][:] = SIZE

    v = COLOR
    a = ALPHA
    arr['color'][:, 0] = v
    arr['color'][:, 1] = v
    arr['color'][:, 2] = v
    arr['color'][:, 3] = a

    return arr

def record(rqr, count):
    logger.debug(f"draw {count} spikes")

    rqr.record_begin(board_id)
    rqr.record_viewport(board_id, 0, 0, 0, 0)
    rqr.record_draw(board_id, graphics_id, 0, count)
    rqr.record_end(board_id)

def create(rqr, rnd, uri, st_name, sd_name, t0=0, t1=1):
    with rqr.requests():
        rqr.create_board(WIDTH, HEIGHT, background=(
            255, 255, 255), id=board_id)
        rqr.create_graphics(board_id, 1, id=graphics_id)

        rqr.create_dat(5, 200, id=mvp_id)
        rqr.bind_dat(graphics_id, 0, mvp_id)
        rqr.upload_dat(mvp_id, 0, from_base64(MVP_BUFFER))

        rqr.create_dat(5, 80, id=viewport_id)
        rqr.bind_dat(graphics_id, 1, viewport_id)
        rqr.upload_dat(viewport_id, 0, from_base64(VIEWPORT_BUFFER))

        rqr.create_dat(2, 20 * MAX_COUNT, id=vertex_id)
        rqr.set_vertex(graphics_id, vertex_id)
        data = get_data(uri, st_name, sd_name, t0=t0, t1=t1)
        rqr.upload_dat(vertex_id, 0, data)

        record(rqr, data.shape[0])

    rqr.submit(rnd)

def update(rqr, rnd, uri, st_name, sd_name, t0=0, t1=1):
    with rqr.requests():
        data = get_data(uri, st_name, sd_name, t0=t0, t1=t1)
        rqr.upload_dat(vertex_id, 0, data)
        record(rqr, data.shape[0])
    rqr.submit(rnd)

def render(rqr, rnd, board_id=1):
    # Trigger a redraw.
    with rqr.requests():
        rqr.update_board(board_id)
    rqr.submit(rnd)

    # Get the image.
    img = rnd.get_png(board_id)
    logger.debug(f"retrieved the PNG image with {len(img)} bytes")

    # Return as PNG
    output = io.BytesIO(img)
    return output

# -------------------------------------------------------------------------------------------------
# Server
# -------------------------------------------------------------------------------------------------

async def process_requests(websocket):
    rqr = Requester()
    rnd = Renderer()
    created = False

    while True:
        try:
            msg = await websocket.recv()
            logger.debug("new message")
            msg = json.loads(msg)
            if 'set_session' in msg:
                uri = msg['set_session']['uri']
                st_name = msg['set_session']['spike_times']
                sd_name = msg['set_session']['spike_depths']
                t0 = msg['set_session'].get('start_time', 0)
                t1 = msg['set_session'].get('stop_time', 1)

                create(rqr, rnd, uri, st_name, sd_name, t0=t0, t1=t1)

            elif 'update_time' in msg:
                t0 = msg['update_time'].get('start_time', 0)
                t1 = msg['update_time'].get('stop_time', 1)

                update(rqr, rnd, uri, st_name, sd_name, t0=t0, t1=t1)

            img = render(rqr, rnd, 1)
            logger.debug(
                f"sending back the image with {img.getbuffer().nbytes} bytes...")
            img.seek(0)
            await websocket.send(img)
        except (websockets.ConnectionClosedOK, websockets.ConnectionClosedError):
            logger.debug("server connection closed")
            break
        except Exception as e:
            logger.error(traceback.format_exc())
            break
    logger.debug("server stopped")

async def server():
    async with websockets.serve(process_requests, "localhost", 1234, max_size=None):
        logger.info("Starting the websockets server")
        await asyncio.Future()  # run forever

# -------------------------------------------------------------------------------------------------
# Client
# -------------------------------------------------------------------------------------------------

async def set_session(websocket, uri, t0=0, t1=1):
    msg = {
        'set_session': {
            'uri': uri,
            'spike_times': SESSIONS[uri]['times'],
            'spike_depths': SESSIONS[uri]['depths'],
            'start_time': t0,
            'stop_time': t1,
        },
    }
    await websocket.send(json.dumps(msg))

async def update_time(websocket, t0=0, t1=1):
    msg = {
        'update_time': {
            'start_time': t0,
            'stop_time': t1,
        },
    }
    await websocket.send(json.dumps(msg))

async def recv_img(websocket, filename):
    logger.debug("client waiting for an incoming message...")
    buf = await websocket.recv()
    logger.info(f"received buffer with {len(buf)} bytes")
    with open(filename, 'wb') as f:
        f.write(buf)

async def client():
    async with websockets.connect("ws://localhost:1234", max_size=None) as websocket:
        try:
            logger.info("starting the websockets client")

            await set_session(websocket, DEFAULT_URI, t0=0, t1=100)
            await recv_img(websocket, 'img0.png')

            await update_time(websocket, t0=1000, t1=1010)
            await recv_img(websocket, 'img1.png')

            logger.info("stopping the websockets client")

        except Exception as e:
            logger.error(traceback.format_exc())

# -------------------------------------------------------------------------------------------------
# Entry-point
# -------------------------------------------------------------------------------------------------

if __name__ == "__main__":
    if len(sys.argv) <= 1 or sys.argv[-1] == 'server':
        asyncio.run(server())
    elif sys.argv[1] == 'client':
        asyncio.run(client())


import time
import subprocess
from pathlib import Path
import pyautogui as pag

p1 = Path.cwd() / 'attachments'

# 3초 뒤 timeLeft 종료
timeLeft = 3
while timeLeft > 0:
    print(timeLeft, end=' ')
    time.sleep(1)
    timeLeft -= 1

try:
    # subprocess.Popen() 함수 통해 알람파일 실행
    subprocess.Popen(['start', p1 / 'alarm.wav'], shell=True)
    # 3초 뒤
    time.sleep(3)
    # pyautogui.getWindwsWithTitle() 통해서 alarm창 객체 생성하고
    alarm = pag.getWindowsWithTitle('groove')[0]
    # 해당 창 종료
    alarm.close()
except:
    print('There is no file.')

print('Process Done!')


# ref. https://keras.io/api/applications/#usage-examples-for-image-classification-models

import tensorflow as tf
from keras.applications.mobilenet_v2 import MobileNetV2
import keras.utils as image
from keras.applications.mobilenet_v2 import preprocess_input, decode_predictions
import numpy as np

physical_devices = tf.config.experimental.list_physical_devices('GPU')
print("Num GPUs Available: ", len(physical_devices))
tf.config.experimental.set_memory_growth(physical_devices[0], True)

model = tf.keras.applications.MobileNetV2(
    input_shape=None,
    alpha=1.0,
    include_top=True,
    weights="imagenet",
    input_tensor=None,
    pooling=None,
    classes=1000,
    classifier_activation="softmax",
)

# img_path = 'example-bluePlayer.PNG'
img_path = 'example-livingRoom.jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

preds = model.predict(x)
# decode the results into a list of tuples (class, description, probability)
# (one such list for each sample in the batch)
print('Predicted:', decode_predictions(preds, top=3)[0])
# Predicted: [(u'n02504013', u'Indian_elephant', 0.82658225), (u'n01871265', u'tusker', 0.1122357), (u'n02504458', u'African_elephant', 0.061040461)]


import openai

import gradio

openai.api_key = " your api key here please"

messages = [{"role": "system", "content": "You are a financial experts that specializes in real estate investment and negotiation"}]

def CustomChatGPT(user_input):
    messages.append({"role": "user", "content": user_input})
    response = openai.ChatCompletion.create(
        model = "gpt-3.5-turbo",
        messages = messages
    )
    ChatGPT_reply = response["choices"][0]["message"]["content"]
    messages.append({"role": "assistant", "content": ChatGPT_reply})
    return ChatGPT_reply

demo = gradio.Interface(fn=CustomChatGPT, inputs = "text", outputs = "text", title = "my chatbot using chatGPT api")

demo.launch(share=True)


import os
import pickle
from datetime import datetime

from music_focus.processors.processor_base import ProcessorBase

class LoadResultProcessor(ProcessorBase):

    def __init__(self, data_dir='./data'):
        self._data_dir = data_dir

    def run(self, workflow_input, tmp_result, workflow_output):
        rtype = workflow_input['result_type']
        if rtype not in workflow_input:
            # 没加载过, 加载
            result_file_name = self._find_newest_result_file(self._data_dir, rtype,
                                                             '{}_%Y-%m-%d_%H:%M:%S.pkl'.format(rtype))
            workflow_input[rtype] = self._load_result(self._data_dir, result_file_name)
        else:
            # 加载过, 根据是否版本最新进行重载
            result_file_name = self._find_newest_result_file(self._data_dir, rtype,
                                                             '{}_%Y-%m-%d_%H:%M:%S.pkl'.format(rtype))
            if result_file_name != workflow_input[rtype]['file_name']:
                workflow_input[rtype] = self._load_result(self._data_dir, result_file_name)

    @staticmethod
    def _find_newest_result_file(dir_name, rtype, file_formatter):
        result_files = [f for f in os.listdir(dir_name) if rtype in f and 'pkl' in f]
        assert result_files is not [], "cant not find result file of {}".format(rtype)
        return max(result_files, key=lambda f: datetime.strptime(f, file_formatter))

    @staticmethod
    def _load_result(data_dir, result_file_name):
        with open('{}/{}'.format(data_dir, result_file_name), 'rb') as f:
            result = pickle.load(f)
        result['file_name'] = result_file_name
        return result


from typing import Iterable

def find_misspellings(words: Iterable[str]) -> None:
    """Checks for common misspellings of keys in scaaml dataset info file.

    Args:
      words: The words to check.

    Raises:
      ValueError: If spell_check_word raises.

    Example use:
      fixed_dict = {
        'licence': 'https://creativecommons.org/licenses/by/4.0/',
        'compression': 'GZIP',
      }
      find_misspellings(fixed_dict.keys())  # Check for misspellings of keys.
    """
    misspellings = [
        {
            'supported': 'licence',
            'unsupported': 'license',
        },
    ]
    for word in words:
        for misspelling in misspellings:
            spell_check_word(word, **misspelling, case_sensitive=False)

def spell_check_word(word: str,
                     supported: str,
                     unsupported: str,
                     case_sensitive: bool = False) -> None:
    """Checks if the word is spelled out as the unsupported, if so raises
    ValueError.

    Args:
      word: The word to check.
      supported: The supported spelling.
      unsupported: The spelling that is not supported.
      case_sensitive: Compare the words case sensitive.

    Raises:
      ValueError: If the word is equal to the unsupported one.
    """
    # Handle case insensitive comparison.
    word_cmp = word
    unsupported_cmp = unsupported
    if not case_sensitive:
        word_cmp = word.lower()
        unsupported_cmp = unsupported.lower()

    # Compare.
    if word_cmp == unsupported_cmp:
        raise ValueError(f'Unsupported spelling ({unsupported}) found, use '
                         f'{supported} instead.')


import cv2
import pafy

class source_http():
    def __init__(self, url):
        self.url = url
    def record(self):
        channel = pafy.new(self.url)
        streamPort = channel.getbest(preftype = 'mp4')
        videoSource = cv2.VideoCapture(streamPort.url)
        while True:
            ret, frame = videoSource.read()
            cv2.imshow('http', frame)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        videoSource.release()
        cv2.destroyAllWindows()


import os
import tempfile
import tensorflow_datasets as tfds
import tensorflow as tf
from keras.callbacks import ReduceLROnPlateau, EarlyStopping, ModelCheckpoint
from keras.engine.saving import load_model
from tensorflow_core.python import InteractiveSession, ConfigProto

# solved some issues with GPU
config = ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.3
session = InteractiveSession(config=config)

dataset, info = tfds.load('imdb_reviews/subwords8k', with_info=True,
                          as_supervised=True)

train_ds, test_ds = dataset['train'], dataset['test']

encoder = info.features['text'].encoder

BUFFER_SIZE = 10000
BATCH_SIZE = 8

padded_shapes = ([None], ())

# Shuffeling our dataset and giving it padded batching - This transformation combines multiple
# consecutive elements of the input dataset into a single element. as combines words into a sentence.
train_ds = train_ds.shuffle(BUFFER_SIZE).padded_batch(BATCH_SIZE,
                                                      padded_shapes=padded_shapes)
test_ds = test_ds.shuffle(BUFFER_SIZE).padded_batch(BATCH_SIZE,
                                                    padded_shapes=padded_shapes)

# Callbacks
# a path for the model.
model_dir = tempfile.gettempdir()
model_ver = 1.0
export_path = os.path.join(model_dir, str(model_ver))

# will create a file checkpoint for our model, it will overwrite it every run until we will find the best model
checkpoint = ModelCheckpoint('lstm.h5',
                             monitor='val_loss',  # monitor our progress by loss value.
                             mode='min',  # smaller loss is better, we try to minimize it.
                             save_best_only=True,
                             verbose=1)

# if our model accuracy (loss) is not improving over 3 epochs, stop the training, something is fishy
earlystop = EarlyStopping(monitor='val_loss',
                          min_delta=0,
                          patience=3,
                          verbose=1,
                          restore_best_weights=True
                          )

# if our loss is not improving, try to reduce learning rate
reduce_lr = ReduceLROnPlateau(monitor='val_loss',
                              factor=0.2,
                              patience=3,
                              verbose=1,
                              min_delta=0.0001)

callbacks = [checkpoint, earlystop, reduce_lr]

# Our Keras Sequential() model.
_model = tf.keras.Sequential([tf.keras.layers.Embedding(encoder.vocab_size, 64),
                              tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64, return_sequences=True)),
                              tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(32)),
                              tf.keras.layers.Dense(64, activation='elu'),
                              tf.keras.layers.Dense(1, activation='sigmoid')])
_model.summary()
_model.save('lstm.h5')
_model.compile(loss='binary_crossentropy',
               optimizer=tf.keras.optimizers.Adam(0.001),
               metrics=['accuracy'])
history = _model.fit(train_ds, epochs=10, validation_data=test_ds, validation_steps=30,
                     callbacks=callbacks)


#!/usr/bin/env python3

import subprocess
from datetime import datetime
import sys, os, re, pytz
import requests
import lxml.html
import argparse

terms = { '10': 'Fall', '20': 'Winter', '30': 'Spring', '40': 'Summer' }
snapshots_dir = 'all-snapshots'

def add_to_index(path):
    if os.path.exists(f'{snapshots_dir}/index.html'):
        index_file = f'{snapshots_dir}/index.html'
    else:
        index_file = 'snapshots_index.html'
    index = lxml.html.parse(index_file)
    ul = index.xpath('//ul')[0]
    snapshots_index = lxml.html.parse(os.path.join(path, 'index.html'))
    text = snapshots_index.xpath('//head/title/text()')[0].replace(': Snapshot taken', '')
    href = path[len(snapshots_dir)+1:]
    li = lxml.html.fromstring(f'
{text}
')
    ul.append(li)
    index.write(f'{snapshots_dir}/index.html', encoding='UTF-8', method='html')

def push_to_git():
    subprocess.run('git add .', cwd=snapshots_dir, shell=True)
    subprocess.run('git commit -m "added new snapshot at $(TZ=Hongkong date +%m-%d\\ %H:%M)"',
                   stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, cwd=snapshots_dir, shell=True)
    subprocess.run('git push', stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, cwd=snapshots_dir, shell=True)

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--url', default='https://w5.ab.ust.hk/wcq/cgi-bin/',
                        help='The start_url for crawler')
    parser.add_argument('-p', '--git-push', action='store_true',
                        help=f'Whether or not push all snapshots to a git repo. Note that the git repo should be set up at the directory {snapshots_dir}')
    args = parser.parse_args()
    start_url = args.url
    do_git_push = args.git_push

    r = requests.get(start_url)
    term_code = re.search(r'\d{4}', r.url).group()
    now = datetime.now(tz=pytz.timezone('Hongkong'))
    minute = '00' if now.minute < 30 else '30'
    path = '{}/20{}/{}/{}/{}'.format(snapshots_dir, term_code[:2], terms[term_code[2:]], now.strftime('%m/%d/%H'), minute)
    if os.path.exists(path):
        print('Pages already crawled')
        return
    res = subprocess.run('scrapy crawl snapshot -a start_url=%s' % start_url, shell=True)
    if res.returncode == 0:
        os.makedirs(path)
        subprocess.run(f'mv current-snapshot/* {path}', shell=True)
        add_to_index(path)
        if do_git_push:
            push_to_git()

if __name__ == '__main__':
    main()


from PIL import Image
import numpy
import os
import scipy.io as sio

def process_image(imagename, resultname, histeq=False,
                  params='--edge-thresh 10 --peak-thresh 5'):
  if not imagename.endswith('pgm') or histeq:
    im = Image.open(imagename).convert('L')
    if histeq:
      import imtools
      im = Image.fromarray(numpy.uint8(imtools.histeq(numpy.array(im))[0]))
    im.save('out_tmp.pgm')
    imagename = 'out_tmp.pgm'

  # Assumes that vlfeat's sift binary is in PATH.
  cmd = ' '.join(['sift', imagename, '--output=' + resultname, params])
  os.system(cmd)

  # Re-write as .mat file, which loads faster.
  f = numpy.loadtxt(resultname)
  sio.savemat(resultname + '.mat', {'f':f}, oned_as='row')

def read_features_from_file(filename):
  '''Returns feature locations, descriptors.'''
  f = sio.loadmat(filename + '.mat')['f']
  return f[:, :4], f[:, 4:]

def read_or_compute(imname, siftname, histeq=False):
  '''Returns features from 'siftname' if it exists. Else, computes features from
  'imname', writes them to 'siftname', and returns them.'''
  if not os.path.exists(siftname):
    process_image(imname, siftname, histeq=histeq)
  return read_features_from_file(siftname)

def plot_features(im, locs, circle=False):
  import pylab
  def draw_circle(c, r):
    t = numpy.arange(0, 1.01, .01) * 2 * numpy.pi
    x = r * numpy.cos(t) + c[0]
    y = r * numpy.sin(t) + c[1]
    pylab.plot(x, y, 'b', linewidth=2)
  pylab.imshow(im)
  if circle:
    for p in locs:
      draw_circle(p[:2], p[2])
  else:
    pylab.plot(locs[:, 0], locs[:, 1], 'ob')
  pylab.axis('off')

def match(desc1, desc2):
  desc1 = numpy.array([d / numpy.linalg.norm(d) for d in desc1])
  desc2 = numpy.array([d / numpy.linalg.norm(d) for d in desc2])

  dist_ratio = 0.6
  desc1_size = desc1.shape

  matchscores = numpy.zeros((desc1_size[0], 1), 'int')
  desc2t = desc2.T
  for i in range(desc1_size[0]):
    dotprods = numpy.dot(desc1[i, :], desc2t)
    dotprods = 0.9999 * dotprods

    # arccos is monotonous, can sort on just its sign.
    #indx = numpy.argsort(numpy.arccos(dotprods))
    indx = numpy.argsort(-dotprods)

    # Only keep best match if it's noticeably better than the next best match.
    if (numpy.arccos(dotprods)[indx[0]] <
        dist_ratio * numpy.arccos(dotprods)[indx[1]]):
      matchscores[i] = int(indx[0])

  return matchscores

def match_twosided(desc1, desc2):
  matches_12 = match(desc1, desc2)
  #return matches_12  # XXX doesn't seem to make things worse?
  matches_21 = match(desc2, desc1)

  ndx_12 = matches_12.nonzero()[0]
  for n in ndx_12:
    if matches_21[int(matches_12[n])] != n:
      matches_12[n] = 0
  return matches_12

def appendimages(im1, im2):
  return numpy.concatenate((im1, im2), axis=1)

def plot_matches(im1, im2, locs1, locs2, matchscores, show_below=True):
  import pylab
  im3 = appendimages(im1, im2)
  if show_below:
    im3 = numpy.vstack((im3, im3))

  pylab.imshow(im3)
  cols1 = im1.shape[1]
  for i, m in enumerate(matchscores):
    if m > 0:
      pylab.plot([locs1[i, 0], locs2[m, 0] + cols1],
                 [locs1[i, 1], locs2[m, 1]], 'c')
  pylab.axis('off')


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# HELICS documentation build configuration file, created by
# sphinx-quickstart on Wed Dec 13 12:07:08 2017.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))

# -- General configuration ------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
import os
import sphinx_rtd_theme
import shutil
import subprocess
import requests
import tempfile
import zipfile

current_directory = os.path.dirname(os.path.realpath(__file__))

def download_helics_images():
    print("Downloading doc images from GMLC-TDC/helics_doc_resources")
    with tempfile.TemporaryDirectory() as tmpdirname:
        url = "https://github.com/GMLC-TDC/helics_doc_resources/archive/refs/heads/main.zip"
        target_path = os.path.join(tmpdirname, "helics_docs_resources.zip")
        response = requests.get(url, stream=True)
        if response.status_code == 200:
            with open(target_path, "wb") as f:
                f.write(response.raw.read())
        with zipfile.ZipFile(target_path, "r") as zip_ref:
            zip_ref.extractall(tmpdirname)
        if os.path.exists("img"):
            shutil.rmtree("img")
        shutil.move(os.path.join(tmpdirname, "helics_doc_resources-main/user_guide"), "img")
    print("Doc images downloaded")

def which(program):
    def is_exe(fpath):
        return os.path.exists(fpath) and os.access(fpath, os.X_OK) and os.path.isfile(fpath)

    def ext_candidates(fpath):
        yield fpath
        for ext in os.environ.get("PATHEXT", "").split(os.pathsep):
            yield fpath + ext

    # fpath, fname = os.path.split(program)
    fpath = os.path.dirname(program)
    if fpath:
        if is_exe(program):
            return program
    else:
        for path in os.environ["PATH"].split(os.pathsep):
            exe_file = os.path.join(path, program)
            for candidate in ext_candidates(exe_file):
                if is_exe(candidate):
                    return candidate

    return None

read_the_docs_build = os.environ.get("READTHEDOCS", None) == "True"

# For RTD builds, only download the images once; for developers, always get the images
if not read_the_docs_build or not os.path.exists("img"):
    download_helics_images()

# For RTD builds run doxygen once for all output formats
if read_the_docs_build:
    dir_name = os.path.realpath(os.path.dirname(__file__))
    checkout_dir = os.path.realpath(os.path.join(dir_name, os.pardir))
    doxygen_build_dir = os.path.realpath(os.path.join(checkout_dir, "build-doxygen"))
    if not os.path.isdir(doxygen_build_dir):
        os.makedirs(os.path.join(doxygen_build_dir, "docs", "html"))
        subprocess.call(
            "cd {dir_name} && python ./scripts/render-doxyfile.py && doxygen Doxyfile;".format(
                dir_name=checkout_dir
            ),
            shell=True,
        )
    html_extra_path = [os.path.abspath(os.path.join(doxygen_build_dir, "docs", "html"))]

extensions = [
    "myst_parser",
    "sphinx.ext.autodoc",
    "sphinx.ext.doctest",
    "sphinx.ext.intersphinx",
    "sphinx.ext.coverage",
    "sphinx.ext.mathjax",
    "sphinx.ext.viewcode",
    "sphinx.ext.githubpages",
    "sphinx.ext.napoleon",
    "sphinxcontrib.rsvgconverter",
    "IPython.sphinxext.ipython_console_highlighting",
    "breathe",
    "sphinxcontrib.redoc",
    "sphinxcontrib.mermaid",
]

myst_enable_extensions = [
    "amsmath",
    "dollarmath",
]
myst_dmath_double_inline = True

breathe_projects = {
    "helics": os.path.abspath(os.path.join(current_directory, "./../build-doxygen/docs/xml")),
}

breathe_default_project = "helics"

# Add any paths that contain templates here, relative to this directory.
templates_path = []

# The master toctree document.
master_doc = "index"

# General information about the project.
project = "HELICS"
copyright = "2017-2021 Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause. Documentation source in https://github.com/GMLC-TDC/HELICS"
author = "Philip Top, Trevor Hardy, Ryan Mast, Dheepak Krishnamurthy, Andrew Fisher, Bryan Palmintier, Jason Fuller"

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = ""
# The full version, including alpha/beta/rc tags.
release = ""

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"

# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False

# redoc config
redoc = [
    {
        "name": "HELICS REST API",
        "page": "references/api-reference/rest_queries_api",
        "spec-root": "swagger/",
        "spec": "reference/queries.yaml",
        "embed": False,
    }
]

# mermaid config
# default js file priority is 500; require.js used by nbsphinx causes issues
# when it gets loaded first
mermaid_js_priority = 499

# -- Options for HTML output ----------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
#
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]

# Theme options are theme-specific and customize the look and feel of a theme
# further.  For a list of options available for each theme, see the
# documentation.
#
html_theme_options = {"navigation_depth": 4, "collapse_navigation": False}

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]

html_logo = "./logos/helics-logo-stacked-onWhite.png"
html_favicon = html_logo

# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# This is required for the alabaster theme
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
html_sidebars = {
    "**": [
        "about.html",
        "navigation.html",
        "relations.html",  # needs 'show_related': True theme option to display
        "searchbox.html",
        "donate.html",
    ]
}

# Adding last updated timestamp at the bottom of every page
html_last_updated_fmt = ""  # Empty string = '%b %d, %Y'

# -- Options for HTMLHelp output ------------------------------------------

# Output file base name for HTML help builder.
htmlhelp_basename = "HELICSdoc"

# -- Options for LaTeX output ---------------------------------------------

latex_elements = {
    # The paper size ('letterpaper' or 'a4paper').
    #
    # 'papersize': 'letterpaper',
    # The font size ('10pt', '11pt' or '12pt').
    #
    # 'pointsize': '10pt',
    # Additional stuff for the LaTeX preamble.
    #
    # 'preamble': '',
    # Latex figure (float) alignment
    #
    # 'figure_align': 'htbp',
}

# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
#  author, documentclass [howto, manual, or own class]).
latex_documents = [
    (
        master_doc,
        "HELICS.tex",
        "HELICS Documentation",
        "Philip Top, Trevor Hardy, Ryan Mast, Dheepak Krishnamurthy, Andrew Fisher, Bryan Palmintier, Jason Fuller",
        "manual",
    ),
]

# -- Options for manual page output ---------------------------------------

# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [(master_doc, "helics", "HELICS Documentation", [author], 1)]

# -- Options for Texinfo output -------------------------------------------

# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
#  dir menu entry, description, category)
texinfo_documents = [
    (
        master_doc,
        "HELICS",
        "HELICS Documentation",
        author,
        "HELICS",
        "Hierarchical Engine for Large-scale Infrastructure Co-Simulation",
        "Miscellaneous",
    ),
]

def setup(app):
    app.add_css_file("css/custom.css")  # may also be an URL


import pytest
import sys, time
from colorama import init, Fore, Style
init()

from lib.logger import Logger, Level
from lib.i2c_scanner import I2CScanner
from lib.enums import Orientation
from lib.matrix import Matrix

# ..............................................................................
@pytest.mark.unit
def test_matrix():

    _port_light = None
    _stbd_light = None

    _log = Logger('matrix-test', Level.INFO)

    try:

        _log.info(Fore.CYAN + 'start matrix test...')

        _i2c_scanner = I2CScanner(Level.DEBUG)
        if _i2c_scanner.has_address([0x77]): # port
            _port_light = Matrix(Orientation.PORT, Level.INFO)
            _log.info('port-side matrix available.')
        else:
            _log.warning('no port-side matrix available.')
        if _i2c_scanner.has_address([0x75]): # starboard
            _stbd_light = Matrix(Orientation.STBD, Level.INFO)
            _log.info('starboard-side matrix available.')
        else:
            _log.warning('no starboard-side matrix available.')

        if not _port_light and not _stbd_light:
            _log.warning('skipping test: no matrix displays available.')
            return

        if _port_light:
            _port_light.text('Y', False, False)
        if _stbd_light:
            _stbd_light.text('N', False, False)
        time.sleep(2)

        if _port_light:
            _port_light.disable()
            _port_light.clear()
        if _stbd_light:
            _stbd_light.disable()
            _stbd_light.clear()
        time.sleep(1)

        _log.info('matrix on...')
        if _port_light:
            _port_light.light()
        if _stbd_light:
            _stbd_light.light()
        time.sleep(2)

        if _port_light:
            _port_light.clear()
        if _stbd_light:
            _stbd_light.clear()
        time.sleep(1)

        _log.info('matrix gradient...')
        for x in range(3):
            for i in range(1,8):
                _log.info('matrix at {:d}'.format(i))
                if _port_light:
                    _port_light.gradient(i)
                if _stbd_light:
                    _stbd_light.gradient(i)
                time.sleep(0.01)
            if _port_light:
                _port_light.clear()
            if _stbd_light:
                _stbd_light.clear()
            time.sleep(0.1)

    except KeyboardInterrupt:
        _log.info(Fore.MAGENTA + 'Ctrl-C caught: interrupted.')
    finally:
        _log.info('closing matrix test...')
        if _port_light:
            _port_light.clear()
        if _stbd_light:
            _stbd_light.clear()

# call main ......................................

def main():

    test_matrix()

if __name__== "__main__":
    main()


import json
import math
import datetime
from pysubparser import parser
import click
import sys
import unicodedata
import re

def slugify(value, allow_unicode=False):
    """
    Taken from https://github.com/django/django/blob/master/django/utils/text.py
    Convert to ASCII if 'allow_unicode' is False. Convert spaces or repeated
    dashes to single dashes. Remove characters that aren't alphanumerics,
    underscores, or hyphens. Convert to lowercase. Also strip leading and
    trailing whitespace, dashes, and underscores.
    """
    value = str(value)
    if allow_unicode:
        value = unicodedata.normalize("NFKC", value)
    else:
        value = (
            unicodedata.normalize("NFKD", value)
            .encode("ascii", "ignore")
            .decode("ascii")
        )
    value = re.sub(r"[^\w\s-]", "", value.lower())
    return re.sub(r"[-\s]+", "-", value).strip("-_")

def get_microseconds(t):
    return (
        (t.hour * 3600 * 1000_000)
        + (t.minute * 60 * 1000_000)
        + (t.second * 1000_000)
        + t.microsecond
    )

@click.command()
@click.option("--sub-file", type=click.File("r"), required=True)
@click.option("--output-manifest-file", type=click.File("w"), required=True)
def cli(sub_file, output_manifest_file):
    subtitles = parser.parse(sub_file.name)

    output_json = []
    for subtitle in subtitles:
        start_time = get_microseconds(subtitle.start)
        end_time = get_microseconds(subtitle.end)
        length = end_time - start_time

        length_in_seconds = math.ceil(length / 1000_000)
        start_time_in_seconds = math.floor(start_time / 1000_000)

        clip_filename = f"{slugify(subtitle.text)}-{start_time_in_seconds}.mp4"
        output_json.append(
            {
                "start_time": start_time_in_seconds,
                "length": length_in_seconds,
                "rename_to": clip_filename,
                "title": subtitle.text,
            }
        )

    json.dump(output_json, output_manifest_file, indent=4, sort_keys=True)

if __name__ == "__main__":
    cli()


import torch
import torch.nn.functional as F
import numpy as np
import math

from src import utils
from src.noise import GammaNetwork, PredefinedNoiseSchedule
from src.dynamics_gvp import DynamicsWithPockets
#from torch_scatter import scatter_mean

class AREDM(torch.nn.Module):
    def __init__(
            self,
            dynamics: DynamicsWithPockets,
            lig_nf: int, # number of lig features (10)
            pocket_nf: int, # number of pocket features (25)
            n_dims: int, # number of position features
            timesteps: int=500,
            n_hier_steps=8, #
            noise_schedule='learned',
            noise_precision=1e-5,
            loss_type='l2',
            norm_values=(1., 4., 1.),
            norm_biases=(None, 0., 0.),
            anchors_context=True, #
            center_of_mass='anchors',
    ):
        super().__init__()
        if noise_schedule == 'learned':
            assert loss_type == 'vlb', 'A noise schedule can only be learned with vlb objective'
            self.gamma = GammaNetwork()
        else:
            self.gamma = PredefinedNoiseSchedule(noise_schedule, timesteps=timesteps, precision=noise_precision)

        self.dynamics = dynamics
        self.lig_nf = lig_nf
        self.pocket_nf = pocket_nf
        self.n_dims = n_dims
        self.T = timesteps
        self.hier_steps = n_hier_steps
        self.norm_values = norm_values
        self.norm_biases = norm_biases
        self.anchors_context = anchors_context
        self.center_of_mass = center_of_mass

    def forward(self, x, h, pocket_x, pocket_h, extension_mask, scaffold_mask, anchors, pocket_anchors, pocket_mask):
        """
        inputs:
            x: [B, N_l, 3] coordinates of molecules
            h: [B, N_l, lig_nf] features of moleucles
            extension_masks: [B, N_l] mask on extension atoms
            scaffold_masks: [B, N_l] mask on scaffold atoms
            anchors: [B, N_l] mask on anchor atoms
            pocket_x: [B, N_p, 3] coordinates of pocket
            pocket_h: [B, N_p, pocket_nf] features of pocket atoms
            pocket_mask: [B, N_p] masking on all the pocket atoms
            pocket_anchors: [B, N_p] masking on anchor atoms
        """
        # NOTE: the molecule is already at the center of mass of the extension at the current step
        x, h = self.normalize(x, h)
        pocket_x, pocket_h = self.normalize(pocket_x, pocket_h)

        num_nodes = x.shape[1] + pocket_x.shape[1]
        # volume change loss term
        delta_log_px = self.delta_log_px(num_nodes)
        # sample t
        t_int = torch.randint(0, self.T+1, size=(x.size(0), 1), device=x.device).float() # [B, 1]
        s_int = t_int - 1
        t = t_int / self.T
        s = s_int / self.T

        # masks for t=0 and t>0
        t_is_zero = (t_int==0).squeeze().float()
        t_is_not_zero = 1 - t_is_zero

        # compute gamma_t and gamma_s according to noise schedule
        gamma_t = self.inflate_batch_array(self.gamma(t), x)
        gamma_s = self.inflate_batch_array(self.gamma(s), x)

        xh = torch.cat([x, h], dim=2) # [B, N_l, h_l+3]
        pocket_xh = torch.cat([pocket_x, pocket_h], dim=2) # [B, N_p, h_p+3]

        # compute alpha_t, sigma_t from gamma
        alpha_t = self.alpha(gamma_t, x)
        sigma_t = self.sigma(gamma_t, x)

        # sample noise (only for extension part)
        eps_t = self.sample_combined_position_features_noise(n_samples=x.size(0), n_nodes=x.size(1), mask=extension_mask.unsqueeze(-1))
        # keep the scaffold part unchanged
        z_t = alpha_t * xh + sigma_t * eps_t
        z_t = xh * scaffold_mask.unsqueeze(-1) + z_t * extension_mask.unsqueeze(-1)

        eps_t_hat = self.dynamics.forward(
            xh=z_t, # zt has random at extension masks and real pos/feat at scaffold mask
            t=t, # timestep
            pocket_xh=pocket_xh,
            extension_mask=extension_mask,
            scaffold_mask=scaffold_mask,
            anchors=anchors,
            pocket_anchors=pocket_anchors,
            pocket_mask=pocket_mask, # [B, N_p]
        ) # [B, N_l, lig_nf+3] # prediction only for the extension part of ligand

        eps_t_hat = eps_t_hat * extension_mask.unsqueeze(-1) # prediction only for the extension part # [B, N, nf+3]
        # computing basic error (further used for computing NLL and L2 loss)
        error_t = (eps_t - eps_t_hat) ** 2 # [B, N, nf+3]
        error_t = self.sum_except_batch(error_t)

        normalization = (self.n_dims + self.lig_nf) * self.numbers_of_nodes(extension_mask)
        l2_loss = error_t / normalization
        l2_loss = l2_loss.mean()

        # KL between q(z_t|x) and p(z_T) = Normal(0,1)
        kl_prior = self.kl_prior(xh, num_nodes).mean()

        # computing NLL middle term
        SNR_weight = (self.SNR(gamma_s - gamma_t)-1).squeeze(1).squeeze(1)
        loss_term_t = self.T * 0.5 * SNR_weight * error_t
        loss_term_t = (loss_term_t * t_is_not_zero).sum() / t_is_not_zero.sum()

        # computing noise returned by dynamics
        noise = torch.norm(eps_t_hat, dim=[1,2])
        noise_t = (noise * t_is_not_zero).sum() / t_is_not_zero.sum()

        if t_is_zero.sum() > 0:
            # the _constants depending on sigma_0 from the cross ent term E_q(z0|x) [log p(x|z0)]
            neg_log_constants = -self.log_constant_of_p_x_given_z0(x, num_nodes)
            # compute L0 term (even if gamma_t is not actually gamma_0)
            # and selected only relevant via masking
            loss_term_0 = -self.log_p_xh_given_z0_without_constants(h, z_t, gamma_t, eps_t, eps_t_hat, extension_mask.unsqueeze(-1))
            loss_term_0 = loss_term_0 + neg_log_constants
            loss_term_0 = (loss_term_0 * t_is_zero).sum() / t_is_zero.sum()

            # computing noise returned by dynamics
            noise_0 = (noise * t_is_zero).sum() / t_is_zero.sum()
        else:
            loss_term_0 = 0.
            noise_0 = 0.

        return delta_log_px, kl_prior, loss_term_t, loss_term_0, l2_loss, noise_t, noise_0

    @torch.no_grad()
    def sample_chain_single_fragment(self, x, h, extension_mask, scaffold_mask, anchors, pocket_x, pocket_h, pocket_mask, pocket_anchors, lj_guidance=False, prot_mol_lj_rm=None, all_H_coords=None, guidance_weights=None, keep_frames=None):

        n_samples = x.size(0)
        n_nodes = x.size(1)

        x, h = self.normalize(x, h)
        pocket_x, pocket_h = self.normalize(pocket_x, pocket_h)

        xh = torch.cat([x,h], dim=2)
        pocket_xh = torch.cat([pocket_x, pocket_h], dim=2)

        # sampling from N(0,1)
        z = self.sample_combined_position_features_noise(n_samples, n_nodes, mask=extension_mask.unsqueeze(-1))

        z = xh * scaffold_mask.unsqueeze(-1) + z * extension_mask.unsqueeze(-1)

        if keep_frames is None:
            keep_frames = self.T
        else:
            assert keep_frames <= self.T

        chain = torch.zeros((keep_frames,) + z.size(), device=z.device) # [num_frames, num_samples, n_nodes, nf+3]
        # sample p(zs|zt)
        for s in reversed(range(0, self.T)):
            s_array = torch.full((n_samples,1), fill_value=s, device=z.device)
            t_array = s_array + 1
            s_array = s_array / self.T
            t_array = t_array / self.T

            z = self.sample_p_zs_given_zt_only_extension(
                s=s_array,
                t=t_array,
                z_t=z,
                pocket_xh=pocket_xh,
                extension_mask=extension_mask,
                scaffold_mask=scaffold_mask,
                anchors=anchors,
                pocket_anchors=pocket_anchors,
                pocket_mask=pocket_mask,
            )

            # Move back to center of mass again
            #if self.center_of_mass == 'anchors':
            #    anchor_pos = torch.zeros((n_samples,3), device=x.device)
            #    row1, col1 = torch.where(pocket_anchors)
            #    anchor_pos[row1] = pocket_x[row1, col1]

            #    row2, col2 = torch.where(anchors)
            #    anchor_pos[row2] = x[row2, col2]
            #    z[:,:,:3] = z[:,:,:3] - anchor_pos.unsqueeze(1) * node_masks.unsqueeze(-1)
            #    pocket_xh[:,:,:3] = pocket_x[:,:,:3] - anchor_pos.unsqueeze(1) * pocket_mask.unsqueeze(-1)

            # NOTE: we are not doing LJ guidance in the last 20 steps
            if lj_guidance and s < 400:
                with torch.enable_grad():
                    lig_x, lig_h = z[:, :, :self.n_dims], z[:, :, self.n_dims:]
                    lig_x.requires_grad = True

                    #h_ext.requires_grad = True
                    if extension_mask.sum() != 0:
                        lj_prot_lig = self.compute_lj(lig_x, lig_h, extension_mask, pocket_xh, pocket_mask, prot_mol_lj_rm=prot_mol_lj_rm, all_H_coords=all_H_coords)
                        lj_grad = torch.autograd.grad(lj_prot_lig, lig_x, retain_graph=True)[0] #
                        energy_prot_mol_lj = 0.3 * lj_grad * extension_mask.unsqueeze(-1) #
                        energy_total = energy_prot_mol_lj * guidance_weights[s]
                        z[:, :, :self.n_dims] = z[:, :, :self.n_dims] - energy_total

            write_index = (s * keep_frames) // self.T
            chain[write_index] = self.unnormalize_z(z)

        # finally sample p(x, h | z0)
        x_out , h_out = self.sample_p_xh_given_z0_only_extension(
            z_0=z,
            pocket_xh=pocket_xh,
            extension_mask=extension_mask,
            scaffold_mask=scaffold_mask,
            anchors=anchors,
            pocket_anchors=pocket_anchors,
            pocket_mask=pocket_mask
        )

        chain[0] = torch.cat([x_out, h_out], dim=2)
        return x_out, h_out, chain

    def compute_lj(self, lig_x, lig_h, extension_mask, pocket_xh, pocket_mask, prot_mol_lj_rm, all_H_coords):
        """ compute the LJ between protein and ligand
        lig_x: [B, N, 3]
        lig_h: [B, N, hf]
        """

        #lig_x.requires_grad = True
        B = extension_mask.shape[0]
        lj_prot_lig = torch.tensor(0., device=lig_x.device)

        n = 0
        for j in range(B):
            num_atoms = extension_mask[j].sum()
            if num_atoms == 0:
                continue # no extension atoms
            n += 1

            x = lig_x[j][extension_mask[j].bool()]  # [N_l, 3] # onlly extension atoms
            h = lig_h[j][extension_mask[j].bool()]  # [N_l, hf] # only extension atoms

            pocket_x = pocket_xh[j][pocket_mask[j].bool()][:, :self.n_dims] # [N_p, 3]
            pocket_h = pocket_xh[j][pocket_mask[j].bool()][:, self.n_dims:][:,:4] # [N_p, hf]
            h_coords = all_H_coords[j] # [N_p, 3]

            # --------------- compute the LJ between protein and ligand --------------
            dists = torch.cdist(x, pocket_x, p=2)
            dists = torch.where(dists<0.5, 0.5, dists)
            inds_lig = torch.argmax(h, dim=1) # [N_l]
            inds_pocket = torch.argmax(pocket_h, dim=1).long() # [N_p]

            rm = prot_mol_lj_rm[inds_lig][:, inds_pocket] # [N_l, N_p]
            lj = ((rm / dists) ** 12 - (rm / dists) ** 6) # [N_l, N_p]

            lj[torch.isnan(lj)] = 0

            lj = torch.clamp(lj, min=0, max=1000) # [N_l, N_p]

            # -------------  compute the loss for h atoms ----------------
            dists_h = torch.cdist(x, h_coords, p=2)
            dists_h = torch.where(dists_h<0.5, 0.5, dists_h)
            inds_H = torch.ones(len(h_coords), device=x.device).long() * 10 # index of H is 10 in the table
            rm_h = prot_mol_lj_rm[inds_lig][:, inds_H]
            lj_h = ((rm_h / dists_h) ** 12 - (rm_h / dists_h) ** 6) # [N_l, N_p]

            lj_h[torch.isnan(lj_h)] = 0 # remove nan values
            lj_h = torch.clamp(lj_h, min=0, max=1000) # [N_l, N_p]

            lj = lj.mean()
            lj_h = lj_h.mean()

            lj_prot_lig = (lj_prot_lig + (lj + lj_h))

        lj_prot_lig = lj_prot_lig / n

        return lj_prot_lig

    @staticmethod
    def get_batch_mask(mask, device):
        n_nodes = mask.float().sum(dim=1).int()
        batch_size = mask.shape[0]
        batch_mask = torch.cat([torch.ones(n_nodes[i]) * i for i in range(batch_size)]).long().to(device)
        return batch_mask

    def sample_p_zs_given_zt_only_extension(self, s, t, z_t, pocket_xh, scaffold_mask, extension_mask, anchors, pocket_anchors, pocket_mask):
        """ samples zs ~ p(zs|zt) only used during sampling. Samples only the extension features and coords """
        gamma_s = self.gamma(s)
        gamma_t = self.gamma(t)

        sigma2_t_given_s, sigma_t_given_s, alpha_t_given_s = self.sigma_and_alpha_t_given_s(gamma_t, gamma_s, z_t)
        sigma_s = self.sigma(gamma_s, target_tensor=z_t)
        sigma_t = self.sigma(gamma_t, target_tensor=z_t)

        eps_hat = self.dynamics.forward(
            xh=z_t,
            pocket_xh=pocket_xh,
            t=t,
            extension_mask=extension_mask,
            scaffold_mask=scaffold_mask,
            anchors=anchors,
            pocket_anchors=pocket_anchors,
            pocket_mask=pocket_mask,
        )

        eps_hat = eps_hat * extension_mask.unsqueeze(-1) # only the extension part is unmasked
        # compute mu for p(z_s|z_t) (algorithm 2 EDM)
        mu = z_t / alpha_t_given_s - (sigma2_t_given_s / alpha_t_given_s / sigma_t) * eps_hat

        # compute sigma for p(z_s | z_t) (alg 2)
        sigma = sigma_t_given_s * sigma_s / sigma_t

        # sample z_s given the params for z_t
        z_s = self.sample_normal(mu, sigma, extension_mask.unsqueeze(-1))
        z_s = z_t * scaffold_mask.unsqueeze(-1) + z_s * extension_mask.unsqueeze(-1) # [B, N, 3]

        return z_s

    def sample_p_xh_given_z0_only_extension(self, z_0, pocket_xh, scaffold_mask, extension_mask, anchors, pocket_anchors, pocket_mask):

        zeros = torch.zeros(size=(z_0.size(0),1), device=z_0.device)
        gamma_0 = self.gamma(zeros)

        # compute sqrt(sigma_0^2/alpha_0^2)
        sigma_x = self.SNR(-0.5 * gamma_0).unsqueeze(1)

        eps_hat = self.dynamics.forward(
                                    t=zeros,
                                    xh=z_0,
                                    pocket_xh=pocket_xh,
                                    extension_mask=extension_mask,
                                    pocket_mask=pocket_mask,
                                    scaffold_mask=scaffold_mask,
                                    anchors=anchors,
                                    pocket_anchors= pocket_anchors,
                                    )

        eps_hat = eps_hat * extension_mask.unsqueeze(-1)
        mu_x = self.compute_x_pred(eps_t=eps_hat, z_t=z_0, gamma_t=gamma_0)
        xh = self.sample_normal(mu=mu_x, sigma=sigma_x, node_mask=extension_mask.unsqueeze(-1))
        xh = z_0 * scaffold_mask.unsqueeze(-1) + xh * extension_mask.unsqueeze(-1)

        x, h = xh[:, :, :self.n_dims], xh[:, :, self.n_dims:]
        x, h = self.unnormalize(x, h)

        node_mask = (scaffold_mask.bool() | extension_mask.bool()).unsqueeze(-1).float()
        h = F.one_hot(torch.argmax(h, dim=2), self.lig_nf) * node_mask
        return x, h

    def kl_prior(self, xh, num_nodes):
        """
        computes the KL between q(z1|x) and prior p(z1) = Normal(0,1)
        This is essentially a lot of work for something that is in practice neglibible in the loss.
        However, you compute it so that you see it when you've made a mistake in your noise schedule
        """
        # compute the last alpha value, alpha_T
        ones = torch.ones((xh.size(0),1), device=xh.device)
        gamma_T = self.gamma(ones) # the last step
        alpha_T = self.alpha(gamma_T, xh) # the last step

        # compute the means
        mu_T = alpha_T * xh
        mu_T_x, mu_T_h = mu_T[:, :, :self.n_dims], mu_T[:, :, self.n_dims:]

        # compute standard devs (only batch axis for x-part, inflated for h-part)
        sigma_T_x = self.sigma(gamma_T, mu_T_x).view(-1) # remove inflate, only keep batch dim for x-part
        sigma_T_h = self.sigma(gamma_T, mu_T_h)

        # compute KL for h-part
        zeros, ones = torch.zeros_like(mu_T_h), torch.ones_like(sigma_T_h)
        kl_distance_h = self.gaussian_kl(mu_T_h, sigma_T_h, zeros, ones)

        # compute KL for x-part
        zeros, ones = torch.zeros_like(mu_T_x), torch.ones_like(sigma_T_x)
        d = self.subspace_dimensionality(num_nodes)
        kl_distance_x = self.gaussian_kl_for_dimension(mu_T_x, sigma_T_x, zeros, ones, d=d)

        return kl_distance_x + kl_distance_h

    def log_constant_of_p_x_given_z0(self, x, num_nodes):
        batch_size = x.size(0)
        degrees_of_freedom = self.subspace_dimensionality(num_nodes)
        zeros = torch.zeros((batch_size, 1), device=x.device)
        gamma_0 = self.gamma(zeros)

        # Recall that sigma_x = sqrt(sigma_0^2 / alpha_0^2) = SNR(-0.5 gamma_0)
        log_sigma_x = 0.5 * gamma_0.view(batch_size)
        return degrees_of_freedom * (-log_sigma_x - 0.5 * np.log(2 * np.pi))

    def log_p_xh_given_z0_without_constants(self, h, z_0, gamma_0, eps, eps_hat, mask, epsilon=1e-10):
        """ compute log(p(x,h)|z0) without constants
        log p(x|z_0) (no const) = -0.5 ||eps-eps_hat||^2
        log p(h|z_0) (no const) = CDF(h + 0.5 - z_0)/sigma_0 - CDF(h - 0.5 - z_0)/sigma_0
            need to be normalized across categories -> log_sum_exp
        mask: must be the extension_mask for atoms to be generated
        """
        z_h = z_0[:, :, self.n_dims:]

        # take only part of over x
        eps_x = eps[:, :, :self.n_dims]
        eps_hat_x = eps_hat[:, :, :self.n_dims]

        # compute sigma_0 and rescale to integer scale of data
        sigma_0 = self.sigma(gamma_0, target_tensor=z_0) * self.norm_values[1]

        # compute teh error for distribution N(x | 1/alpha_0 z_0 - sigma_0/alpha_0, sigma_0/alpha_0)
        # the weighting of eps parameterization is exactly 1 (eq 19 edm)
        # NOTE: for the next prediction hte previous parts of eps_x and eps_hat_x must be the same
        log_p_x_given_z_without_constants = -0.5 * self.sum_except_batch((eps_x - eps_hat_x) ** 2)

        # categorical features
        # compute delta indicator mask
        h = h * self.norm_values[1] + self.norm_biases[1]
        estimated_h = z_h * self.norm_values[1] + self.norm_biases[1]

        # centered h_cat around 1, since onehot encoded
        centered_h = estimated_h - 1

        # compute integral from 0.5 to 1.5 of normal dist
        log_p_h_proportioal = torch.log(
            self.cdf_standard_gaussian(((centered_h + 0.5)/sigma_0)) -  # TODO: check if mask is actually needed here
            self.cdf_standard_gaussian(((centered_h - 0.5)/sigma_0)) +
            epsilon
        )

        # normalize the distribution over categories
        log_Z = torch.logsumexp(log_p_h_proportioal, dim=2, keepdim=True)
        log_probabilities = log_p_h_proportioal - log_Z

        # select the log_prob of current category using onehot repr
        # mask is [B, N] boolean matrix
        log_p_h_given_z = self.sum_except_batch(log_probabilities * h * mask)

        # combine log probs for x and h
        log_p_xh_given_z = log_p_x_given_z_without_constants + log_p_h_given_z
        return log_p_xh_given_z

    def compute_x_pred(self, eps_t, z_t, gamma_t): # NOTE: may need a mask
        """ computes x_pred, i.e. the most likely prediction of x"""
        sigma_t = self.sigma(gamma_t, target_tensor=eps_t)
        alpha_t = self.alpha(gamma_t, target_tensor=eps_t)
        x_pred = 1. / alpha_t * (z_t - sigma_t * eps_t)
        return x_pred

    def sample_combined_position_features_noise(self, n_samples, n_nodes, mask):
        """ samples gaussian noise for both positions and features and then concatenates them
        uses node_mask on the noises
        """
        z_x = utils.sample_gaussian_with_mask(
            size=(n_samples, n_nodes, self.n_dims),
            device=mask.device,
            node_mask=mask
        )
        z_h = utils.sample_gaussian_with_mask(
            size=(n_samples, n_nodes, self.lig_nf),
            device=mask.device,
            node_mask=mask
        )
        z = torch.cat([z_x, z_h], dim=2)
        return z

    def sample_normal(self, mu, sigma, node_mask):
        """ Samples from a normal dist """
        eps = self.sample_combined_position_features_noise(mu.size(0), mu.size(1), node_mask)
        return mu + sigma * eps

    def normalize(self, x, h):
        new_x = x / self.norm_values[0]
        new_h = (h.float() - self.norm_biases[1]) / self.norm_values[1]
        return new_x, new_h

    def unnormalize(self, x, h):
        new_x = x * self.norm_values[0]
        new_h = h * self.norm_values[1] + self.norm_biases[1]
        return new_x, new_h

    def unnormalize_z(self, z):
        assert z.size(2) == self.n_dims + self.lig_nf
        x, h  = z[:, :, :self.n_dims], z[:, :, self.n_dims:]
        x, h  = self.unnormalize(x, h)
        return torch.cat([x,h], dim=2)

    def delta_log_px(self, num_nodes):
        return -self.subspace_dimensionality(num_nodes) * np.log(self.norm_values[0])

    def dimensionality(self, mask):
        return self.numbers_of_nodes(mask) * self.n_dims

    def sigma(self, gamma, target_tensor):
        """Computes sigma given gamma."""
        return self.inflate_batch_array(torch.sqrt(torch.sigmoid(gamma)), target_tensor)

    def alpha(self, gamma, target_tensor):
        """Computes alpha given gamma."""
        return self.inflate_batch_array(torch.sqrt(torch.sigmoid(-gamma)), target_tensor)

    def SNR(self, gamma):
        """Computes signal to noise ratio (alpha^2/sigma^2) given gamma."""
        return torch.exp(-gamma)

    def sigma_and_alpha_t_given_s(self, gamma_t: torch.Tensor, gamma_s: torch.Tensor, target_tensor: torch.Tensor):
        """
        Computes sigma t given s, using gamma_t and gamma_s. Used during sampling.
        These are defined as:
            alpha t given s = alpha t / alpha s,
            sigma t given s = sqrt(1 - (alpha t given s) ^2 ).
        """
        sigma2_t_given_s = self.inflate_batch_array(
            -self.expm1(self.softplus(gamma_s) - self.softplus(gamma_t)),
            target_tensor
        )

        # alpha_t_given_s = alpha_t / alpha_s
        log_alpha2_t = F.logsigmoid(-gamma_t)
        log_alpha2_s = F.logsigmoid(-gamma_s)
        log_alpha2_t_given_s = log_alpha2_t - log_alpha2_s

        alpha_t_given_s = torch.exp(0.5 * log_alpha2_t_given_s)
        alpha_t_given_s = self.inflate_batch_array(alpha_t_given_s, target_tensor)
        sigma_t_given_s = torch.sqrt(sigma2_t_given_s)

        return sigma2_t_given_s, sigma_t_given_s, alpha_t_given_s

    def subspace_dimensionality(self, input_size):
        """Compute the dimensionality on translation-invariant linear subspace
        where distributions on x are defined."""
        return (input_size - 1) * self.n_dims

    @staticmethod
    def numbers_of_nodes(mask):
        if len(mask.squeeze().shape) > 1:
            return torch.sum(mask.squeeze(), dim=1)
        else:
            return torch.sum(mask.squeeze())

    @staticmethod
    def inflate_batch_array(array, target):
         """ inflates teh batch array with only a single axis (i.e. shape = (batch_size,)
         or possibly more empty axes (batch_size, 1, ..., 1) to match the target)
         """
         target_shape = (array.size(0),) + (1,) * (len(target.size())-1)
         return array.view(target_shape)

    @staticmethod
    def sum_except_batch(x):
        return x.view(x.size(0), -1).sum(-1) # sum everyting except batch dimension

    @staticmethod
    def expm1(x):
        return torch.expm1(x)

    @staticmethod
    def softplus(x):
        return F.softplus(x)

    @staticmethod
    def cdf_standard_gaussian(x):
        """ Returns the cumulative distribution function (CDF) of gaussian """
        return 0.5 * (1 + torch.erf(x/math.sqrt(2)))

    @staticmethod
    def gaussian_kl(q_mu, q_sigma, p_mu, p_sigma):
        """
        Computes KL between two normal dists
        Args:
            q_mu: Mean of q
            q_sigma: std of q
            p_mu: mean of p
            p_sigma: std of p
        Returns:
            KL distance summed over all dims except the batch dim
        """
        kl = torch.log(p_sigma / q_sigma) + 0.5 * (q_sigma ** 2 + (q_mu - p_mu) **2) / (p_sigma ** 2) - 0.5
        return AREDM.sum_except_batch(kl)

    def subspace_dimensionality(self, input_size):
        """Compute the dimensionality on translation-invariant linear subspace
        where distributions on x are defined."""
        return (input_size - 1) * self.n_dims

    @staticmethod
    def gaussian_kl_for_dimension(q_mu, q_sigma, p_mu, p_sigma, d):
        """
        computes the KL between two normal dists taking the dimension into account
        Returns:
            KL distance summed over all dims except the batch dim
        """
        mu_norm_2 = AREDM.sum_except_batch((q_mu - p_mu) ** 2)
        return d * torch.log(p_sigma / q_sigma) + 0.5 * (d * q_sigma ** 2 + mu_norm_2) / (p_sigma ** 2) - 0.5 * d


bl_info = {
	"name": "Datablock Tools",
	"author": "Mackenzie Crawford, Vitor Balbio",
	"version": (2, 2, 1),
	"blender": (2, 80, 0),
	"location": "View3D > Object > Datablock Tools",
	"description": "Some tools to handle datablocks",
	"warning": "",
	"tracker_url": "",
	"category": "3D View"}

import bpy
import re

class CleanImagesOP(bpy.types.Operator):
	#replace the ".0x" images with the original and mark this to remove in next load
	bl_idname = "object.clean_images"
	bl_label = "Clean Images Datablocks"

	@classmethod
	def poll(cls, context):
		return context.selected_objects is not None

	def execute(self, context):
		ImageList = []
		#get full image name including extension
		for i in bpy.data.images:
			ImageList.append([i.name,i])

		for obj in bpy.context.selected_objects:
			for uv in obj.data.uv_textures.items():
				for faceTex in uv[1].data:
					if (not (faceTex.image is None)):
						image = faceTex.image

						if (bool(re.search(r'\.(\d){3}', image.name))): #if an image is set, and its name contains a . followed by 3 digits
							replaced = False
							for ima_name, ima in ImageList:
								if (image.name.startswith(ima_name) and (".0" not in ima_name)):
									faceTex.image.user_clear()
									faceTex.image = ima
									replaced = True
							if (replaced == False):
								#we didn't find a match, rename this one
								image.name = image.name.rsplit(".", 1)[0] #splits on the last . in the image name and returns the left part. Allows handling of names with multiple .s
		return {'FINISHED'}

class CleanMaterialsOP(bpy.types.Operator):
	#replace the ".0x" materials with the original and mark this to remove in next load
	bl_idname = "object.clean_materials"
	bl_label = "Clean Materials Datablocks"

	@classmethod
	def poll(cls, context):
		return context.selected_objects is not None

	def execute(self, context):
		matlist = bpy.data.materials
		for obj in bpy.context.selected_objects:
			for mat_slt in obj.material_slots:
				if (mat_slt.material != None and bool(re.search(r'\.(\d){3}', mat_slt.material.name))): #if a material is set, and its name contains a . followed by 3 digits
					replaced = False
					for mat in matlist:
						if ((mat.name == mat_slt.material.name.rsplit(".", 1)[0]) and (not bool(re.search(r'\.(\d){3}', mat.name)))):
							mat_slt.material = mat
							replaced = True
					if replaced == False:
						#we didn't find a match, rename this one
						mat_slt.material.name = mat_slt.material.name.rsplit(".", 1)[0] #splits on the last . in the material name and returns the left part. Allows handling of names with multiple .s
		return {'FINISHED'}

class RemoveAllMaterialsOP(bpy.types.Operator):
	#removes all materials from selected objects
	bl_idname = "object.remove_materials"
	bl_label = "Remove All Materials Datablocks"

	@classmethod
	def poll(cls, context):
		return context.selected_objects is not None

	def execute(self, context):
		for obj in bpy.context.selected_objects:
			#iterate through materials list and remove each sequentially
			obj.active_material_index = 0
			for i in range(len(obj.material_slots)):
				bpy.ops.object.material_slot_remove({'object': obj})
		return {'FINISHED'}

class DatablockToolsMenu(bpy.types.Menu):
	bl_label = "Datablock Tools"
	bl_idname = "VIEW_MT_datablock_tools"

	def draw(self, context):
		layout = self.layout

		layout.operator("object.clean_materials")
		layout.operator("object.remove_materials")
		layout.operator("object.clean_images")
		layout.operator("object.set_instance")

def draw_item(self, context):
	layout = self.layout
	layout.menu(DatablockToolsMenu.bl_idname)

classes = (CleanMaterialsOP, RemoveAllMaterialsOP, CleanImagesOP, DatablockToolsMenu)

def register():
	from bpy.utils import register_class
	for cls in classes:
		register_class(cls)

	bpy.types.VIEW3D_MT_object.append(draw_item)

def unregister():
	from bpy.utils import unregister_class
	for cls in reverse(classes):
		unregister_class(cls)

	bpy.types.VIEW3D_MT_object.remove(draw_item)

if __name__ == "__main__":
	register()


import os
import sys
import logging
import openerp
import openerp.netsvc as netsvc
import openerp.addons.decimal_precision as dp
from openerp.osv import fields, osv, expression, orm
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from openerp import SUPERUSER_ID, api
from openerp import tools
from openerp.tools.translate import _
from openerp.tools.float_utils import float_round as round
from openerp.tools import (DEFAULT_SERVER_DATE_FORMAT,
    DEFAULT_SERVER_DATETIME_FORMAT,
    DATETIME_FORMATS_MAP,
    float_compare)

_logger = logging.getLogger(__name__)

class ResPartner(orm.Model):
    """ Model name: ResPartner
    """

    _inherit = 'res.partner'

    def no_auto_address_field(self, cr, uid, ids, context=None):
        ''' Remove default for this partner
        '''
        assert len(ids) == 1, 'Works only with one record a time'

        address_ids = self.search(cr, uid, [
            ('parent_id', '=', ids[0]),
            ('is_address', '=', True),
            ('auto_address', '=', True),
            ], context=context)

        # Remove previous check:
        if address_ids:
            self.write(cr, uid, address_ids, {
                'auto_address': False,
                }, context=context)
        return True

    def set_auto_address_field(self, cr, uid, ids, context=None):
        ''' Set as default address for this partner
        '''
        assert len(ids) == 1, 'Works only with one record a time'

        current_proxy = self.browse(cr, uid, ids, context=context)[0]
        parent_id = current_proxy.parent_id.id
        address_ids = self.search(cr, uid, [
            ('parent_id', '=', parent_id),
            ('is_address', '=', True),
            ('auto_address', '=', True),
            ], context=context)

        # Remove previous check:
        if address_ids:
            self.write(cr, uid, address_ids, {
                'auto_address': False,
                }, context=context)

        # Write check on this:
        return self.write(cr, uid, ids, {
            'auto_address': True,
            }, context=context)

    _columns = {
        'auto_address': fields.boolean('Auto address',
            help='Set up as default oder address when choose this partner'),
    }

class SaleOrder(orm.Model):
    ''' Manage delivery in header
    '''
    _inherit = 'sale.order'

    # Override onchange for reset address name
    def onchange_partner_id(self, cr, uid, ids, part, context=None):
        res = super(SaleOrder, self).onchange_partner_id(
            cr, uid, ids, part, context=context)

        partner_pool = self.pool.get('res.partner')
        address_id = False
        if part:
            address_ids = partner_pool.search(cr, uid, [
                ('parent_id', '=', part),
                ('is_address', '=', True),
                ('auto_address', '=', True),
                ], context=context)
            if address_ids:
                address_id = address_ids[0]

        # Reset value if not present
        res['value']['destination_partner_id'] = address_id
        res['value']['invoice_partner_id'] = False
        return res
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:


from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
import pandas as pd
#set chromodriver.exe path
driver = webdriver.Chrome()
driver.implicitly_wait(0.5)
#launch URL
driver.get("http://www.google.com")

df = pd.read_csv('CollegeNames.csv')

my_list = []

def getUrls (college):
    element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, "q")))
    element.clear()
    element.send_keys(row + ' news')
    #print(row,'row')
    element.send_keys(Keys.ENTER)
    #result = driver.findElement(By.id("rso")).findElements(By.xpath("/*")).get(0).click()
    #result = driver.find_element(By.XPATH, '(//h3)[1]/a').click()
    #result = driver.find_element_by_class_name("iUh30")
    #result = driver.find_element_by_xpath('//*[@id="rso"]/div[1]/div/div/div/div[1]/a').get_attribute('href')
    results = driver.find_elements_by_css_selector('div.g')
    link = results[0].find_element_by_tag_name("a")
    result = link.get_attribute("href")
    #print(result,'result')
    my_list.append(result)
    #df["link"] = result
    #df.to_csv("CollegeNames.csv", index=False)
    #driver.quit()

for index, row in df.iterrows():
    time.sleep(10)
    getUrls(row)

#print(my_list,'mylist')
df['link'] = my_list
df.to_csv("CollegeNames.csv", index=False)

#details_lst = []
#print('df',df)
#for column in df.columns:
    #details_lst.append(df[column][1])
    #print('college',column)
    #element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, "q")))
    #element.send_keys(column)
    #element.send_keys(Keys.ENTER)
    #result = driver.find_element_by_class_name("iUh30").text
    #print(result,'result')


#!/usr/bin/env python
'''
Create template for new python/shell scripts to save some time.
'''
# pytlint: disable=missing-docstring
import argparse
import sys

from collections import namedtuple

class Argument(namedtuple('Argument', ['short', 'long', 'type', 'default'])):
    '''
    >>> a = Argument('j:job:int:4')
    >>> str(a)
    "    parser.add_argument(\\n\
        'j', 'job', type=int, default=4\\n\
    )"
    >>> a = Argument('j:job')
    >>> str(a)
    "    parser.add_argument(\\n        'j', 'job'\\n    )"
    '''
    def __new__(cls, string):
        arguments = string.split(':', 4)
        l = len(arguments)
        if l > 4:
            raise TypeError('Argument with more than 4 metas')
        arguments.extend([None] * (4 - l))
        return tuple.__new__(cls, arguments)

    def __repr__(self):
        tmpl = ['    parser.add_argument(']
        args = ["'%s'" % s for s in (self.short, self.long) if s]
        if self.type:
            args.append('type=%s' % self.type)
        if self.default:
            args.append('default=%s' % self.default)
        args = '        %s' % ', '.join(args)
        tmpl.extend([args, '    )'])
        return '\n'.join(tmpl)

def python_template(args):
    tmpl = [
        '#!/usr/bin/env python',
        "'''",
        "'''",
        '# pylint: disable=missing-docstring',
        'import argparse',
        'import sys',
        '', '',
        'def parse_args(argv):',
        '    parser = argparse.ArgumentParser(description=__doc__)',
    ]
    for a in args.args:
        tmpl.append(str(Argument(a)))
    tmpl.append('    return parser.parse_args(argv)')

    if not args.no_main:
        tmpl.extend([
            '', '',
            'def main(argv):',
            '    args = parse_args(argv)',
            '', '',
            "if __name__ == '__main__':",
            '    sys.exit(main(sys.argv[1:]))',
            ''
        ])

    with args.script_name as f:
        f.write('\n'.join(tmpl))

def add_python_options(subparser):
    parser = subparser.add_parser('python',
                                  help='Create template for a python script.')
    parser.add_argument(
        '--no-main', action='store_true',
        help="Doesn't create main function."
    )
    parser.add_argument(
        '--no-test', action='store_true',
        help="Doesn't create test script."
    )
    parser.add_argument(
        '-a', '--arg', dest='args', action='append',
        metavar='SHORT:LONG:TYPE:DEFAULT',
        help='arguments for the new script'
    )
    parser.add_argument(
        'script_name', metavar='SCRIPT_NAME', type=argparse.FileType('w'),
        help='script name (w/o ext name)'
    )
    parser.set_defaults(func=python_template)

def parse_args(argv):
    parser = argparse.ArgumentParser(description=__doc__)
    subparser = parser.add_subparsers()
    add_python_options(subparser)
    return parser.parse_args(argv)

def main(argv):
    args = parse_args(argv)
    args.func(args)

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


#!/usr/bin/python
# -*- coding: utf-8 -*-
__author__		= "HSC, GDT, MCU"
__date__		= "$March 8, 2011 12:02:34 PM$"
__version__		= "0.1.0.1"
__copyright__		= "Copytight 2011 %s" %__author__
__webpage__		= "http://code.google.com/p/gml/"

REPO = "http://www.infoiasi.ro/gml/repo.lst"
LOCAL_REPOSITORY = "repo.lst"

# === DO NOT MODIFY BELOW ===

import sys, os, re, hashlib, zipfile, shutil

if sys.version_info < (2, 6):
	raise("Not tested on this version of python. If you think it might work, please disable this check.")
	from urllib import urlretrieve
elif sys.version_info > (3, 0):
	from urllib.request import urlretrieve
else:
	from urllib import urlretrieve

from ctypes import *
from glob import glob
from time import strftime, localtime, sleep
from os.path import basename, dirname, isfile, exists, join
from os import makedirs
from os import name as OS_TYPE

plugin_data = {"algorithms":"alg", "connectors":"dbc", "databases":"db", "notifiers":"ntf"}

class OParse:
	__options = {}

	def __init__(self, argv, version):
		self.argv = argv
		self.version = version

		self.add_option('version', short_alias='-v', long_alias='--version', param_nr=0, help='Display version information and exit', callback=self.display_version)
		self.add_option('help', short_alias='-h', long_alias='--help', param_nr=0, help='Display commands and a description', callback=self.usage)

	def __is_short_opt(self, opt):
		if not opt.startswith("-") or len(opt) != 2:
			return ""
		for _opt in self.__options.keys():
			if self.__options[_opt].short_alias == opt.lower():
				return self.__options[_opt].__name__

	def __is_long_opt(self, opt):
		if not opt.startswith("--") or len(opt) < 4:
			return ""
		for _opt in self.__options.keys():
			if self.__options[_opt].long_alias == opt.lower():
				return self.__options[_opt].__name__

	def display_version(self, params):
		print("Version: %s" %self.version)

	def usage(self, params):
		from os.path import basename
		print("Usage: %s command [options]\n\nCommands:" %basename(self.argv[0]))
		options = [x for x in self.__options.keys()]
		options.sort()
		for opt in options:
			tmp_params = "0"
			if self.__options[opt].param_nr < 0:
				tmp_params = "variable number"
			else:
				if self.__options[opt].param_nr == 0:
					tmp_params = "None"
				else:
					tmp_params = str(self.__options[opt].param_nr)
			if self.__options[opt].accept_no_param:
				tmp_params += " (use with 0 parameters for more info)"
			print("  %s, %s, %s\n\tdescription: %s\n\tparameters: %s" %(
				self.__options[opt].__name__,
				self.__options[opt].short_alias,
				self.__options[opt].long_alias,
				self.__options[opt].help,
				tmp_params)
			)

	def add_option(self, name, short_alias="", long_alias="", param_nr=0, accept_no_param=False, help="", callback=None):
		name = name.lower()
		short_alias = short_alias.lower()
		long_alias = long_alias.lower()
		if name in self.__options.keys():
			raise NameError("Duplicate option: %s" %name)
		for argv in self.__options.keys():
			if self.__options[argv].short_alias == short_alias:
				raise NameError("Duplicate short alias: %s. Already used for '%s' option." %(short_alias, argv))
			if self.__options[argv].long_alias == long_alias:
				raise NameError("Duplicate long alias: %s. Already used for '%s' option." %(long_alias, argv))
		tmp_obj = type(
				name,
				(object,),
				{
					'callback':callback,
					'help':help,
					'short_alias':short_alias.lower(),
					'long_alias':long_alias.lower(),
					'param_nr':param_nr,
					'accept_no_param':accept_no_param
				}
			      )
		self.__options[name] = tmp_obj

	def parse(self):
		if len(sys.argv) == 1:
			self.usage([])
			return
		consumed = []
		for argv in self.argv[1:]:
			if argv in consumed:
				continue
			tmp = ""
			if not argv in self.__options.keys():
				tmp = self.__is_short_opt(argv)
				if tmp == "":
					tmp = self.__is_long_opt(argv)
				if tmp == "" and not tmp is None:
					print("Unknown option: %s" %argv)
					return
				else:
					argv = tmp
			opt = self.__options[argv]
			if opt.param_nr == -1:
				opt.param_nr = len(self.argv) - 2
			if len(self.argv) < 2 + opt.param_nr and not opt.accept_no_param: #FIXME
				print("[ERROR] Expecting %d parameters" %opt.param_nr)
				return
			if not opt.callback is None:
				opt.callback(self.argv[2:2+opt.param_nr])
			else:
				print("[WARN] No callback function for '%s' option set!" %argv)
			consumed += (self.argv[:2+opt.param_nr])
			break #FIXME: allows only one command at a time
		if len(consumed) != len(self.argv):
			print("Some options did not get parsed") #TODO: add what options

def md5sum(filePath):
	md5 = hashlib.md5()
	file = open(filePath, "rb")
	while True:
		data = file.read(8192)
		if not data:
			break
		md5.update(data)
	file.close()
	return md5.hexdigest()

def __add_to_path(path):
	if OS_TYPE == 'nt':
		from winreg import CreateKey, SetValueEx, QueryValueEx, HKEY_CURRENT_USER, REG_EXPAND_SZ
		from win32gui import SendMessage
		from win32con import HWND_BROADCAST, WM_SETTINGCHANGE
		envpath = None
		HKCU = HKEY_CURRENT_USER
		ENV = "Environment"
		PATH = "PATH"
		DEFAULT = "%PATH%"
		with CreateKey(HKCU, ENV) as key:
			try:
				envpath = QueryValueEx(key, PATH)[0]
			except WindowsError:
				envpath = DEFAULT
			paths = [envpath]
			if path and path not in envpath and os.path.isdir(path):
					paths.append(path)
			envpath = os.pathsep.join(paths)
			try:
				SetValueEx(key, PATH, 0, REG_EXPAND_SZ, envpath)
				SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 'Environment')
			except WindowsError:
				return False
			return True
	else:
		return False

def __add_to_pypath(path):
	if OS_TYPE == 'nt':
		from winreg import CreateKey, SetValueEx, QueryValueEx, HKEY_LOCAL_MACHINE, REG_SZ
		envpath = ""
		HKLM = HKEY_LOCAL_MACHINE
		PythonPath = r"SOFTWARE\Python\PythonCore\%s\PythonPath" %sys.version.split()[0] #FIXME: 3.1.3 --> 3.1
		with CreateKey(HKLM, PythonPath) as key:
			try:
				envpath = QueryValueEx(key, "")[0]
			except WindowsError:
				return False
			paths = [envpath]
			if path and path not in envpath and os.path.isdir(path):
					paths.append(path)
			envpath = os.pathsep.join(paths)
			try:
				SetValueEx(key, "", 0, REG_SZ, envpath)
			except WindowsError:
				return False
			return True
	else:
		return False

def add_to_path(path):
	cm = ConsoleMessages()
	cm.print_msg("\n[Registry operations]")
	if not __add_to_path(path):
		cm.print_error("Could not add GML root dir to PATH")
		exit(1)
	else:
		cm.print_msg("  [ -- ] Done adding GML root dir to PATH. Changes will be\n  visible in a new command line")
	#if not __add_to_pypath(path):
	#	cm.print_error("Could not add GML root dir to PYTHONPATH")
	#	exit(1)
	#else:
	#	cm.print_msg("  [ -- ] Done adding GML root dir to PYTHONPATH")

class Plugin:
	__no_data = b"No data set"

	def __init__(self, plg_name):
		self.plg_name = plg_name
		self.__cm = ConsoleMessages()
		try:
			self.dll = CDLL(self.plg_name)
		except:
			self.__cm.print_error("Could not load plugin: %s" %self.plg_name)

	def get_author(self):
		author = c_char_p(self.__no_data)
		try:
			author = c_char_p(self.dll.GetInterfaceAuthor())
		except:
			pass
		if author.value is None or author.value == "":
			return self.__no_data.decode('ascii')
		else:
			return author.value.decode('ascii')

	def get_description(self):
		description = c_char_p(self.__no_data)
		try:
			description = c_char_p(self.dll.GetInterfaceDescription())
		except:
			pass
		if description.value is None or description.value == "":
			return self.__no_data.decode('ascii')
		else:
			return description.value.decode('ascii')

	def get_version(self, ret_type=str):
		version = c_int(0)
		try:
			version = c_int(self.dll.GetInterfaceVersion())
		except:
			pass
		if version.value is None or version.value == 0:
			return self.__no_data
		else:
			return version.value

	def get_properties(self):
		tmp_fname = b"~prop.tmp"
		ret = "\n"
		ready = c_bool(False)
		try:
			ready = c_bool(self.dll.SaveInterfaceTemplate(c_char_p(tmp_fname)))
		except:
			pass
		if ready:
			RFILE = None
			lines = []
			try:
				RFILE = open(tmp_fname, "rt")
				lines = RFILE.readlines()
			except:
				pass
			finally:
				if RFILE != None:
					RFILE.close()
				if os.path.isfile(tmp_fname):
					try:
						os.remove(tmp_fname)
					except:
						pass
			ignore = False
			for line in lines:
				line = line.strip();
				if len(line) == 0:
					continue
				if line.startswith("["):
					ignore = True
				if line.endswith("]"):
					ignore = False
					continue
				if ignore:
					continue
				ret += "\t" + line + "\n"
		return ret

class ConsoleMessages:
	def __source_info(self):
		return sys._getframe(2).f_code.co_filename, sys._getframe(2).f_lineno, sys._getframe(2).f_code.co_name

	def __timestamp(self):
		return strftime("%d %b %Y %H:%M:%S", localtime())

	def print_error(self, msg):
		fname, line, func = self.__source_info()
		print("[ERROR]\n   Message\t: %s\n   Source\t: %s:%d::%s\n   Timestamp\t: %s" %(msg, fname, line, func, self.__timestamp()))
		return False

	def print_msg(self, msg):
		print(msg)

class unzip:
	cm = None
	def __init__(self, verbose = False, percent = 10):
		self.verbose = verbose
		self.percent = percent
		self.cm = ConsoleMessages()

	def __makedirs(self, fname, basedir):
		directories = self.__listdirs(fname)
		for dname in directories:
			curdir = join(basedir, dname).replace("/","")
			if not exists(curdir):
				try:
					makedirs(curdir)
				except:
					return self.cm.print_error("Could not create directory: \"%s\"" %curdir)
		return True

	def __listdirs(self, fname):
		zf = zipfile.ZipFile(fname)
		dirs = []
		for name in zf.namelist():
			if name.endswith('/'):
				dirs.append(name)
		dirs.sort()
		return dirs

	def extract(self, fname, root):
		if not isfile(fname):
			return self.cm.print_error("File doesn't exist: \"%s\"" %fname)

		if not root.endswith(':') and not exists(root):
			try:
				makedirs(root)
			except:
				return cm.print_error("Could not make root directory: \"%s\"" %root)

		zf = zipfile.ZipFile(fname)
		if zf.testzip() != None:
			return self.cm.print_error("Invalid zip archive: \"%s\"" %fname)

		zf.extractall(path=root)
		return True

class Downloader:
	repository = None
	cm = None
	root = ""
	lrepo_file = ""

	def __init__(self, repository=None, root=""):
		self.repository = repository
		self.root = root
		self.lrepo_file = join(self.root, LOCAL_REPOSITORY)
		self.cm = ConsoleMessages()

	def __report_hook(self, numblocks, blocksize, filesize, dest):
		try:
			percent = min((numblocks*blocksize*100)/filesize, 100)
		except:
			percent = 100
		if numblocks != 0:
			sys.stdout.write("\b"*70)
			sys.stdout.write("  [%3d%%] %-61s" % (percent, dest))

	def update(self):
		self.cm.print_msg("[Update process]")
		ret = True
		if self.repository == None:
			return False
		if not self.download(self.repository, self.lrepo_file):
			return False
		if isfile(self.lrepo_file):
			RFILE = None
			lines = []
			try:
				RFILE = open(self.lrepo_file)
				lines = RFILE.readlines()
			except:
				return False
			finally:
				if RFILE != None:
					RFILE.close()
			for line in lines:
				line = line.strip()
				if len(line) == 0 or line.startswith("#"):
					continue
				sline = line.split("|")
				if len(sline) != 4:
					return self.cm.print_error("Invalid line in repo.lst: \"%s\". Update/Install will not continue" %line)
				if sline[0].startswith("action="):
					action = sline[0].split("=")[-1]
					if action == "get":
						fname = join(self.root, sline[2])
						if isfile(fname):
							if sline[3] != md5sum(fname):
								ret &= self.download(sline[1], fname)
							else:
								sys.stdout.write("  [ -- ] %-61s [OK]\n" %fname)
						else:
							ret &= self.download(sline[1], fname)
					elif action == "inflate":
						unz = unzip()
						sys.stdout.write("Inflating %s ..." %sline[1])
						if not unz.extract(join(self.root, sline[1]), join(self.root, sline[2])):
							return False
						sys.stdout.write("\b"*70)
						sys.stdout.write("  [ -- ] Inflating %-51s [OK]\n" %fname)
					else:
						return self.cm.print_error("Unknown action from repository file: \"%s\". Will not continue" %action)
				else:
					return self.cm.print_error("Unknown repository format")
		else:
			ret = False
		return ret

	def download(self, src, dest):
		sys.stdout.write("Download: " + src)
		if not exists(dirname(dest)):
			try:
				makedirs(dirname(dest))
			except:
				return self.cm.print_error("Could not create target dir: \"%s\"" %dirname(dest))
		try:
			if sys.stdout.isatty():
				urlretrieve(src, dest, lambda nb, bs, fs, dst=dest: self.__report_hook(nb, bs, fs, dst))
			else:
				urlretrieve(src, dest)
		except:
			sys.stdout.write(" [ERROR]\n")
			return False
		else:
			sys.stdout.write(" [OK]\n")
		return True

class ActionHandler:
	def __init__(self, root):
		self.__cm = ConsoleMessages()
		self.__root = os.path.dirname(root)

	def handle_install(self, params):
		if os.path.exists(params[0]):
			if os.path.isfile(params[0]):
				self.__cm.print_error("Installation directory exists and it is a file. Install aborted")
				return False
		else:
			try:
				os.makedirs(params[0])
			except:
				self.__cm.print_error("Could not create %s. Please check is user has enough rights" %params[0])
				return False
		self.__install_root = params[0]
		d = Downloader(repository=REPO, root=params[0])
		if not d.update():
			self.__cm.print_error("Could not update GML")
			return False
		add_to_path(params[0])
		try:
			shutil.copyfile(os.path.join(self.__install_root, "gmllib.py"), os.path.join(sys.prefix, "Lib\\gmllib.py"))
		except:
			self.__cm.print_error("Could not copy 'gmllib.py' to %s" %(os.path.join(sys.prefix, "Lib")))
		WFILE = None
		try:
			WFILE = open(os.path.join(sys.prefix, "Lib\\gmllib.py"), "wt")
			WFILE.write("""import sys
sys.path.append(r'%s')
from attributelist import *
from ialgorithm import *
from builder import *
""" %os.path.join(self.__install_root, "Python"))
			WFILE.close()
		except:
			self.__cm.print_error("Could not modify 'gmllib.py'")
		try:
			shutil.move(os.path.join(self.__install_root, "gmllib.py"), os.path.join(self.__install_root, "gmllib.py.bak"))
		except:
			pass
		self.__cm.print_msg("== Done ==")

	def handle_list(self, params, show_info=False):
		if len(params) == 0:
			self.__cm.print_msg("Posible parameters:")
			for elem in plugin_data.keys():
				self.__cm.print_msg("  %s" %elem)
		else:
			param = params[0].lower()
			err = True
			for lparam in [x.lower() for x in plugin_data.keys()]: #FIXME: beautifie code
				for found in re.findall(param, lparam):
					found = found.lower()
					if found in [x.lower() for x in plugin_data.keys()]:
						err = False
						for fname in glob(os.path.join(os.path.join(self.__root, found), "*." + plugin_data[found])):
							self.__cm.print_msg("%s" %os.path.basename(fname).split(".")[0])
							if show_info:
								plugin = Plugin(fname)
								self.__cm.print_msg("  Author: %s\n  Version: %d\n  Description: %s\n  Properties: %s\n" %(plugin.get_author(), plugin.get_version(), plugin.get_description(), plugin.get_properties()))
			if err:
				self.__cm.print_msg("Unknown parameter for 'list' command: %s" %param)
				return

	def handle_info(self, params):
		if len(params) < 2:
			self.handle_list(params, show_info=True)

if __name__ == '__main__':
	action_handler = ActionHandler(sys.argv[0])
	optparse = OParse(sys.argv, "0.1.0.1")
	optparse.add_option('info',
				short_alias='-i',
				long_alias='--info',
				param_nr=-1,
				accept_no_param=True,
				help='Display a description for the given plugins',
				callback=action_handler.handle_info)
	optparse.add_option('list',
				short_alias='-l',
				long_alias='--list',
				param_nr=1,
				accept_no_param=True,
				help='List available options for given pattern',
				callback=action_handler.handle_list)
	optparse.add_option('install',
				long_alias='--install',
				param_nr=1,
				help='Install GML',
				callback=action_handler.handle_install)
	optparse.parse()


from django.shortcuts import render
from django.http import HttpResponseRedirect
from .forms import paymentForm
from django.contrib.auth.models import User
from accounts.models import Activation
from django import forms
from django_messages.forms import ComposeForm
from django.contrib import messages
from django.utils.translation import gettext as _
from django.core.files.base import ContentFile, File
from django.core.exceptions import ObjectDoesNotExist

def payment(request, template_name='payment.html', form_class=ComposeForm):

    ctx = {}
    form = paymentForm()
    ctx['form'] = form

    if request.method == 'POST':
        form_payment = paymentForm(request.POST)
        if form_payment.is_valid():
            recipient_UWP = form_payment.cleaned_data['address']

        form = form_class(request.POST)
        if form.is_valid():
            sender = User.objects.get(username='webshopPondersourceNet')

            xml_type = 'invoice'

            via = request.POST['via']

            if via=='AS4':
                peppol_classic = False
            else:
                peppol_classic = True

            try:
                recipient = Activation.objects.get(webID=recipient_UWP)
                if peppol_classic:
                    ctx['form'] = form_class(initial={"subject": request.GET.get("subject", "")})
                    messages.info(request, _(u"You can't send a new message to a WEebID through Peppol classic "))
                    return render(request, template_name, ctx)
                recipient_username = recipient.user.username
                recipient = User.objects.get(username=recipient_username)
            except ObjectDoesNotExist:
                try:
                    recipient = Activation.objects.get(peppolID=recipient_UWP)
                    recipient_username = recipient.user.username
                    recipient = User.objects.get(username=recipient_username)
                except ObjectDoesNotExist:
                    try:
                        recipient = User.objects.get(username=recipient_UWP)
                        recipient_username = recipient.username
                    except ObjectDoesNotExist as e:
                        ctx["errors"] = ["%s" % e]
                        return render(request, template_name, ctx )

            recipient = User.objects.get(pk=recipient.pk)
            sender = User.objects.get(username='webshopPondersourceNet')
            form.save(sender=sender , recipient=recipient , xml_type=xml_type, peppol_classic = peppol_classic)
            messages.info(request, _(u"Invoice successfully sent."))
            return HttpResponseRedirect('/')

    return render(request,template_name,ctx)


import os
import sys

from argparse import ArgumentParser

def convert_to_video(folder, zfill_num, image_format, output_video_fname, output_video_fps, speed=1):
    print('trying to create the output file..')
    try:
        image_pattern = "%0{0}d.{1}".format(zfill_num, image_format)
        # ffmpeg = f"ffmpeg -i {folder}/{image_pattern} -c:v libx264 -vf fps={output_video_fps} -pix_fmt yuv420p {output_video_fname}"

        # Normal speed video with one image per frame
        ffmpeg = f"ffmpeg -r {speed} -i {folder}/{image_pattern} -c:v libx264 -framerate {output_video_fps} -pix_fmt yuv420p {output_video_fname}"
        os.system(ffmpeg)
    except:
        print('Something went wrong. try manually.')
        pass
    print("End of program")

if __name__ == "__main__":

    # if len(sys.argv) < 2:
    #     print('Please specify folder')
    #     sys.exit(0)
    # folder = sys.argv[1]
    parser = ArgumentParser()
    parser.add_argument(
        "folder", help="The folder with data", type=str)
    parser.add_argument("--fps", help="Video output fps", type=int, default=25)
    parser.add_argument("--zfill", help="Images zfill number", type=int, default=7)
    parser.add_argument("--speed", help="Relative speed of video. i.e. how many frames per second", type=str, default="1")
    args = parser.parse_args()

    folder = args.folder
    files = [f for f in os.listdir(
        folder) if os.path.isfile(os.path.join(folder, f))]
    zfill_num = args.zfill  # with zfill = 7, the max frame num is 9,999,999; should be enough
    output_video_fps = args.fps
    folder_id = folder.split('frames_')[1].replace(os.sep, '')
    output_video_fname = f"out_{folder_id}.mp4"
    speed = args.speed

    num_files = len(files)
    if num_files > 0:
        image_format = files[0].split('.')[-1]
        convert_to_video(folder, zfill_num, image_format,
                         output_video_fname, output_video_fps, speed)
        print('Done')
    else:
        print(f'Found {num_files} files, aborting.')