# Notebook from FPreta/pyfiction
Path: pyfiction/examples/generalisation/Generalisation_U_P_LSTM.ipynb

<code>
import argparse
import logging
import string
logging.basicConfig(filename = 'U_P_LSTM_Generalisation.txt', filemode='w', level=logging.INFO)

from keras.optimizers import RMSprop
from keras.utils import plot_model
from pyfiction.agents.ssaqn_agent import SSAQNAgent
from pyfiction.simulators.games.catsimulator2016_simulator import CatSimulator2016Simulator
from pyfiction.simulators.games.machineofdeath_simulator import MachineOfDeathSimulator
from pyfiction.simulators.games.savingjohn_simulator import SavingJohnSimulator
from pyfiction.simulators.games.starcourt_simulator import StarCourtSimulator
from pyfiction.simulators.games.theredhair_simulator import TheRedHairSimulator
from pyfiction.simulators.games.transit_simulator import TransitSimulator
from pyfiction.simulators.text_games.simulators.MySimulator import StoryNode

logger = logging.getLogger(__name__)

"""
An SSAQN agent that supports leave-one-out generalisation testing
"""

simulators = [CatSimulator2016Simulator(),
              MachineOfDeathSimulator(),
              SavingJohnSimulator(),
              StarCourtSimulator(),
              TheRedHairSimulator(),
              TransitSimulator()]
test_steps = [
    1,
    5,
    1,
    5,
    1,
    1
]

simulator_index = 1

if simulator_index == 0:
    train_simulators = simulators
    test_simulators = simulators
    print('Training and testing on all games:', [simulator.game.name for simulator in simulators])
else:
    train_simulators = simulators[:simulator_index - 1] + simulators[simulator_index:]
    test_simulators = simulators[simulator_index - 1]
    test_steps = test_steps[simulator_index - 1]
    print('Training on games:', [simulator.game.name for simulator in train_simulators])
    print('Testing on game:', test_simulators.game.name)

# Create the agent and specify maximum lengths of descriptions (in words)
agent = SSAQNAgent(train_simulators=train_simulators, test_simulators=test_simulators,mode='LSTM')

# Load or learn the vocabulary (random sampling on this many games could be extremely slow)
agent.initialize_tokens('vocabulary.txt')

optimizer = RMSprop(lr=0.00001)

embedding_dimensions = 300
lstm_dimensions = 32
dense_dimensions = 8

agent.create_model(embedding_dimensions=embedding_dimensions,
                   lstm_dimensions=lstm_dimensions,
                   dense_dimensions=dense_dimensions,
                   optimizer=optimizer,
                  embeddings=None,
                  embeddings_trainable=False)

# Visualize the model
try:
    plot_model(agent.model, to_file='model.png', show_shapes=True)
except ImportError as e:
    logger.warning("Couldn't print the model image: {}".format(e))

# Iteratively train the agent on five out of the six games or on all six games
# This example seems to converge to the optimal reward in all games but Star Court  when training on all games
epochs = 1
for i in range(epochs):
    logger.info('Epoch %s', i)
    agent.train_online(episodes=256, batch_size=64, gamma=0.95, epsilon=1, epsilon_decay=0.99,
                       prioritized_fraction=0.25, test_interval=16, test_steps=test_steps,
                       log_prefix=str(simulator_index))

# Transfer learning test - train the agent on the previously unseen (only used for testing) game
if simulator_index != 0:
    agent.clear_experience()
    agent.train_simulators = test_simulators if isinstance(test_simulators, list) else [test_simulators]
    agent.train_online(episodes=256, batch_size=64, gamma=0.95, epsilon=1, epsilon_decay=0.99,
                       prioritized_fraction=0.25, test_interval=16, test_steps=test_steps,
                       log_prefix=('transfer' + str(simulator_index)))
Training on games: ['Machine Of Death', 'Saving John', 'Star Court', 'The Red Hair', 'Transit']
Testing on game: Cat Simulator 2016
---------------
Complete model:
____________________________________________________________________________________________________
Layer (type)                     Output Shape          Param #     Connected to
====================================================================================================
input_state (InputLayer)         (None, None)          0
____________________________________________________________________________________________________
input_action (InputLayer)        (None, None)          0
____________________________________________________________________________________________________
embedding_shared (Embedding)     (None, None, 300)     1670400     input_state[0][0]
                                                                   input_action[0][0]
____________________________________________________________________________________________________
lstm_shared (LSTM)               (None, 32)            42624       embedding_shared[0][0]
                                                                   embedding_shared[1][0]
____________________________________________________________________________________________________
dense_state (Dense)              (None, 8)             264         lstm_shared[0][0]
____________________________________________________________________________________________________
dense_action (Dense)             (None, 8)             264         lstm_shared[1][0]
____________________________________________________________________________________________________
dot_state_action (Model)         (None, 1)             0           dense_state[0][0]
                                                                   dense_action[0][0]
====================================================================================================
Total params: 1,713,552
Trainable params: 43,152
Non-trainable params: 1,670,400
____________________________________________________________________________________________________
---------------
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.
WARNING: Transit simulator removed all actions because of a game bug! Ending with a 0 reward.

</code>


# Notebook from tresordesfeves/artificial-intelligence
Path: HMM Tagger.ipynb

# Project: Part of Speech Tagging with Hidden Markov Models
---
### Introduction

Part of speech tagging is the process of determining the syntactic category of a word from the words in its surrounding context. It is often used to help disambiguate natural language phrases because it can be done quickly with high accuracy. Tagging can be used for many NLP tasks like determining correct pronunciation during speech synthesis (for example, _dis_-count as a noun vs dis-_count_ as a verb), for information retrieval, and for word sense disambiguation.

In this notebook, you'll use the [Pomegranate](http://pomegranate.readthedocs.io/) library to build a hidden Markov model for part of speech tagging using a "universal" tagset. Hidden Markov models have been able to achieve [>96% tag accuracy with larger tagsets on realistic text corpora](http://www.coli.uni-saarland.de/~thorsten/publications/Brants-ANLP00.pdf). Hidden Markov models have also been used for speech recognition and speech generation, machine translation, gene recognition for bioinformatics, and human gesture recognition for computer vision, and more.

![](_post-hmm.png)

The notebook already contains some code to get you started. You only need to add some new functionality in the areas indicated to complete the project; you will not need to modify the included code beyond what is requested. Sections that begin with **'IMPLEMENTATION'** in the header indicate that you must provide code in the block that follows. Instructions will be provided for each section, and the specifics of the implementation are marked in the code block with a 'TODO' statement. Please be sure to read the instructions carefully!_____no_output_____

**Note:** Once you have completed all of the code implementations, you need to finalize your work by exporting the iPython Notebook as an HTML document. Before exporting the notebook to html, all of the code cells need to have been run so that reviewers can see the final implementation and output. You must then **export the notebook** by running the last cell in the notebook, or by using the menu above and navigating to **File -> Download as -> HTML (.html)** Your submissions should include both the `html` and `ipynb` files.

_____no_output_____

**Note:** Code and Markdown cells can be executed using the `Shift + Enter` keyboard shortcut. Markdown cells can be edited by double-clicking the cell to enter edit mode.

_____no_output_____### The Road Ahead
You must complete Steps 1-3 below to pass the project. The section on Step 4 includes references & resources you can use to further explore HMM taggers.

- [Step 1](#Step-1:-Read-and-preprocess-the-dataset): Review the provided interface to load and access the text corpus
- [Step 2](#Step-2:-Build-a-Most-Frequent-Class-tagger): Build a Most Frequent Class tagger to use as a baseline
- [Step 3](#Step-3:-Build-an-HMM-tagger): Build an HMM Part of Speech tagger and compare to the MFC baseline
- [Step 4](#Step-4:-[Optional]-Improving-model-performance): (Optional) Improve the HMM tagger_____no_output_____

**Note:** Make sure you have selected a **Python 3** kernel in Workspaces or the hmm-tagger conda environment if you are running the Jupyter server on your own machine.

_____no_output_____

# Jupyter "magic methods" -- only need to be run once per kernel restart
%load_ext autoreload
%aimport helpers, tests
%autoreload 1The autoreload extension is already loaded. To reload it, use:
  %reload_ext autoreload
# let see it it"s save_____no_output_____# import python modules -- this cell needs to be run again if you make changes to any of the files
import matplotlib.pyplot as plt
import numpy as np

from IPython.core.display import HTML
from itertools import chain
from collections import Counter, defaultdict
from helpers import show_model, Dataset
from pomegranate import State, HiddenMarkovModel, DiscreteDistribution_____no_output_____

## Step 1: Read and preprocess the dataset
---
We'll start by reading in a text corpus and splitting it into a training and testing dataset. The data set is a copy of the [Brown corpus](https://en.wikipedia.org/wiki/Brown_Corpus) (originally from the [NLTK](https://www.nltk.org/) library) that has already been pre-processed to only include the [universal tagset](https://arxiv.org/pdf/1104.2086.pdf). You should expect to get slightly higher accuracy using this simplified tagset than the same model would achieve on a larger tagset like the full [Penn treebank tagset](https://www.ling.upenn.edu/courses/Fall_2003/ling001/penn_treebank_pos.html), but the process you'll follow would be the same.

The `Dataset` class provided in helpers.py will read and parse the corpus. You can generate your own datasets compatible with the reader by writing them to the following format. The dataset is stored in plaintext as a collection of words and corresponding tags. Each sentence starts with a unique identifier on the first line, followed by one tab-separated word/tag pair on each following line. Sentences are separated by a single blank line.

Example from the Brown corpus.
```
b100-38532
Perhaps	ADV
it	PRON
was	VERB
right	ADJ
;	.
;	.

b100-35577
...
```_____no_output_____

data = Dataset("tags-universal.txt", "brown-universal.txt", train_test_split=0.8)

print("There are {} sentences in the corpus.".format(len(data)))
print("There are {} sentences in the training set.".format(len(data.training_set)))
print("There are {} sentences in the testing set.".format(len(data.testing_set)))

assert len(data) == len(data.training_set) + len(data.testing_set), \
       "The number of sentences in the training set + testing set should sum to the number of sentences in the corpus"There are 57340 sentences in the corpus.
There are 45872 sentences in the training set.
There are 11468 sentences in the testing set.
f = open("tags-universal.txt", "r") # open file in read mode
data = f.read()      # copy to a string
f.close()               # close the file
print(data)          # print the data.
ADJ
ADP
ADV
CONJ
DET
NOUN
NUM
PRON
PRT
VERB
X

### The Dataset Interface

You can access (mostly) immutable references to the dataset through a simple interface provided through the `Dataset` class, which represents an iterable collection of sentences along with easy access to partitions of the data for training & testing. Review the reference below, then run and review the next few cells to make sure you understand the interface before moving on to the next step.

```
Dataset-only Attributes:
    training_set - reference to a Subset object containing the samples for training
    testing_set - reference to a Subset object containing the samples for testing

Dataset & Subset Attributes:
    sentences - a dictionary with an entry {sentence_key: Sentence()} for each sentence in the corpus
    keys - an immutable ordered (not sorted) collection of the sentence_keys for the corpus
    vocab - an immutable collection of the unique words in the corpus
    tagset - an immutable collection of the unique tags in the corpus
    X - returns an array of words grouped by sentences ((w11, w12, w13, ...), (w21, w22, w23, ...), ...)
    Y - returns an array of tags grouped by sentences ((t11, t12, t13, ...), (t21, t22, t23, ...), ...)
    N - returns the number of distinct samples (individual words or tags) in the dataset

Methods:
    stream() - returns an flat iterable over all (word, tag) pairs across all sentences in the corpus
    __iter__() - returns an iterable over the data as (sentence_key, Sentence()) pairs
    __len__() - returns the nubmer of sentences in the dataset
```

For example, consider a Subset, `subset`, of the sentences `{"s0": Sentence(("See", "Spot", "run"), ("VERB", "NOUN", "VERB")), "s1": Sentence(("Spot", "ran"), ("NOUN", "VERB"))}`. The subset will have these attributes:

```
subset.keys == {"s1", "s0"}  # unordered
subset.vocab == {"See", "run", "ran", "Spot"}  # unordered
subset.tagset == {"VERB", "NOUN"}  # unordered
subset.X == (("Spot", "ran"), ("See", "Spot", "run"))  # order matches .keys
subset.Y == (("NOUN", "VERB"), ("VERB", "NOUN", "VERB"))  # order matches .keys
subset.N == 7  # there are a total of seven observations over all sentences
len(subset) == 2  # because there are two sentences
```

**Note:** The `Dataset` class is _convenient_, but it is **not** efficient. It is not suitable for huge datasets because it stores multiple redundant copies of the same data.

_____no_output_____#### Sentences

`Dataset.sentences` is a dictionary of all sentences in the training corpus, each keyed to a unique sentence identifier. Each `Sentence` is itself an object with two attributes: a tuple of the words in the sentence named `words` and a tuple of the tag corresponding to each word named `tags`._____no_output_____

key = 'b100-38532'
print("Sentence: {}".format(key))
print("words:\n\t{!s}".format(data.sentences[key].words))
print("tags:\n\t{!s}".format(data.sentences[key].tags))_____no_output_____

**Note:** The underlying iterable sequence is **unordered** over the sentences in the corpus; it is not guaranteed to return the sentences in a consistent order between calls. Use `Dataset.stream()`, `Dataset.keys`, `Dataset.X`, or `Dataset.Y` attributes if you need ordered access to the data.

#### Counting Unique Elements

You can access the list of unique words (the dataset vocabulary) via `Dataset.vocab` and the unique list of tags via `Dataset.tagset`._____no_output_____

print("There are a total of {} samples of {} unique words in the corpus."
      .format(data.N, len(data.vocab)))
print("There are {} samples of {} unique words in the training set."
      .format(data.training_set.N, len(data.training_set.vocab)))
print("There are {} samples of {} unique words in the testing set."
      .format(data.testing_set.N, len(data.testing_set.vocab)))
print("There are {} words in the test set that are missing in the training set."
      .format(len(data.testing_set.vocab - data.training_set.vocab)))

assert data.N == data.training_set.N + data.testing_set.N, \
       "The number of training + test samples should sum to the total number of samples"_____no_output_____

#### Accessing word and tag Sequences
The `Dataset.X` and `Dataset.Y` attributes provide access to ordered collections of matching word and tag sequences for each sentence in the dataset._____no_output_____

# accessing words with Dataset.X and tags with Dataset.Y
for i in range(2):
    print("Sentence {}:".format(i + 1), data.X[i])
    print()
    print("Labels {}:".format(i + 1), data.Y[i])
    print()_____no_output_____

#### Accessing (word, tag) Samples
The `Dataset.stream()` method returns an iterator that chains together every pair of (word, tag) entries across all sentences in the entire corpus._____no_output_____

# use Dataset.stream() (word, tag) samples for the entire corpus
print("\nStream (word, tag) pairs:\n")
for i, pair in enumerate(data.stream()):
    print("\t", pair)
    if i > 5: break_____no_output_____

For both our baseline tagger and the HMM model we'll build, we need to estimate the frequency of tags & words from the frequency counts of observations in the training corpus. In the next several cells you will complete functions to compute the counts of several sets of counts. _____no_output_____## Step 2: Build a Most Frequent Class tagger
---

Perhaps the simplest tagger (and a good baseline for tagger performance) is to simply choose the tag most frequently assigned to each word. This "most frequent class" tagger inspects each observed word in the sequence and assigns it the label that was most often assigned to that word in the corpus._____no_output_____### IMPLEMENTATION: Pair Counts

Complete the function below that computes the joint frequency counts for two input sequences._____no_output_____

def pair_counts(sequences_A, sequences_B):
    """Return a dictionary keyed to each unique value in the first sequence list
    that counts the number of occurrences of the corresponding value from the
    second sequences list.

    For example, if sequences_A is tags and sequences_B is the corresponding
    words, then if 1244 sequences contain the word "time" tagged as a NOUN, then
    you should return a dictionary such that pair_counts[NOUN][time] == 1244
    """
    # TODO: Finish this function!
    raise NotImplementedError

# Calculate C(t_i, w_i)
emission_counts = pair_counts(# TODO: YOUR CODE HERE)

assert len(emission_counts) == 12, \
       "Uh oh. There should be 12 tags in your dictionary."
assert max(emission_counts["NOUN"], key=emission_counts["NOUN"].get) == 'time', \
       "Hmmm...'time' is expected to be the most common NOUN."
HTML('
Your emission counts look good!
')_____no_output_____

### IMPLEMENTATION: Most Frequent Class Tagger

Use the `pair_counts()` function and the training dataset to find the most frequent class label for each word in the training data, and populate the `mfc_table` below. The table keys should be words, and the values should be the appropriate tag string.

The `MFCTagger` class is provided to mock the interface of Pomegranite HMM models so that they can be used interchangeably._____no_output_____

# Create a lookup table mfc_table where mfc_table[word] contains the tag label most frequently assigned to that word
from collections import namedtuple

FakeState = namedtuple("FakeState", "name")

class MFCTagger:
    # NOTE: You should not need to modify this class or any of its methods
    missing = FakeState(name="<MISSING>")

    def __init__(self, table):
        self.table = defaultdict(lambda: MFCTagger.missing)
        self.table.update({word: FakeState(name=tag) for word, tag in table.items()})

    def viterbi(self, seq):
        """This method simplifies predictions by matching the Pomegranate viterbi() interface"""
        return 0., list(enumerate(["<start>"] + [self.table[w] for w in seq] + ["<end>"]))

# TODO: calculate the frequency of each tag being assigned to each word (hint: similar, but not
# the same as the emission probabilities) and use it to fill the mfc_table

word_counts = pair_counts(# TODO: YOUR CODE HERE)

mfc_table = # TODO: YOUR CODE HERE

# DO NOT MODIFY BELOW THIS LINE
mfc_model = MFCTagger(mfc_table) # Create a Most Frequent Class tagger instance

assert len(mfc_table) == len(data.training_set.vocab), ""
assert all(k in data.training_set.vocab for k in mfc_table.keys()), ""
assert sum(int(k not in mfc_table) for k in data.testing_set.vocab) == 5521, ""
HTML('
Your MFC tagger has all the correct words!
')_____no_output_____

### Making Predictions with a Model
The helper functions provided below interface with Pomegranate network models & the mocked MFCTagger to take advantage of the [missing value](http://pomegranate.readthedocs.io/en/latest/nan.html) functionality in Pomegranate through a simple sequence decoding function. Run these functions, then run the next cell to see some of the predictions made by the MFC tagger._____no_output_____

def replace_unknown(sequence):
    """Return a copy of the input sequence where each unknown word is replaced
    by the literal string value 'nan'. Pomegranate will ignore these values
    during computation.
    """
    return [w if w in data.training_set.vocab else 'nan' for w in sequence]

def simplify_decoding(X, model):
    """X should be a 1-D sequence of observations for the model to predict"""
    _, state_path = model.viterbi(replace_unknown(X))
    return [state[1].name for state in state_path[1:-1]]  # do not show the start/end state predictions_____no_output_____

### Example Decoding Sequences with MFC Tagger_____no_output_____

for key in data.testing_set.keys[:3]:
    print("Sentence Key: {}\n".format(key))
    print("Predicted labels:\n-----------------")
    print(simplify_decoding(data.sentences[key].words, mfc_model))
    print()
    print("Actual labels:\n--------------")
    print(data.sentences[key].tags)
    print("\n")_____no_output_____

### Evaluating Model Accuracy

The function below will evaluate the accuracy of the MFC tagger on the collection of all sentences from a text corpus. _____no_output_____

def accuracy(X, Y, model):
    """Calculate the prediction accuracy by using the model to decode each sequence
    in the input X and comparing the prediction with the true labels in Y.

    The X should be an array whose first dimension is the number of sentences to test,
    and each element of the array should be an iterable of the words in the sequence.
    The arrays X and Y should have the exact same shape.

    X = [("See", "Spot", "run"), ("Run", "Spot", "run", "fast"), ...]
    Y = [(), (), ...]
    """
    correct = total_predictions = 0
    for observations, actual_tags in zip(X, Y):

        # The model.viterbi call in simplify_decoding will return None if the HMM
        # raises an error (for example, if a test sentence contains a word that
        # is out of vocabulary for the training set). Any exception counts the
        # full sentence as an error (which makes this a conservative estimate).
        try:
            most_likely_tags = simplify_decoding(observations, model)
            correct += sum(p == t for p, t in zip(most_likely_tags, actual_tags))
        except:
            pass
        total_predictions += len(observations)
    return correct / total_predictions_____no_output_____

#### Evaluate the accuracy of the MFC tagger
Run the next cell to evaluate the accuracy of the tagger on the training and test corpus._____no_output_____

mfc_training_acc = accuracy(data.training_set.X, data.training_set.Y, mfc_model)
print("training accuracy mfc_model: {:.2f}%".format(100 * mfc_training_acc))

mfc_testing_acc = accuracy(data.testing_set.X, data.testing_set.Y, mfc_model)
print("testing accuracy mfc_model: {:.2f}%".format(100 * mfc_testing_acc))

assert mfc_training_acc >= 0.955, "Uh oh. Your MFC accuracy on the training set doesn't look right."
assert mfc_testing_acc >= 0.925, "Uh oh. Your MFC accuracy on the testing set doesn't look right."
HTML('
Your MFC tagger accuracy looks correct!
')_____no_output_____

## Step 3: Build an HMM tagger
---
The HMM tagger has one hidden state for each possible tag, and parameterized by two distributions: the emission probabilties giving the conditional probability of observing a given **word** from each hidden state, and the transition probabilities giving the conditional probability of moving between **tags** during the sequence.

We will also estimate the starting probability distribution (the probability of each **tag** being the first tag in a sequence), and the terminal probability distribution (the probability of each **tag** being the last tag in a sequence).

The maximum likelihood estimate of these distributions can be calculated from the frequency counts as described in the following sections where you'll implement functions to count the frequencies, and finally build the model. The HMM model will make predictions according to the formula:

$$t_i^n = \underset{t_i^n}{\mathrm{argmax}} \prod_{i=1}^n P(w_i|t_i) P(t_i|t_{i-1})$$

Refer to Speech & Language Processing [Chapter 10](https://web.stanford.edu/~jurafsky/slp3/10.pdf) for more information._____no_output_____### IMPLEMENTATION: Unigram Counts

Complete the function below to estimate the co-occurrence frequency of each symbol over all of the input sequences. The unigram probabilities in our HMM model are estimated from the formula below, where N is the total number of samples in the input. (You only need to compute the counts for now.)

$$P(tag_1) = \frac{C(tag_1)}{N}$$_____no_output_____

def unigram_counts(sequences):
    """Return a dictionary keyed to each unique value in the input sequence list that
    counts the number of occurrences of the value in the sequences list. The sequences
    collection should be a 2-dimensional array.

    For example, if the tag NOUN appears 275558 times over all the input sequences,
    then you should return a dictionary such that your_unigram_counts[NOUN] == 275558.
    """
    # TODO: Finish this function!
    raise NotImplementedError

# TODO: call unigram_counts with a list of tag sequences from the training set
tag_unigrams = unigram_counts(# TODO: YOUR CODE HERE)

assert set(tag_unigrams.keys()) == data.training_set.tagset, \
       "Uh oh. It looks like your tag counts doesn't include all the tags!"
assert min(tag_unigrams, key=tag_unigrams.get) == 'X', \
       "Hmmm...'X' is expected to be the least common class"
assert max(tag_unigrams, key=tag_unigrams.get) == 'NOUN', \
       "Hmmm...'NOUN' is expected to be the most common class"
HTML('
Your tag unigrams look good!
')_____no_output_____

### IMPLEMENTATION: Bigram Counts

Complete the function below to estimate the co-occurrence frequency of each pair of symbols in each of the input sequences. These counts are used in the HMM model to estimate the bigram probability of two tags from the frequency counts according to the formula: $$P(tag_2|tag_1) = \frac{C(tag_2|tag_1)}{C(tag_2)}$$
_____no_output_____

def bigram_counts(sequences):
    """Return a dictionary keyed to each unique PAIR of values in the input sequences
    list that counts the number of occurrences of pair in the sequences list. The input
    should be a 2-dimensional array.

    For example, if the pair of tags (NOUN, VERB) appear 61582 times, then you should
    return a dictionary such that your_bigram_counts[(NOUN, VERB)] == 61582
    """

    # TODO: Finish this function!
    raise NotImplementedError

# TODO: call bigram_counts with a list of tag sequences from the training set
tag_bigrams = bigram_counts(# TODO: YOUR CODE HERE)

assert len(tag_bigrams) == 144, \
       "Uh oh. There should be 144 pairs of bigrams (12 tags x 12 tags)"
assert min(tag_bigrams, key=tag_bigrams.get) in [('X', 'NUM'), ('PRON', 'X')], \
       "Hmmm...The least common bigram should be one of ('X', 'NUM') or ('PRON', 'X')."
assert max(tag_bigrams, key=tag_bigrams.get) in [('DET', 'NOUN')], \
       "Hmmm...('DET', 'NOUN') is expected to be the most common bigram."
HTML('
Your tag bigrams look good!
')_____no_output_____

### IMPLEMENTATION: Sequence Starting Counts
Complete the code below to estimate the bigram probabilities of a sequence starting with each tag._____no_output_____

def starting_counts(sequences):
    """Return a dictionary keyed to each unique value in the input sequences list
    that counts the number of occurrences where that value is at the beginning of
    a sequence.

    For example, if 8093 sequences start with NOUN, then you should return a
    dictionary such that your_starting_counts[NOUN] == 8093
    """
    # TODO: Finish this function!
    raise NotImplementedError

# TODO: Calculate the count of each tag starting a sequence
tag_starts = starting_counts(# TODO: YOUR CODE HERE)

assert len(tag_starts) == 12, "Uh oh. There should be 12 tags in your dictionary."
assert min(tag_starts, key=tag_starts.get) == 'X', "Hmmm...'X' is expected to be the least common starting bigram."
assert max(tag_starts, key=tag_starts.get) == 'DET', "Hmmm...'DET' is expected to be the most common starting bigram."
HTML('
Your starting tag counts look good!
')_____no_output_____

### IMPLEMENTATION: Sequence Ending Counts
Complete the function below to estimate the bigram probabilities of a sequence ending with each tag._____no_output_____

def ending_counts(sequences):
    """Return a dictionary keyed to each unique value in the input sequences list
    that counts the number of occurrences where that value is at the end of
    a sequence.

    For example, if 18 sequences end with DET, then you should return a
    dictionary such that your_starting_counts[DET] == 18
    """
    # TODO: Finish this function!
    raise NotImplementedError

# TODO: Calculate the count of each tag ending a sequence
tag_ends = ending_counts(# TODO: YOUR CODE HERE)

assert len(tag_ends) == 12, "Uh oh. There should be 12 tags in your dictionary."
assert min(tag_ends, key=tag_ends.get) in ['X', 'CONJ'], "Hmmm...'X' or 'CONJ' should be the least common ending bigram."
assert max(tag_ends, key=tag_ends.get) == '.', "Hmmm...'.' is expected to be the most common ending bigram."
HTML('
Your ending tag counts look good!
')_____no_output_____

### IMPLEMENTATION: Basic HMM Tagger
Use the tag unigrams and bigrams calculated above to construct a hidden Markov tagger.

- Add one state per tag
    - The emission distribution at each state should be estimated with the formula: $P(w|t) = \frac{C(t, w)}{C(t)}$
- Add an edge from the starting state `basic_model.start` to each tag
    - The transition probability should be estimated with the formula: $P(t|start) = \frac{C(start, t)}{C(start)}$
- Add an edge from each tag to the end state `basic_model.end`
    - The transition probability should be estimated with the formula: $P(end|t) = \frac{C(t, end)}{C(t)}$
- Add an edge between _every_ pair of tags
    - The transition probability should be estimated with the formula: $P(t_2|t_1) = \frac{C(t_1, t_2)}{C(t_1)}$_____no_output_____

basic_model = HiddenMarkovModel(name="base-hmm-tagger")

# TODO: create states with emission probability distributions P(word | tag) and add to the model
# (Hint: you may need to loop & create/add new states)
basic_model.add_states()

# TODO: add edges between states for the observed transition frequencies P(tag_i | tag_i-1)
# (Hint: you may need to loop & add transitions
basic_model.add_transition()

# NOTE: YOU SHOULD NOT NEED TO MODIFY ANYTHING BELOW THIS LINE
# finalize the model
basic_model.bake()

assert all(tag in set(s.name for s in basic_model.states) for tag in data.training_set.tagset), \
       "Every state in your network should use the name of the associated tag, which must be one of the training set tags."
assert basic_model.edge_count() == 168, \
       ("Your network should have an edge from the start node to each state, one edge between every " +
        "pair of tags (states), and an edge from each state to the end node.")
HTML('
Your HMM network topology looks good!
')_____no_output_____hmm_training_acc = accuracy(data.training_set.X, data.training_set.Y, basic_model)
print("training accuracy basic hmm model: {:.2f}%".format(100 * hmm_training_acc))

hmm_testing_acc = accuracy(data.testing_set.X, data.testing_set.Y, basic_model)
print("testing accuracy basic hmm model: {:.2f}%".format(100 * hmm_testing_acc))

assert hmm_training_acc > 0.97, "Uh oh. Your HMM accuracy on the training set doesn't look right."
assert hmm_testing_acc > 0.955, "Uh oh. Your HMM accuracy on the testing set doesn't look right."
HTML('
Your HMM tagger accuracy looks correct! Congratulations, you\'ve finished the project.
')_____no_output_____

### Example Decoding Sequences with the HMM Tagger_____no_output_____

for key in data.testing_set.keys[:3]:
    print("Sentence Key: {}\n".format(key))
    print("Predicted labels:\n-----------------")
    print(simplify_decoding(data.sentences[key].words, basic_model))
    print()
    print("Actual labels:\n--------------")
    print(data.sentences[key].tags)
    print("\n")_____no_output_____

## Finishing the project
---

**Note:** **SAVE YOUR NOTEBOOK**, then run the next cell to generate an HTML copy. You will zip & submit both this file and the HTML copy for review.

_____no_output_____

!!jupyter nbconvert *.ipynb_____no_output_____

## Step 4: [Optional] Improving model performance
---
There are additional enhancements that can be incorporated into your tagger that improve performance on larger tagsets where the data sparsity problem is more significant. The data sparsity problem arises because the same amount of data split over more tags means there will be fewer samples in each tag, and there will be more missing data  tags that have zero occurrences in the data. The techniques in this section are optional.

- [Laplace Smoothing](https://en.wikipedia.org/wiki/Additive_smoothing) (pseudocounts)
    Laplace smoothing is a technique where you add a small, non-zero value to all observed counts to offset for unobserved values.

- Backoff Smoothing
    Another smoothing technique is to interpolate between n-grams for missing data. This method is more effective than Laplace smoothing at combatting the data sparsity problem. Refer to chapters 4, 9, and 10 of the [Speech & Language Processing](https://web.stanford.edu/~jurafsky/slp3/) book for more information.

- Extending to Trigrams
    HMM taggers have achieved better than 96% accuracy on this dataset with the full Penn treebank tagset using an architecture described in [this](http://www.coli.uni-saarland.de/~thorsten/publications/Brants-ANLP00.pdf) paper. Altering your HMM to achieve the same performance would require implementing deleted interpolation (described in the paper), incorporating trigram probabilities in your frequency tables, and re-implementing the Viterbi algorithm to consider three consecutive states instead of two.

### Obtain the Brown Corpus with a Larger Tagset
Run the code below to download a copy of the brown corpus with the full NLTK tagset. You will need to research the available tagset information in the NLTK docs and determine the best way to extract the subset of NLTK tags you want to explore. If you write the following the format specified in Step 1, then you can reload the data using all of the code above for comparison.

Refer to [Chapter 5](http://www.nltk.org/book/ch05.html) of the NLTK book for more information on the available tagsets._____no_output_____

import nltk
from nltk import pos_tag, word_tokenize
from nltk.corpus import brown

nltk.download('brown')
training_corpus = nltk.corpus.brown
training_corpus.tagged_sents()[0]_____no_output_____


# Notebook from AndrewSerra/Knet.jl
Path: tutorial/30.lin.ipynb

# Linear models, loss functions, gradients, SGD
(c) Deniz Yuret, 2019
* Objectives: Define, train and visualize a simple model; understand gradients and SGD; learn to use the GPU.
* Prerequisites: [Callable objects](https://docs.julialang.org/en/v1/manual/methods/#Function-like-objects-1), [Generator expressions](https://docs.julialang.org/en/v1/manual/arrays/#Generator-Expressions-1), [MNIST](20.mnist.ipynb), [Iterators](25.iterators.ipynb)
* New functions:
[accuracy](http://denizyuret.github.io/Knet.jl/latest/reference/#Knet.accuracy),
[zeroone](http://denizyuret.github.io/Knet.jl/latest/reference/#Knet.zeroone),
[nll](http://denizyuret.github.io/Knet.jl/latest/reference/#Knet.nll),
[Param, @diff, value, params, grad](http://denizyuret.github.io/Knet.jl/latest/reference/#AutoGrad),
[sgd](http://denizyuret.github.io/Knet.jl/latest/reference/#Knet.sgd),
[progress, progress!](http://denizyuret.github.io/Knet.jl/latest/reference/#Knet.progress),
[gpu](http://denizyuret.github.io/Knet.jl/latest/reference/#Knet.gpu),
[KnetArray](http://denizyuret.github.io/Knet.jl/latest/reference/#Knet.KnetArray),
[load](http://denizyuret.github.io/Knet.jl/latest/reference/#Knet.load),
[save](http://denizyuret.github.io/Knet.jl/latest/reference/#Knet.save)

 ([image source](https://www.oreilly.com/library/view/tensorflow-for-deep/9781491980446/ch04.html))

In Knet, a machine learning model is defined using plain Julia code. A typical model consists of a **prediction** and a **loss** function. The prediction function takes some input, returns the prediction of the model for that input. The loss function measures how bad the prediction is with respect to some desired output. We train a model by adjusting its parameters to reduce the loss.

In this section we will implement a simple linear model to classify MNIST digits. The prediction function will return 10 scores for each of the possible labels 0..9 as a linear combination of the pixel values. The loss function will convert these scores to normalized probabilities and return the average -log probability of the correct answers. Minimizing this loss should maximize the scores assigned to correct answers by the model. We will make use of the loss gradient with respect to each parameter, which tells us the direction of the greatest loss increase. We will improve the model by moving the parameters in the opposite direction (using a GPU if available). We will visualize the model weights and performance over time. The final accuracy of about 92% is close to the limit of what we can achieve with this type of model. To improve further we must look beyond linear models._____no_output_____

# Set display width, load packages, import symbols
ENV["COLUMNS"]=72
using Statistics: mean
using Base.Iterators: flatten
using IterTools: ncycle, takenth
import Random # seed!
using MLDatasets: MNIST
import CUDA # functional
using Knet: Knet, AutoGrad, dir, Data, minibatch, Param, @diff, value, params, grad, progress, progress!, KnetArray, load143, save
# The following are defined for instruction even though they are provided in Knet
# using Knet: accuracy, zeroone, nll, sgd_____no_output_____# Load MNIST data
xtrn,ytrn = MNIST.traindata(Float32); ytrn[ytrn.==0] .= 10
xtst,ytst = MNIST.testdata(Float32);  ytst[ytst.==0] .= 10
dtrn = minibatch(xtrn, ytrn, 100; xsize = (784,:), xtype = Array)
dtst = minibatch(xtst, ytst, 100; xsize = (784,:), xtype = Array)
println.(summary.((dtrn,dtst)));600-element Data{Tuple{Array{Float32,2},Array{Int64,1}}}
100-element Data{Tuple{Array{Float32,2},Array{Int64,1}}}

## Model definition_____no_output_____

# In Julia we define a new datatype using `struct`:
struct Linear; w; b; end

# The new struct comes with a default constructor:
model = Linear(0.01 * randn(10,784), zeros(10))

# We can define other constructors with different inputs:
Linear(i::Int,o::Int,scale=0.01) = Linear(scale * randn(o,i), zeros(o))

# This one allows instances to be defined using input and output sizes:
model = Linear(784,10)_____no_output_____

## Prediction_____no_output_____

# We turn Linear instances into callable objects for prediction:
(m::Linear)(x) = m.w * x .+ m.b_____no_output_____x,y = first(dtst) # The first minibatch from the test set
summary.((x,y))_____no_output_____Int.(y)' # correct answers are given as an array of integers (remember we use 10 for 0)_____no_output_____ypred = model(x)  # Predictions on the first minibatch: a 10x100 score matrix_____no_output_____# We can calculate the accuracy of our model for the first minibatch
accuracy(model,x,y) = mean(y' .== map(i->i[1], findmax(Array(model(x)),dims=1)[2]))
accuracy(model,x,y)_____no_output_____# We can calculate the accuracy of our model for the whole test set
accuracy(model,data) = mean(accuracy(model,x,y) for (x,y) in data)
accuracy(model,dtst)_____no_output_____# ZeroOne loss (or error) is defined as 1 - accuracy
zeroone(x...) = 1 - accuracy(x...)
zeroone(model,dtst)_____no_output_____

## Loss function_____no_output_____

# For classification we use negative log likelihood loss (aka cross entropy, softmax loss, NLL)
# This is the average -log probability assigned to correct answers by the model
function nll(scores, y)
    expscores = exp.(scores)
    probabilities = expscores ./ sum(expscores, dims=1)
    answerprobs = (probabilities[y[i],i] for i in 1:length(y))
    mean(-log.(answerprobs))
end_____no_output_____# model(x) gives predictions, let model(x,y) give the loss
(m::Linear)(x, y) = nll(m(x), y)
model(x,y)_____no_output_____# We can also use the Knet nll implementation for efficiency
(m::Linear)(x, y) = Knet.nll(m(x), y)
model(x,y)_____no_output_____# If the input is a dataset compute average loss:
(m::Linear)(data::Data) = mean(m(x,y) for (x,y) in data)_____no_output_____# Here is per-instance average negative log likelihood for the whole test set
model(dtst)_____no_output_____

**Bonus question:** What is special about the loss value 2.3?_____no_output_____## Calculating the gradient using AutoGrad_____no_output_____

@doc AutoGrad_____no_output_____# Redefine the constructor to use Param's so we can compute gradients
Linear(i::Int,o::Int,scale=0.01) =

Linear(Param(scale * randn(o,i)), Param(zeros(o)))_____no_output_____# Set random seed for replicability
Random.seed!(226);_____no_output_____# Use a larger scale to get a large initial loss
model = Linear(784,10,1.0)_____no_output_____# We can still do predictions and calculate loss:
model(x,y)_____no_output_____# And we can do the same loss calculation also computing gradients:
J = @diff model(x,y)_____no_output_____# To get the actual loss value from J:
value(J)_____no_output_____# params(J) returns an iterator of Params J depends on (i.e. model.b, model.w):
params(J) |> collect_____no_output_____# To get the gradient of a parameter from J:
∇w = grad(J,model.w)_____no_output_____# Note that each gradient has the same size and shape as the corresponding parameter:
@show ∇b = grad(J,model.b);∇b = grad(J, model.b) = [0.5906946123008457, -0.027041397089362467, -0.08694323408456664, -0.10750809160810809, -0.05254391972254851, -0.09056807340274403, -0.14070630316059043, 0.015127334068075577, -0.03230399769325696, -0.06820692960774405]

## Checking the gradient using numerical approximation

What does ∇b represent?

∇b[1] = 0.59 means if I increase b[1] by ϵ, loss will increase by 0.59ϵ_____no_output_____

# Loss for the first minibatch with the original parameters
@show value(model.b)
model(x,y)value(model.b) = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
# To numerically check the gradient let's increase the last entry of b by +0.1.
model.b[1] = 0.1_____no_output_____# We see that the loss moves by ≈ +0.79*0.1 as expected.
@show value(model.b)
model(x,y)value(model.b) = [0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
# Reset the change.
model.b[1] = 0_____no_output_____

## Checking the gradient using manual implementation_____no_output_____

# Without AutoGrad we would have to define the gradients manually:
function nllgrad(model,x,y)
    scores = model(x)
    expscores = exp.(scores)
    probabilities = expscores ./ sum(expscores, dims=1)
    for i in 1:length(y); probabilities[y[i],i] -= 1; end
    dJds = probabilities / length(y)
    dJdw = dJds * x'
    dJdb = vec(sum(dJds,dims=2))
    dJdw,dJdb
end;_____no_output_____∇w2,∇b2 = nllgrad(model,x,y)_____no_output_____∇w2 ≈ ∇w_____no_output_____∇b2 ≈ ∇b_____no_output_____

## Training with Stochastic Gradient Descent (SGD)_____no_output_____

# Here is a single SGD update:
function sgdupdate!(func, args; lr=0.1)
    fval = @diff func(args...)
    for param in params(fval)
        ∇param = grad(fval, param)
        param .-= lr * ∇param
    end
    return value(fval)
end_____no_output_____# We define SGD for a dataset as an iterator so that:
# 1. We can monitor and report the training loss
# 2. We can take snapshots of the model during training
# 3. We can pause/terminate training when necessary
sgd(func, data; lr=0.1) =
    (sgdupdate!(func, args; lr=lr) for args in data)_____no_output_____# Let's train a model for 10 epochs to compare training speed on cpu vs gpu.
# progress!(itr) displays a progress bar when wrapped around an iterator like this:
# 2.94e-01  100.00%┣████████████████████┫ 6000/6000 [00:10/00:10, 592.96/s] 2.31->0.28
model = Linear(784,10)
@show model(dtst)
progress!(sgd(model, ncycle(dtrn,10)))
@show model(dtst);model(dtst) = 2.3142570870549655

## Using the GPU_____no_output_____

# The training would go a lot faster on a GPU:
# 2.94e-01  100.00%┣███████████████████┫ 6000/6000 [00:02/00:02, 2653.45/s]  2.31->0.28
# To work on a GPU, all we have to do is convert Arrays to KnetArrays:
if CUDA.functional()  # returns true if there is a GPU
    atype = KnetArray{Float32}  # CuArrays are stored and operated in the GPU
    dtrn = minibatch(xtrn, ytrn, 100; xsize = (784,:), xtype=atype)
    dtst = minibatch(xtst, ytst, 100; xsize = (784,:), xtype=atype)
    Linear(i::Int,o::Int,scale=0.01) =
        Linear(Param(atype(scale * randn(o,i))),
               Param(atype(zeros(o))))

    model = Linear(784,10)
    @show model(dtst)
    progress!(sgd(model,ncycle(dtrn,10)))
    @show model(dtst)
end;model(dtst) = 2.3094196f0

## Recording progress_____no_output_____

function trainresults(file, model)
    if (print("Train from scratch? (~77s) "); readline()[1]=='y')
        # We will train 100 epochs (the following returns an iterator, does not start training)
        training = sgd(model, ncycle(dtrn,100))
        # We will snapshot model and train/test loss and errors
        snapshot() = (deepcopy(model),model(dtrn),model(dtst),zeroone(model,dtrn),zeroone(model,dtst))
        # Snapshot results once every epoch (still an iterator)
        snapshots = (snapshot() for x in takenth(progress(training),length(dtrn)))
        # Run the snapshot/training iterator, reshape and save results as a 5x100 array
        lin = reshape(collect(flatten(snapshots)),(5,:))
        # Knet.save and Knet.load can be used to store models in files
        Knet.save(file,"results",lin)
    else
        isfile(file) || download("http://people.csail.mit.edu/deniz/models/tutorial/$file", file)
        lin = Knet.load143(file,"results")
    end
    return lin
end_____no_output_____# 2.43e-01  100.00%┣████████████████▉┫ 60000/60000 [00:44/00:44, 1349.13/s]
lin = trainresults("lin113.jld2",Linear(784,10));Train from scratch? (~77s) stdin> n

## Linear model shows underfitting_____no_output_____

using Plots; default(fmt = :png)_____no_output_____# Demonstrates underfitting: training loss not close to 0
# Also slight overfitting: test loss higher than train
trnloss,tstloss = Array{Float32}(lin[2,:]), Array{Float32}(lin[3,:])
plot([trnloss,tstloss],ylim=(.0,.4),labels=["trnloss" "tstloss"],xlabel="Epochs",ylabel="Loss")_____no_output_____# this is the error plot, we get to about 7.5% test error, i.e. 92.5% accuracy
trnerr,tsterr = Array{Float32}(lin[4,:]), Array{Float32}(lin[5,:])
plot([trnerr,tsterr],ylim=(.0,.12),labels=["trnerr" "tsterr"],xlabel="Epochs",ylabel="Error")_____no_output_____

## Visualizing the learned weights_____no_output_____

# Let us visualize the evolution of the weight matrix as images below
# Each row is turned into a 28x28 image with positive weights light and negative weights dark gray
using Images, ImageMagick
for t in 10 .^ range(0,stop=log10(size(lin,2)),length=20) #logspace(0,2,20)
    i = ceil(Int,t)
    f = lin[1,i]
    w1 = reshape(Array(value(f.w))', (28,28,10))
    w2 = clamp.(w1.+0.5,0,1)
    IJulia.clear_output(true)
    display([MNIST.convert2image(w2[:,:,i]) for i=1:10])
    display("Epoch $(i-1)")
    sleep(1) # (0.96^i)
end_____no_output_____


# Notebook from SarahRomyMarkose/Business-Analytics-with-Python
Path: Math library, Matplotlib, Functions.ipynb

<code>
import math as sarah_____no_output_____sarah.pi # Pi value_____no_output_____sarah.cos(sarah.pi/2)  # value of cos(pi/2)_____no_output_____sarah.sqrt(4)_____no_output_____import matplotlib.pyplot as plt_____no_output_____x=[1,2,3,4,5,6,7,8,9]
y=[1,3,5,7,9,2,4,6,8]

plt.plot(x,y)
plt.xlabel("Days")
plt.ylabel("Sales")
plt.title("Sales vs Days")_____no_output_____plt.scatter(x,y)
plt.xlabel("Days")
plt.ylabel("Sales")
plt.title("Sales vs Days")_____no_output_____plt.scatter(x,y, marker="*")  # Here, '*'/asterix refers to star shape.
plt.xlabel("Days")
plt.ylabel("Sales")
plt.title("Sales vs Days")_____no_output_____plt.plot(x,y, marker="D") # Here, 'D' refers to Diamond shape.
plt.xlabel("Days")
plt.ylabel("Sales")
plt.title("Sales vs Days")_____no_output_____plt.plot(x,y, marker="D", ms=20)  # 'ms' determines the size of induvidual plots.
plt.xlabel("Days")
plt.ylabel("Sales")
plt.title("Sales vs Days")_____no_output_____plt.plot(x,y, marker="D", ms=20, mec="r")   # 'mec' determines the outer color of induvidual plots.
plt.xlabel("Days")
plt.ylabel("Sales")
plt.title("Sales vs Days")_____no_output_____plt.plot(x,y, marker="D", ms=20, mec="r", mfc="g")  # 'mfc' determines the color of induvidual plots.
plt.xlabel("Days")
plt.ylabel("Sales")
plt.title("Sales vs Days")_____no_output_____def add(x,y) :   #FUNCTIONS
    print(x+y)_____no_output_____add(4,3)7
add(40,60)100
def add(x,y) :
    z=x+y
    return z_____no_output_____add(40,67)_____no_output_____def add(x,y):    # Use 'return()' or 'print()' after each definition. Both have the same meaning in this context but 'return()' command will have more aplication widely.
    z=x+y
    return(z)

def sub(x,y):
    z=x-y
    return(z)

def mult(x,y):
    z=x*y
    return(z)

def div(x,y):
    z=x/y
    return(z)_____no_output_____a=int(input("Enter the I no.: "))
b=int(input("Enter the II no.: "))
sub(a,b)Enter the I no.:  4
Enter the II no.:  3

</code>


# Notebook from littleblackfish/gimmemotifs
Path: docs/api_examples.ipynb

from pkg_resources import resource_filename
data_dir = resource_filename("gimmemotifs", "../data/examples")

%cd {data_dir}/home/simon/anaconda3/envs/gimme/lib/python3.6/site-packages/gimmemotifs-0.13.0+35.gfd2d0cc.dirty-py3.6-linux-x86_64.egg/data/examples
from gimmemotifs.motif import Motif,read_motifs

# Read from file
motifs = read_motifs("example.pfm")

for motif in motifs:
    print(motif)AP1_ATGAsTCAy
CTCF_syGCCmyCTrGTGG
# Read from file to a dictionary
motifs = read_motifs("example.pfm", as_dict=True)
print(motifs){'AP1': AP1_ATGAsTCAy, 'CTCF': CTCF_syGCCmyCTrGTGG}
# Read any motif database included with gimmemotifs by name
motifs = read_motifs("JASPAR2018_vertebrates")
print(len(motifs))
print(motifs[0].to_pwm())579
>MA0004.1_Arnt
0.2000	0.7999	0.0000	0.0000
0.9499	0.0000	0.0500	0.0000
0.0000	0.9999	0.0000	0.0000
0.0000	0.0000	0.9999	0.0000
0.0000	0.0000	0.0000	0.9999
0.0000	0.0000	0.9999	0.0000
# Create from scratch
m = Motif([[0,1,0,0],[0,0,1,0]])
m.id = "CpG"
print(m)CpG_CG
# Or from a consensus sequence
from gimmemotifs.motif import motif_from_consensus
ap1 = motif_from_consensus("TGASTCA")
print(ap1.to_pwm())>TGASTCA
0.0001	0.0001	0.0001	0.9998
0.0001	0.0001	0.9998	0.0001
0.9998	0.0001	0.0001	0.0001
0.0001	0.4999	0.4999	0.0001
0.0001	0.0001	0.0001	0.9998
0.0001	0.9998	0.0001	0.0001
0.9998	0.0001	0.0001	0.0001

Read motifs from files in other formats.
_____no_output_____

with open("MA0099.3.jaspar") as f:
    motifs = read_motifs(f, fmt="jaspar")
print(motifs[0])MA0099.3	FOS::JUN_ATGAGTCAyn

You can convert a motif to several formats.
_____no_output_____

with open("example.pfm") as f:
    motifs = read_motifs(f)

# pwm
print(motifs[0].to_pwm())>AP1
0.5558	0.1469	0.2734	0.0240
0.0020	0.0015	0.0017	0.9948
0.0039	0.0019	0.9502	0.0439
0.9697	0.0220	0.0018	0.0065
0.0377	0.3311	0.6030	0.0283
0.0033	0.0031	0.0043	0.9893
0.0188	0.9775	0.0023	0.0014
0.9951	0.0021	0.0012	0.0015
0.0121	0.3096	0.1221	0.5561
# pfm
print(motifs[0].to_pfm())>AP1
555.8	146.9	273.4	24.0
2.0	1.5	1.7	994.8000000000001
3.9	1.9	950.2	43.9
969.7	22.0	1.8	6.5
37.699999999999996	331.1	603.0	28.299999999999997
3.3	3.1	4.3	989.3
18.8	977.5	2.3	1.4
995.1	2.1	1.2	1.5
12.1	309.59999999999997	122.1	556.1
# consensus sequence
print(motifs[0].to_consensus())ATGAsTCAy
# TRANSFAC
print(motifs[0].to_transfac())DE	AP1	unknown
0	555	146	273	24	A
1	2	1	1	994	T
2	3	1	950	43	G
3	969	22	1	6	A
4	37	331	603	28	s
5	3	3	4	989	T
6	18	977	2	1	C
7	995	2	1	1	A
8	12	309	122	556	y
XX
# MEME
print(motifs[0].to_meme())MOTIF AP1
BL   MOTIF AP1 width=0 seqs=0
letter-probability matrix: alength= 4 w= 9 nsites= 1000.1 E= 0
0.5558	0.1469	0.2734	0.024
0.002	0.0015	0.0017	0.9948
0.0039	0.0019	0.9502	0.0439
0.9697	0.022	0.0018	0.0065
0.0377	0.3311	0.603	0.0283
0.0033	0.0031	0.0043	0.9893
0.0188	0.9775	0.0023	0.0014
0.9951	0.0021	0.0012	0.0015
0.0121	0.3096	0.1221	0.5561

Some other useful tidbits._____no_output_____

m = motif_from_consensus("NTGASTCAN")
print(len(m))9
# Trim by information content
m.trim(0.5)
print(m.to_consensus(), len(m))TGAsTCA 7
# Slices
print(m[:3].to_consensus())TGA
# Shuffle
random_motif = motif_from_consensus("NTGASTGAN").randomize()
print(random_motif)random_sGTAnATGn

To convert a motif to an image, use `to_img()`. Supported formats are png, ps and pdf._____no_output_____

m = motif_from_consensus("NTGASTCAN")
m.to_img("ap1.png", fmt="png")_____no_output_____from IPython.display import Image
Image("ap1.png")_____no_output_____

# Motif scanning

For very simple scanning, you can just use a Motif instance. Let’s say we have a FASTA file called `test.small.fa` that looks like this:

```
>seq1
AAAAAAAAAAAAAAAAAAAAAA
>seq2
CGCGCGTGAGTCACGCGCGCGCG
>seq3
TGASTCAAAAAAAAAATGASTCA
```

Now we can use this file for scanning._____no_output_____

from gimmemotifs.motif import motif_from_consensus
from gimmemotifs.fasta import Fasta

f = Fasta("test.small.fa")
m = motif_from_consensus("TGAsTCA")

m.pwm_scan(f)_____no_output_____

This return a dictionary with the sequence names as keys. The value is a list with positions where the motif matches. Here, as the AP1 motif is a palindrome, you see matches on both forward and reverse strand. This is more clear when we use `pwm_scan_all()` that returns position, score and strand for every match._____no_output_____

m.pwm_scan_all(f)_____no_output_____

The number of matches to return is set to 50 by default, you can control this by setting the `nreport` argument. Use `scan_rc=False` to only scan the forward orientation.
_____no_output_____

m.pwm_scan_all(f, nreport=1, scan_rc=False)_____no_output_____

While this functionality works, it is not very efficient. To scan many motifs in potentially many sequences, use the functionality in the `scanner` module. If you only want the best match per sequence, there is a utility function called `scan_to_best_match`, otherwise, use the `Scanner` class._____no_output_____

from gimmemotifs.motif import motif_from_consensus
from gimmemotifs.scanner import scan_to_best_match

m1 = motif_from_consensus("TGAsTCA")
m1.id = "AP1"
m2 = motif_from_consensus("CGCG")
m2.id = "CG"
motifs = [m1, m2]

print("motif\tpos\tscore")
result = scan_to_best_match("test.small.fa", motifs)
for motif, matches in result.items():
    for match in matches:
        print("{}\t{}\t{}".format(motif, match[1], match[0]))
motif	pos	score
AP1	0	-20.052563923836903
AP1	6	9.029486018303187
AP1	0	8.331550321011443
CG	0	-18.26379789133924
CG	0	5.554366880674296
CG	0	-7.743307225501047

The matches are in the same order as the sequences in the original file.

While this function can be very useful, a Scanner instance is much more flexible. You can scan different input formats (BED, FASTA, regions), and control the thresholds and output.

As an example we will use the file `Gm12878.CTCF.top500.w200.fa` that contains 500 top CTCF peaks. We will get the CTCF motif and scan this file in a number of different ways.
_____no_output_____

from gimmemotifs.motif import default_motifs
from gimmemotifs.scanner import Scanner
from gimmemotifs.fasta import Fasta
import numpy as np

# Input file
fname = "Gm12878.CTCF.top500.w200.fa"

# Select the CTCF motif from the default motif database
motifs = [m for m in default_motifs() if "CTCF" in m.factors['direct']][:1]

# Initialize the scanner
s = Scanner()
s.set_motifs(motifs)_____no_output_____

Now let’s get the best score for the CTCF motif for each sequence._____no_output_____

scores = [r[0] for r in s.best_score("Gm12878.CTCF.top500.w200.fa")]
print("{}\t{:.2f}\t{:.2f}\t{:.2f}".format(
    len(scores),
    np.mean(scores),
    np.min(scores),
    np.max(scores)
    ))500	11.00	1.45	15.07

In many cases you’ll want to set a threshold. In this example we’ll use a 1% FPR threshold, based on scanning randomly selected sequences from the hg38 genome. The first time you run this, it will take a while. However, the tresholds will be cached. This means that for the same combination of motifs and genome, the previously generated threshold will be used.
_____no_output_____

# Set a 1% FPR threshold based on random hg38 sequence
s.set_genome("hg38")
s.set_threshold(fpr=0.01)

# get the number of sequences with at least one match
counts = [n[0] for n in s.count("Gm12878.CTCF.top500.w200.fa", nreport=1)]
print(counts[:10])2018-12-05 02:18:08,850 - INFO - Using default background: genome hg38 with length 200
2018-12-05 02:18:08,853 - INFO - Using background: genome hg38 with length 200
# or the grand total of number of sequences with 1 match
print(s.total_count("Gm12878.CTCF.top500.w200.fa", nreport=1))[414]
# Scanner.scan() just gives all information
seqs = Fasta("Gm12878.CTCF.top500.w200.fa")[:10]
for i,result in enumerate(s.scan(seqs)):
    seqname = seqs.ids[i]
    for m,matches in enumerate(result):
        motif = motifs[m]
        for score, pos, strand in matches:
            print(seqname, motif, score, pos, strand)chr11:190037-190237 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 11.987579910503003 142 1
chr11:190037-190237 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 9.366964008790466 21 1
chr11:190037-190237 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 9.049239042402315 81 1
chr14:106873577-106873777 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 15.066074431157894 119 1
chr14:106873577-106873777 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 14.695942248831264 82 1
chr14:106873577-106873777 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 12.362503901152305 26 1
chr14:106873577-106873777 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 9.885395021504959 158 1
chr14:106873577-106873777 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 9.035150927051049 100 1
chr14:106873577-106873777 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 8.943385403326214 6 1
chr14:106765204-106765404 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 15.066074431157894 144 1
chr14:106765204-106765404 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 14.76300111320958 184 1
chr14:106765204-106765404 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 14.629818549380293 164 1
chr14:106765204-106765404 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 13.7098269913903 26 1
chr14:106765204-106765404 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 12.732636083478935 125 1
chr14:106765204-106765404 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 12.180200548235172 66 1
chr15:22461178-22461378 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 15.066074431157894 27 1
chr15:22461178-22461378 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 15.066074431157894 184 1
chr15:22461178-22461378 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 14.237178252975294 66 1
chr15:22461178-22461378 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 12.362503901152305 146 1
chr15:22461178-22461378 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 11.986694533589388 125 1
chr15:22461178-22461378 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 11.010111555985224 6 1
chr14:107119996-107120196 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 12.732636083478935 36 1
chr14:107119996-107120196 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 12.732636083478935 94 1
chr14:107119996-107120196 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 12.732636083478935 152 1
chr14:107119996-107120196 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 10.821419305539889 74 1
chr14:107119996-107120196 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 10.75850548012932 16 1
chr14:107119996-107120196 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 10.75850548012932 132 1
chr14:107238917-107239117 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 15.066074431157894 91 1
chr14:107238917-107239117 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 12.180200548235172 33 1
chr14:107238917-107239117 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 10.065681099588275 14 1
chr14:107238917-107239117 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 9.248968117435332 53 1
chr14:107238917-107239117 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 9.248968117435332 111 1
chr6:53036754-53036954 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 9.03332830388423 62 -1
chr14:107147705-107147905 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 14.607310435301924 32 1
chr14:107147705-107147905 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 14.171054553524323 148 1
chr14:107147705-107147905 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 12.015417890970234 91 1
chr14:107147705-107147905 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 12.015417890970234 129 1
chr14:50328834-50329034 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 11.417325296846556 133 -1
chr1:114889205-114889405 GM.5.0.C2H2_ZF.0024_syGCCmyCTrGTGG 10.747636638875207 124 -1

# Finding de novo motifs

Let’s take the `Gm12878.CTCF.top500.w200.fa` file as example again. For a basic example we’ll just use two motif finders, as they’re quick to run.
_____no_output_____

from gimmemotifs.denovo import gimme_motifs

peaks = "Gm12878.CTCF.top500.w200.fa"
outdir = "CTCF.gimme"
params = {
    "tools": "Homer,BioProspector",
    "genome": "hg38",
    }

motifs = gimme_motifs(peaks, outdir, params=params)2018-12-05 02:18:10,850 - INFO - starting full motif analysis
2018-12-05 02:18:10,853 - INFO - preparing input (FASTA)
not enough random sequences found for 0.7000000000000001 <= GC < 0.75 (83 instead of 100)
2018-12-05 02:19:19,484 - INFO - starting motif prediction (medium)
2018-12-05 02:19:19,487 - INFO - tools: BioProspector, Homer
2018-12-05 02:19:20,146 - INFO - all jobs submitted
2018-12-05 02:19:23,902 - INFO - Homer_width_5 finished, found 5 motifs
2018-12-05 02:19:24,247 - INFO - Homer_width_6 finished, found 5 motifs
2018-12-05 02:19:25,217 - INFO - Homer_width_7 finished, found 5 motifs
2018-12-05 02:19:26,671 - INFO - Homer_width_8 finished, found 5 motifs
2018-12-05 02:19:28,930 - INFO - Homer_width_9 finished, found 5 motifs
2018-12-05 02:19:29,602 - INFO - Homer_width_10 finished, found 5 motifs
2018-12-05 02:19:30,393 - INFO - BioProspector_width_5 finished, found 5 motifs
2018-12-05 02:19:30,642 - INFO - BioProspector_width_6 finished, found 5 motifs
2018-12-05 02:19:31,293 - INFO - BioProspector_width_7 finished, found 5 motifs
2018-12-05 02:19:31,892 - INFO - BioProspector_width_8 finished, found 5 motifs
2018-12-05 02:19:32,083 - INFO - BioProspector_width_9 finished, found 5 motifs
2018-12-05 02:19:32,479 - INFO - BioProspector_width_10 finished, found 5 motifs
2018-12-05 02:19:41,497 - INFO - predicted 60 motifs
2018-12-05 02:19:41,613 - INFO - 50 motifs are significant
2018-12-05 02:19:41,704 - INFO - clustering 50 motifs.
2018-12-05 02:21:00,349 - INFO - creating reports
2018-12-05 02:22:17,818 - INFO - finished
2018-12-05 02:22:17,822 - INFO - output dir: CTCF.gimme
2018-12-05 02:22:17,825 - INFO - report: CTCF.gimme/motif_report.html

This will basically run the same pipeline as the `gimme motifs` command. All output files will be stored in outdir and `gimme_motifs` returns a `list` of `Motif` instances. If you only need the motifs but not the graphical report, you can decide to skip it by setting `create_report` to `False`. Additionally, you can choose to skip clustering (`cluster=False`) or to skip calculation of significance (`filter_significant=False`). For instance, the following command will only predict motifs and cluster them.
_____no_output_____

motifs = gimme_motifs(peaks, outdir,
    params=params, filter_significant=False, create_report=False)2018-12-05 02:22:17,889 - INFO - starting full motif analysis
2018-12-05 02:22:17,893 - INFO - preparing input (FASTA)
not enough random sequences found for 0.7000000000000001 <= GC < 0.75 (271 instead of 290)
2018-12-05 02:22:47,000 - INFO - starting motif prediction (medium)
2018-12-05 02:22:47,002 - INFO - tools: BioProspector, Homer
2018-12-05 02:22:47,928 - INFO - all jobs submitted
2018-12-05 02:22:51,852 - INFO - Homer_width_5 finished, found 5 motifs
2018-12-05 02:22:52,728 - INFO - Homer_width_7 finished, found 5 motifs
2018-12-05 02:22:53,196 - INFO - Homer_width_6 finished, found 5 motifs
2018-12-05 02:22:54,898 - INFO - Homer_width_8 finished, found 5 motifs
2018-12-05 02:22:56,287 - INFO - Homer_width_9 finished, found 5 motifs
2018-12-05 02:22:57,110 - INFO - Homer_width_10 finished, found 5 motifs
2018-12-05 02:22:58,226 - INFO - BioProspector_width_5 finished, found 5 motifs
2018-12-05 02:22:59,184 - INFO - BioProspector_width_6 finished, found 5 motifs
2018-12-05 02:23:00,207 - INFO - BioProspector_width_7 finished, found 5 motifs
2018-12-05 02:23:00,756 - INFO - BioProspector_width_8 finished, found 5 motifs
2018-12-05 02:23:00,905 - INFO - BioProspector_width_9 finished, found 5 motifs
2018-12-05 02:23:01,666 - INFO - BioProspector_width_10 finished, found 5 motifs
2018-12-05 02:23:09,414 - INFO - predicted 60 motifs
2018-12-05 02:23:09,503 - INFO - not filtering for significance
2018-12-05 02:23:09,614 - INFO - clustering 60 motifs.
2018-12-05 02:25:05,541 - INFO - finished
2018-12-05 02:25:05,546 - INFO - output dir: CTCF.gimme
2018-12-05 02:25:05,548 - INFO - report: CTCF.gimme/motif_report.html

All parameters for motif finding are set by the `params` argument_____no_output_____Although the `gimme_motifs` function is probably the easiest way to run the `de novo` finding tools, you can also run any of the tools directly. In this case you would also have to supply the background file if the specific tool requires it._____no_output_____

from gimmemotifs.tools import get_tool
from gimmemotifs.background import MatchedGcFasta

m = get_tool("homer")  # tool name is case-insensitive

# Create a background fasta file with a similar GC%
fa = MatchedGcFasta("TAp73alpha.fa", number=1000)
fa.writefasta("bg.fa")

# Run motif prediction
params = {
    "background": "bg.fa",
    "width": "20",
    "number": 5,
}

motifs, stdout, stderr = m.run("TAp73alpha.fa", params=params)
print(motifs[0].to_consensus())nnnCnTGynnnGrCwTGyyn

# Motif statistics

With some motifs, a sample file and a background file you can calculate motif statistics. Let’s say I wanted to know which of the p53-family motifs is most enriched in the file TAp73alpha.fa.

First, we’ll generate a GC%-matched genomic background. Then we only select p53 motifs.
_____no_output_____

from gimmemotifs.background import MatchedGcFasta
from gimmemotifs.fasta import Fasta
from gimmemotifs.stats import calc_stats
from gimmemotifs.motif import default_motifs

sample = "TAp73alpha.fa"
bg = MatchedGcFasta(sample, genome="hg19", number=1000)

motifs = [m for m in default_motifs() if any(f in m.factors['direct'] for f in ["TP53", "TP63", "TP73"])]

stats = calc_stats(motifs, sample, bg)

print("Stats for", motifs[0])
for k, v in stats[str(motifs[0])].items():
    print(k,v)

print()

best_motif = sorted(motifs, key=lambda x: stats[str(x)]["recall_at_fdr"])[-1]
print("Best motif (recall at 10% FDR):", best_motif)Stats for GM.5.0.p53.0001_rCATGyCCnGrCATGy
recall_at_fdr 0.833
fraction_fpr 0.416
score_at_fpr 9.05025905735
enr_at_fpr 41.6
max_enrichment 55.5
phyper_at_fpr 3.33220067463e-132
mncp 1.85474606318
roc_auc 0.9211925
roc_auc_xlim 0.0680115
pr_auc 0.927368602993
max_fmeasure 0.867519181586
ks_pvalue 0.0
ks_significance inf

Best motif (recall at 10% FDR): GM.5.0.p53.0001_rCATGyCCnGrCATGy

A lot of statistics are generated and you will not always need all of them. You can choose one or more specific metrics with the additional `stats` argument.
_____no_output_____

metrics = ["roc_auc", "recall_at_fdr"]
stats = calc_stats(motifs, sample, bg, stats=metrics)

for metric in metrics:
    for motif in motifs:
        print("{}\t{}\t{:.2f}".format(
            motif.id, metric, stats[str(motif)][metric]
            ))GM.5.0.p53.0001	roc_auc	0.92
GM.5.0.p53.0003	roc_auc	0.89
GM.5.0.p53.0004	roc_auc	0.91
GM.5.0.p53.0005	roc_auc	0.86
GM.5.0.p53.0006	roc_auc	0.80
GM.5.0.p53.0007	roc_auc	0.87
GM.5.0.p53.0008	roc_auc	0.82
GM.5.0.p53.0010	roc_auc	0.80
GM.5.0.p53.0011	roc_auc	0.85
GM.5.0.p53.0001	recall_at_fdr	0.83
GM.5.0.p53.0003	recall_at_fdr	0.64
GM.5.0.p53.0004	recall_at_fdr	0.74
GM.5.0.p53.0005	recall_at_fdr	0.58
GM.5.0.p53.0006	recall_at_fdr	0.19
GM.5.0.p53.0007	recall_at_fdr	0.66
GM.5.0.p53.0008	recall_at_fdr	0.18
GM.5.0.p53.0010	recall_at_fdr	0.20
GM.5.0.p53.0011	recall_at_fdr	0.53

# Motif comparison_____no_output_____

from gimmemotifs.comparison import MotifComparer
from gimmemotifs.motif import motif_from_consensus
from gimmemotifs.motif import read_motifs_____no_output_____

Compare two motifs_____no_output_____

m1 = motif_from_consensus("RRRCATGYYY")
m2 = motif_from_consensus("TCRTGT")

mc = MotifComparer()
score, pos, orient = mc.compare_motifs(m1, m2)

if orient == -1:
    m2 = m2.rc()
pad1, pad2 = "", ""
if pos < 0:
    pad1 = " " * -pos
elif pos > 0:
    pad2 =" " * pos
print(pad1 + m1.to_consensus())
print(pad2 + m2.to_consensus())rrrCATGyyy
  ACAyGA

Find closest match in a motif database_____no_output_____

motifs = [
    motif_from_consensus("GATA"),
    motif_from_consensus("NTATAWA"),
    motif_from_consensus("ACGCG"),
]

mc = MotifComparer()
results = mc.get_closest_match(motifs, dbmotifs=read_motifs("HOMER"), metric="seqcor")

# Load motifs
db = read_motifs("HOMER", as_dict=True)

for motif in motifs:
    match, scores = results[motif.id]
    print("{}: {} - {:.3f}".format(motif.id, match, scores[0]))
    dbmotif = db[match]
    orient = scores[2]
    if orient == -1:
        dbmotif = dbmotif.rc()
    padm, padd = 0, 0
    if scores[1] < 0:
        padm = -scores[1]
    elif scores[1] > 0:
        padd = scores[1]
    print(" " * padm + motif.to_consensus())
    print(" " * padd + dbmotif.to_consensus())
    print()GATA: AGATAASR_GATA3(Zf)/iTreg-Gata3-ChIP-Seq(GSE20898)/Homer - 0.823
 GATA
AGATAAnr

NTATAWA: NGYCATAAAWCH_CDX4(Homeobox)/ZebrafishEmbryos-Cdx4.Myc-ChIP-Seq(GSE48254)/Homer - 0.747
  nTATAwA
nnynrTAAAnnn

ACGCG: NCCACGTG_c-Myc(bHLH)/LNCAP-cMyc-ChIP-Seq(Unpublished)/Homer - 0.744
 ACGCG
CACGTGGn


# Notebook from jgarciasuarez/fundamental_mode_resonance_inhomogeneous_soil
Path: Fundamental Resonant Mode Inhomogeneous Soil Deposits.ipynb

# On the Fundamental Resonant Mode of Inhomogeneous Soild Deposits

This notebook details the calculations and the generation of results in "On the fundamental resonant mode of inhomogeneous soil deposits". The authors recommend using this notebook as the paper is being read. The references to equations and figures correspond to those in the text.

_Joaquin Garcia-Suarez, 2019 (All rights reserved)_

## Import python packages_____no_output_____

import numpy as np
import matplotlib.pyplot as plt
import sympy as sym
import mpmath as mp
import cmath
import itertools
import array as arr
from scipy import special
from scipy.special import jv as besselJ
from scipy.special import yv as besselY
from scipy.optimize import fsolve
from math import pi as Pi
from cmath import sqrt as sqrt_____no_output_____

Use inline magic to display plots on notebook_____no_output_____

%matplotlib inline_____no_output_____

## Auxiliary Parameters_____no_output_____Parameters necessary to evaluate the exact response corresponding the "generalized-parabola distribution" (Mylonakis et. al 2013):_____no_output_____

def beta(alpha):
    return alpha**0.5_____no_output_____def b(alpha,n):
    return beta(alpha)**(1/n)_____no_output_____def q(alpha,n):
    return 1.0-b(alpha,n)_____no_output_____def psi(n):
    return (1-2*n)/2_____no_output_____def ell(n):
    return 2(1-n)_____no_output_____def nu(n):
    return (2*n-1)/2/(1-n)_____no_output_____def lambd(alpha,n,r,delta):
    auxval=r/sqrt(1+1j*delta)/(1-n)/(1-b(alpha,n))
    return auxval_____no_output_____

Shear-wave velocity distribution ("generalized parabola"), eq.(3) in the text:_____no_output_____

def f(eta,n,alpha):
    return (1+(beta(alpha)**(1/n)-1)*eta)**n_____no_output_____

## Previous and new results used in the paper (for generalized parabola distribution)_____no_output_____### Exact solutions for generalized parabola (Rovithis et al. 2011)_____no_output_____Base-to-top transfer function, eq.(7):_____no_output_____

def TFR(alpha,n,r,delta):
    aux_value=2/Pi*(b(alpha,n)**(psi(n)-1+n))/lambd(alpha,n,r,delta)*\
    (besselJ(nu(n)+1,lambd(alpha,n,r,delta)*b(alpha,n)**(1-n))*\
    besselY(nu(n),lambd(alpha,n,r,delta))-\
    besselY(nu(n)+1,lambd(alpha,n,r,delta)*b(alpha,n)**(1-n))*\
    besselJ(nu(n),lambd(alpha,n,r,delta)))**(-1)
    return aux_value_____no_output_____

Function to find the exact fundamental frequency_____no_output_____

def findR(alpha,n):
    aux_val=lambda r: abs(besselJ(nu(n)+1,lambd(alpha,n,r,0)*b(alpha,n)**(1-n))*\
    besselY(nu(n),lambd(alpha,n,r,0))-\
    besselY(nu(n)+1,lambd(alpha,n,r,0)*b(alpha,n)**(1-n))*\
    besselJ(nu(n),lambd(alpha,n,r,0)))
    return float(fsolve(aux_val,1))_____no_output_____

Vertical displacement evolution across stratum, eq(5):_____no_output_____

def Uexact(alpha,n,r,delta,eta):
    aux_value=((b(alpha,n)+q(alpha,n)*(1-eta))**psi(n))*\
    (besselJ(nu(n)+1,lambd(alpha,n,r,delta)*b(alpha,n)**(1-n))*\
    besselY(nu(n),lambd(alpha,n,r,delta)*(b(alpha,n)+q(alpha,n)*(1-eta))**(1-n))-\
    besselY(nu(n)+1,lambd(alpha,n,r,delta)*b(alpha,n)**(1-n))*\
    besselJ(nu(n),lambd(alpha,n,r,delta)*(b(alpha,n)+q(alpha,n)*(1-eta))**(1-n)))*\
    (besselJ(nu(n)+1,lambd(alpha,n,r,delta)*b(alpha,n)**(1-n))*\
    besselY(nu(n),lambd(alpha,n,r,delta))-\
    besselY(nu(n)+1,lambd(alpha,n,r,delta)*b(alpha,n)**(1-n))*\
    besselJ(nu(n),lambd(alpha,n,r,delta)))**(-1)
    return aux_value_____no_output_____

### Estimate of the fundamental frequency applying Rayleigh Quotient (Mylonakis et al. 2011)_____no_output_____This function returns the value of the Rayleigh Quotient, eq.(4): _____no_output_____

def RayEst(alpha,n):
    aux_value2=(15/2*(-1-3*n-2*n**2+(1+2*n)*(3+2*n)*alpha**(1/2/n)-\
    (1+n)*(3+2*n)*alpha**(1/n)+alpha**(1+3/2/n))/(1+n)/(1+2*n)/(3+2*n)\
    /(-1+alpha**(1/2/n))**3)**(1/2)
    return aux_value2_____no_output_____

### Results based on asymptotic behavior of exact solution (Garcia-Suarez, Seylabi and Asimaki, 2019)_____no_output_____Base-to-top transfer function, eq.(8):_____no_output_____

def Asy_TR(alpha,n,r,delta):
    aux_value=(alpha**(-1/4))/np.cos((1-alpha**((1-n)/2/n))/(1-n)/(1-b(alpha,n))*r/sqrt(1+1j*DE))
    return aux_value_____no_output_____

Corresponding value of fundamental frequency_____no_output_____

def AsyEst(alpha,n):
    aux_value2=(1-n)*(1-beta(alpha)**(1/n))/(1-beta(alpha)**((1-n)/n))
    return aux_value2_____no_output_____

### New results deriving from the resonance argument_____no_output_____Estimate of the displacement field, eq.(15): _____no_output_____

def Uest(alpha,n,r,delta,eta):
    auxV=1-(r**2)/delta*1j*((1-2*b(alpha,n)+2*n*(-1+b(alpha,n))+(-1+b(alpha,n)*\
    (2+2*n*(-1+eta)-eta)-2*n*(-1+eta)+eta)*(1+(b(alpha,n)-1)*eta)\
    **(1-2*n))/(2*(-1+n)*(-1+2*n)*(-1+b(alpha,n))**2))
    return auxV _____no_output_____

Dichotomy for displacement at resonance, eq.(18) (converted to total displacements):_____no_output_____

def Uest2(delta):
    auxV=1-1/delta*1j
    return auxV _____no_output_____

The new estimate of the fundamental frequency based on the resonance argument, eq.(20b):_____no_output_____

def IntegralEst(alpha,n):
    aux_value1=(Pi/8*(alpha-2*n*alpha+2*(-1+n)*alpha**(1+1/2/n)+alpha**(1/n))/\
               ((-1+n)*(-1+2*n)*alpha*(-1+b(alpha,n))**2))**(-1/2)
    return aux_value1_____no_output_____

## Generate Figure 4 and 5: comparison of magnitude and phase of displacement field at resonance, assuming inhomogeneity given by gen. parabola
Fix the first set of values to input:_____no_output_____

NN=0.1
BETA=0.1
DE=0.1
ALPHA=BETA**2
#find the corresponding frequency first
RR=findR(ALPHA,NN)_____no_output_____

### Figure 4_____no_output_____

y=np.linspace(1,0)
plt.figure(figsize=(8,8))
plt.tight_layout()
plt.subplot(1,2,1)
plt.plot(abs(Uexact(ALPHA,NN,RR,DE,y)),y,'r',\
         abs(Uest(ALPHA,NN,RayEst(ALPHA,NN),DE,y)),y,'gray',\
         abs(np.cos(Pi/2/sqrt(1+1j*DE)*(1-y))/np.cos(Pi/2/sqrt(1+1j*DE))),y,'b',\
         abs(Uest2(DE))*np.ones(50),y,'k--');

plt.legend(('Exact', 'Estimate #1','Homogeneus (base)','Estimate #2'),
           loc='upper left')
plt.title('Displacement magnitude and phase during resonance across stratum')

plt.xlabel('$|u/X_g|$',fontsize=15);
plt.ylabel('$\eta$',fontsize=18);

plt.subplot(1,2,2)
plt.plot(np.angle(Uexact(ALPHA,NN,RR,DE,y)),y,'r',\
         np.angle(Uest(ALPHA,NN,RR,DE,y)),y,'gray',\
         np.angle(np.cos(Pi/2/sqrt(1+1j*DE)*(1-y))/np.cos(Pi/2/sqrt(1+1j*DE))),y,'b',\
         np.angle(Uest2(DE))*np.ones(50),y,'k--');

plt.xlabel('$arg(u/X_g)$',fontsize=15);_____no_output_____

### Figure 5
New set of values_____no_output_____

NN2=0.6
BETA2=0.3
ALPHA2=BETA2**2
#find the corresponding frequency
RR2=findR(ALPHA2,NN2)_____no_output_____plt.figure(figsize=(8,8))
plt.tight_layout()
plt.subplot(1,2,1)
plt.title('Displacement magnitude and phase during resonance across stratum')
plt.plot(abs(Uexact(ALPHA2,NN2,RR2,DE,y)),y,'r',\
         abs(Uest(ALPHA2,RayEst(ALPHA2,NN2),RR2,DE,y)),y,'gray',\
         abs(np.cos(Pi/2/sqrt(1+1j*DE)*(1-y))/np.cos(Pi/2/sqrt(1+1j*DE))),y,'b',\
         abs(Uest2(DE))*np.ones(50),y,'k--');

plt.xlabel('$|u/X_g|$',fontsize=15);
plt.ylabel('$\eta$',fontsize=18);

plt.subplot(1,2,2)
plt.plot(np.angle(Uexact(ALPHA2,NN2,RR2,DE,y)),y,'r',\
         np.angle(Uest(ALPHA2,NN2,RayEst(ALPHA2,NN2),DE,y)),y,'gray',\
         np.angle(np.cos(Pi/2/sqrt(1+1j*DE)*(1-y))/np.cos(Pi/2/sqrt(1+1j*DE))),y,'b',\
         np.angle(Uest2(DE))*np.ones(50),y,'k--');

plt.xlabel('$arg(u/U)$',fontsize=15);
plt.legend(('Exact', 'Estimate #1','Homogeneus (base)','Estimate #2'),
           loc='upper right');_____no_output_____

## Figure 6: Comparison of fundamental frequency of inhomoegenous stratum (generalized parabola)
_____no_output_____

nn=np.linspace(0.01,0.99)
plotR=[]
for k in range(0,len(nn)):
    plotR.append(2/Pi*findR(0.2**2,nn[k]))
# Plot to compare against Mylonakis
plt.figure(figsize=(8,10))
plt.tight_layout()
plt.subplot(3,1,1)
# beta=0.2
plt.plot(nn,plotR,\
         nn,2/Pi*IntegralEst(0.2**2,nn),\
         nn,2/Pi*RayEst(0.2**2,nn),\
         nn,AsyEst(0.2**2,nn));
plt.axis([0, 1, 0, 1])

plt.legend(('Exact','Estimate #1','Rayleigh Quotient','Asymptotics'),
           loc='lower left')
plt.title('a) $c_{s,top} / c_{s,base}=0.2$')

plt.ylabel('$\omega_s/\omega_{s,base}$',fontsize=18);
# beta=0.5
plt.subplot(3,1,2)
plotR=[]
for k in range(0,len(nn)):
    plotR.append(2/Pi*findR(0.5**2,nn[k]))
plt.plot(nn,plotR,\
         nn,2/Pi*IntegralEst(0.5**2,nn),\
         nn,2/Pi*RayEst(0.5**2,nn),\
         nn,AsyEst(0.5**2,nn));
plt.axis([0, 1, 0, 1])

plt.legend(('Exact','Estimate #1','Rayleigh Quotient','Asymptotics'),
           loc='lower left')
plt.title('b) $c_{s,top} / c_{s,base}=0.5$')

plt.ylabel('$\omega_s/\omega_{s,base}$',fontsize=18);
# beta=0.8
plt.subplot(3,1,3)
plotR=[]
for k in range(0,len(nn)):
    plotR.append(2/Pi*findR(0.8**2,nn[k]))
plt.plot(nn,plotR,\
         nn,2/Pi*IntegralEst(0.8**2,nn),\
         nn,2/Pi*RayEst(0.8**2,nn),\
         nn,AsyEst(0.8**2,nn));
plt.axis([0, 1, 0, 1])

plt.legend(('Exact','Estimate #1','Rayleigh Quotient','Asymptotics'),
           loc='lower left')
plt.title('c) $c_{s,top} / c_{s,base}=0.8$')

plt.ylabel('$\omega_s/\omega_{s,base}$',fontsize=18);
plt.xlabel('$n$',fontsize=18);_____no_output_____

## Generate Figure 7: amplification comparison assuming gen. parabola_____no_output_____

rr=np.linspace(0.1,6*Pi/2,1000)
DE=0.15
NN=0.499
BETA=0.9
ALPHA=BETA**2
# Plot to compare amplitude
plt.figure(figsize=(8,10))
plt.tight_layout()
# FIRST TILE
plt.subplot(3,1,1)
plt.title('a) $c_{s,top} / c_{s,base}=0.9$, damping=15%')
plt.plot(rr*2/Pi,abs(TFR(ALPHA,NN,rr,DE)));
plt.plot(rr*2/Pi,abs(Asy_TR(ALPHA,NN,rr,DE)));
# vertical lines
w_locus=RayEst(ALPHA,NN) # frequency
amplitude=abs(Uest(ALPHA,NN,RayEst(ALPHA,NN),DE,1))
plt.plot([w_locus/(Pi/2),w_locus/(Pi/2)],[0,amplitude],'k--')
plt.axis([0, 6, 0, 15])
w_locus2=IntegralEst(ALPHA,NN) # frequency
amplitude2=4/Pi/DE
plt.plot([w_locus2/(Pi/2),w_locus2/(Pi/2)],[0,amplitude2],'g')
plt.axis([0, 6, 0, 15])
# horizontal lines
plt.plot([0,w_locus/(Pi/2)],[amplitude,amplitude],'k--')
plt.plot([0,w_locus2/(Pi/2)],[amplitude2,amplitude2],'g')

plt.legend(('Exact','Asymptotics','Estimate based on RQ','Estimate based on resonance argument'),
           loc='upper right')

plt.ylabel('$A(\omega)$',fontsize=18);
# SECOND TILE
DE=0.10
BETA=0.5
ALPHA=BETA**2
plt.subplot(3,1,2)
plt.title('b) $c_{s,top} / c_{s,base}=0.5$, damping=10%')
plt.plot(rr*2/Pi,abs(TFR(ALPHA,NN,rr,DE)));
plt.plot(rr*2/Pi,abs(Asy_TR(ALPHA,NN,rr,DE)));
# vertical lines
w_locus=RayEst(ALPHA,NN) # frequency
amplitude=abs(Uest(ALPHA,NN,RayEst(ALPHA,NN),DE,1))
plt.plot([w_locus/(Pi/2),w_locus/(Pi/2)],[0,amplitude],'k--')
plt.axis([0, 6, 0, 15])
w_locus2=IntegralEst(ALPHA,NN) # frequency
amplitude2=4/Pi/DE
plt.plot([w_locus2/(Pi/2),w_locus2/(Pi/2)],[0,amplitude2],'g')
plt.axis([0, 6, 0, 20])
# horizontal lines
plt.plot([0,w_locus/(Pi/2)],[amplitude,amplitude],'k--')
plt.plot([0,w_locus2/(Pi/2)],[amplitude2,amplitude2],'g')

plt.ylabel('$A(\omega)$',fontsize=18);
# THIRD TILE
DE=0.05
BETA=0.1
ALPHA=BETA**2
plt.subplot(3,1,3)
plt.title('c) $c_{s,top} / c_{s,base}=0.1$, damping=5%')
plt.plot(rr*2/Pi,abs(TFR(ALPHA,NN,rr,DE)));
plt.plot(rr*2/Pi,abs(Asy_TR(ALPHA,NN,rr,DE)));
# vertical lines
w_locus=RayEst(ALPHA,NN) # frequency
amplitude=abs(Uest(ALPHA,NN,RayEst(ALPHA,NN),DE,1))
plt.plot([w_locus/(Pi/2),w_locus/(Pi/2)],[0,amplitude],'k--')
plt.axis([0, 6, 0, 15])
w_locus2=IntegralEst(ALPHA,NN) # frequency
amplitude2=4/Pi/DE
plt.plot([w_locus2/(Pi/2),w_locus2/(Pi/2)],[0,amplitude2],'g')
plt.axis([0, 6, 0, 40])
# horizontal lines
plt.plot([0,w_locus/(Pi/2)],[amplitude,amplitude],'k--')
plt.plot([0,w_locus2/(Pi/2)],[amplitude2,amplitude2],'g')

plt.ylabel('$A(\omega)$',fontsize=18);
plt.xlabel('$\omega/\omega_{s,base}$',fontsize=18);_____no_output_____

## Generate Figure 8: amplification comparison layered site¶

### Function to calculate transfer function for discontinuous layers
This corresponds to an implementation of the classic procedure, which is detailed, e.g., in Kramer's(1996)_____no_output_____

def getAmp(alpha_m,H,V_base,Vs,delta,hm):
    Amp=np.zeros(len(om))
    for vv in range(np.size(Amp)):
        L=np.array([[1, 0], [0, 1]])
        for uu in range(len(alpha_m)):
            hmkm=1j*Pi/2*hm[uu]/H*V_base/Vs[uu]*om[vv]*(1-1j*delta/2)
            Laux=np.array([[0.5*(1+alpha_m[uu])*cmath.exp(hmkm),\
            0.5*(1-alpha_m[uu])*cmath.exp(-hmkm)],\
            [0.5*(1-alpha_m[uu])*cmath.exp(hmkm),\
            0.5*(1+alpha_m[uu])*cmath.exp(-hmkm)]])
            L=np.dot(Laux,L) #the new matrix multiply the previous one from the left
        Amp[vv]=2/abs(L[0,0]+L[0,1]+L[1,0]+L[1,1])
    return Amp_____no_output_____

### Function to calculate the integral estimate of the fundamental frequency for layered site_____no_output_____

def getWn(ZZ,Vs,depth):
    # Discretize and normalize Vs into Vs_disc (same #points as ZZ)
    Vs_disc=np.linspace(0,1,1000)
    ii=0
    jj=0
    while ii < len(ZZ):
        # ZZ[ii] in what interval?
        if ZZ[ii]<=depth[jj]: # in the j-th interval
            Vs_disc[ii]=Vs[jj]
        else: # in the next one
            jj+=1
            Vs_disc[ii]=Vs[jj]
        ii+=1
    Vs_disc[-1]=Vs[-1]
    Vs_disc=np.flip(Vs_disc)/Vs[-1]
    # Calculate the weighted harmonic mean of the shear modulus
    C_cor=0
    for ii in range(1000):
        C_cor=C_cor+1/Vs_disc[-(ii+1)]/Vs_disc[-(ii+1)]\
        *ZZ[ii]/H*(ZZ[1]-ZZ[0])/H
    return abs(sqrt(16.0/C_cor/Pi**3))_____no_output_____

Range of frequencies to be used for plots (expressed as multiples of the fundamental frequency of the homogeneous stratum based on the properties at the base)_____no_output_____

om=np.linspace(0,6,1000)_____no_output_____

### Quick Test (Homogeneous case)

Let us run an example divided in multiple layers with the same properties_____no_output_____

DE=0.1
depth=arr.array('f',[20,190,410,518]) # [m]
Vs=arr.array('f',[110,110,110,110]) # Vs distribution [m/s]
#
H=depth[-1] # soft soil depth [m]
ZZ=np.linspace(0,H,1000) # [m]
YY=np.flip(1-ZZ/H) # profile distance from base to top [m]
V_base=Vs[-1] # Vs of the soil in contact with bedrock
# Inter-layer impedance
alpha_m=np.divide(Vs[0:len(Vs)-1],Vs[1:len(Vs)])
alpha_m=alpha_m.tolist()
alpha_m.append(0)
# Layer depth
hm=np.subtract(depth[1:len(depth)],depth[0:len(depth)-1])
hm=np.concatenate(([depth[0]],hm),axis=0)_____no_output_____AmpHom=np.zeros(len(om))
for vv in range(np.size(AmpHom)):
    AmpHom[vv]=abs(1/cmath.cos(Pi/2*om[vv]*(1-1j*DE/2)))_____no_output_____plt.plot(om,getAmp(alpha_m,H,V_base,Vs,DE,hm));
plt.axis([0, 6, 0, 15]);
plt.plot(om,AmpHom,'--')

plt.legend(('Using getAmp','Homogeneous'),
           loc='upper right')

plt.ylabel('$A(\omega)$',fontsize=18);
plt.xlabel('$\omega/\omega_{s,base}$',fontsize=18);
plt.title('IBRH10');_____no_output_____

### KikNet Data: IBRH10_____no_output_____

depth=arr.array('f',[20,190,410,518]) # [m]
Vs=arr.array('f',[110,380,530,850]) # Vs distribution [m/s]
#
H=depth[-1] # soft soil depth [m]
ZZ=np.linspace(0,H,1000) # [m]
YY=np.flip(1-ZZ/H) # profile distance from base to top [m]
V_base=Vs[-1] # Vs of the soil in contact with bedrock
# Inter-layer impedance
alpha_m=np.divide(Vs[0:len(Vs)-1],Vs[1:len(Vs)])
alpha_m=alpha_m.tolist()
alpha_m.append(0)
# Layer depth
hm=np.subtract(depth[1:len(depth)],depth[0:len(depth)-1])
hm=np.concatenate(([depth[0]],hm),axis=0)_____no_output_____DE=0.035
plt.plot(om,getAmp(alpha_m,H,V_base,Vs,DE,hm));
plt.axis([0, 6, 0, 40]);
# vertical lines
w_locus=getWn(ZZ,Vs,depth) # frequency
amplitude=1+Pi*Pi/8/DE
plt.plot([w_locus,w_locus],[0,amplitude],'k--')
# horizontal lines
plt.plot([0,w_locus],[amplitude,amplitude],'k--')

plt.legend(('Exact','Estimate based on resonance argument'),
           loc='upper right')

plt.ylabel('$A(\omega)$',fontsize=18);
plt.xlabel('$\omega/\omega_{s,base}$',fontsize=18);
plt.title('IBRH10');_____no_output_____

### KikNet Data: TKCH08_____no_output_____

depth=arr.array('f',[4,36,78]) # [m]
Vs=arr.array('f',[130,480,590]) # Vs distribution [m/s]
#
H=depth[-1] # soft soil depth [m]
ZZ=np.linspace(0,H,1000) # [m]
YY=np.flip(1-ZZ/H) # profile distance from base to top [m]
V_base=Vs[-1] # Vs of the soil in contact with bedrock
# Inter-layer impedance
alpha_m=np.divide(Vs[0:len(Vs)-1],Vs[1:len(Vs)])
alpha_m=alpha_m.tolist()
alpha_m.append(0)
# Layer depth
hm=np.subtract(depth[1:len(depth)],depth[0:len(depth)-1])
hm=np.concatenate(([depth[0]],hm),axis=0)_____no_output_____DE=0.068
plt.plot(om,getAmp(alpha_m,H,V_base,Vs,DE,hm));
plt.axis([0, 6, 0, 25]);
# vertical lines
w_locus=getWn(ZZ,Vs,depth) # frequency
amplitude=1+Pi*Pi/8/DE
plt.plot([w_locus,w_locus],[0,amplitude],'k--')
# horizontal lines
plt.plot([0,w_locus],[amplitude,amplitude],'k--')

plt.legend(('Exact','Estimate based on resonance argument'),
           loc='upper right')

plt.ylabel('$A(\omega)$',fontsize=18);
plt.xlabel('$\omega/\omega_{s,base}$',fontsize=18);
plt.title('TKCH08');_____no_output_____

### KikNet Data: IBRH17_____no_output_____

depth=arr.array('f',[1,10,90,235,300,380,460]) # [m]
Vs=arr.array('f',[90,250,380,470,540,660,820]) # Vs distribution [m/s]
#
H=depth[-1] # soft soil depth [m]
ZZ=np.linspace(0,H,1000) # [m]
YY=np.flip(1-ZZ/H) # profile distance from base to top [m]
V_base=Vs[-1] # Vs of the soil in contact with bedrock
# Inter-layer impedance
alpha_m=np.divide(Vs[0:len(Vs)-1],Vs[1:len(Vs)])
alpha_m=alpha_m.tolist()
alpha_m.append(0)
# Layer depth
hm=np.subtract(depth[1:len(depth)],depth[0:len(depth)-1])
hm=np.concatenate(([depth[0]],hm),axis=0)_____no_output_____DE=0.147
plt.plot(om,getAmp(alpha_m,H,V_base,Vs,DE,hm));
plt.axis([0, 6, 0, 10]);
# vertical lines
w_locus=getWn(ZZ,Vs,depth) # frequency
amplitude=1+Pi*Pi/8/DE
plt.plot([w_locus,w_locus],[0,amplitude],'k--')
# horizontal lines
plt.plot([0,w_locus],[amplitude,amplitude],'k--')

plt.legend(('Exact','Estimate based on resonance argument'),
           loc='upper right')

plt.ylabel('$A(\omega)$',fontsize=18);
plt.xlabel('$\omega/\omega_{s,base}$',fontsize=18);
plt.title('IBRH17');_____no_output_____