```python
import random

lst1 = [chr(random.randint(97,97+26-1)) for i in range(1024)]
lst2 = [chr(random.randint(65,65+26-1)) for i in range(1024)]
lst3 = [random.randint(0,100) for i in range(1024)]
lst = lst1 + lst2 + lst3
random.shuffle(lst)
print(lst)
```

    ['T', 'J', 'R', 'g', 'l', 'v', 'j', 'M', 'd', 28, 'Q', 'Q', 23, 'I', 'T', 'T', 'u', 'n', 'V', 'o', 'f', 'p', 't', 'b', 'N', 'X', 'U', 0, 3, 46, 84, 48, 'S', 'V', 's', 68, 'U', 'y', 'X', 64, 51, 'c', 24, 'P', 68, 'k', 'w', 'J', 'S', 93, 57, 'U', 'r', 'g', 'l', 'D', 's', 80, 'T', 'o', 95, 's', 'O', 'M', 'P', 'n', 'K', 'M', 96, 46, 'M', 70, 'm', 'E', 'E', 'O', 'x', 'P', 's', 'x', 58, 100, 'x', 56, 'f', 'u', 7, 99, 44, 'b', 'I', 39, 97, 'h', 'd', 8, 'a', 'X', 15, 100, 'U', 68, 'T', 'D', 'W', 'u', 5, 'M', 'q', 'I', 64, 'a', 'J', 81, 'V', 19, 'c', 'r', 'j', 'j', 'R', 'A', 'B', 59, 45, 'c', 'z', 't', 'r', 88, 'X', 'c', 'z', 96, 'I', 'S', 15, 91, 'S', 39, 21, 24, 'J', 's', 81, 68, 'j', 'f', 29, 'L', 'D', 43, 'm', 'L', 'z', 31, 'G', 'K', 28, 73, 74, 'f', 'f', 'v', 'z', 37, 53, 2, 54, 'Z', 37, 'Q', 'b', 'D', 'Y', 'z', 25, 25, 'B', 'l', 'b', 'o', 'X', 'f', 'E', 31, 'Y', 'J', 38, 'o', 'S', 50, 'T', 'g', 'j', 70, 'q', 'x', 'p', 8, 72, 'R', 21, 'l', 76, 9, 27, 'Z', 33, 95, 'H', 'Q', 'S', 'E', 'j', 'g', 61, 'k', 24, 'P', 36, 'm', 6, 58, 'A', 25, 'w', 'T', 'M', 'P', 'O', 'E', 49, 7, 'f', 'M', 'j', 100, 14, 76, 'C', 'z', 'z', 'W', 'h', 'G', 15, 'S', 'K', 'W', 's', 'C', 'o', 'Z', 'H', 'E', 63, 'a', 'O', 'o', 71, 'u', 'W', 51, 50, 91, 'i', 'z', 16, 27, 7, 'H', 27, 60, 18, 'X', 40, 'Z', 'E', 'K', 'g', 'U', 'W', 'J', 'u', 'C', 13, 't', 'Z', 'H', 'P', 'H', 89, 'H', 'e', 'V', 'S', 25, 'e', 'e', 'r', 'L', 'F', 6, 'A', 95, 71, 86, 'L', 1, 'n', 'Z', 'm', 'p', 'D', 'b', 'r', 'G', 'Y', 'u', 'G', 'k', 'N', 28, 9, 'K', 39, 't', 67, 'o', 'D', 'w', 49, 'x', 'Q', 72, 'V', 91, 'X', 'l', 12, 'g', 'A', 74, 'A', 'Q', 's', 'E', 'g', 'w', 79, 'F', 17, 'D', 'I', 'e', 38, 45, 73, 29, 'U', 'y', 'I', 70, 85, 42, 94, 't', 'V', 'g', 'y', 'F', 'B', 'E', 'B', 62, 'H', 'p', 38, 'D', 'L', 'C', 'c', 'P', 6, 'D', 69, 'M', 26, 91, 47, 72, 'j', 'R', 'D', 47, 66, 'I', 'P', 'A', 53, 54, 'G', 'h', 56, 'n', 68, 61, 'e', 6, 89, 'r', 'p', 'U', 41, 'r', 'a', 'f', 'C', 'y', 95, 'H', 54, 'T', 'w', 22, 't', 72, 'T', 'P', 63, 21, 'D', 92, 'q', 'R', 'v', 'k', 62, 'y', 'G', 'o', 'V', 'J', 'g', 85, 'y', 'U', 40, 'e', 'L', 90, 'J', 53, 'W', 'b', 94, 'g', 'L', 'S', 'K', 56, 'f', 'E', 'Z', 'I', 20, 'E', 93, 'y', 'p', 'B', 'x', 'n', 7, 45, 'R', 76, 'r', 't', 'r', 'D', 'B', 56, 'P', 'T', 'd', 't', 'J', 'O', 41, 48, 'I', 84, 'o', 'E', 'r', 45, 'Y', 'z', 93, 'o', 23, 'p', 10, 'w', 'b', 44, 68, 'u', 'u', 'Y', 'T', 'T', 91, 'H', 48, 53, 'H', 'V', 'L', 'B', 'E', 'p', 'D', 'r', 'R', 76, 'U', 51, 9, 28, 56, 'G', 69, 3, 'p', 94, 32, 'Y', 57, 'r', 32, 29, 'R', 68, 'H', 'z', 'A', 'D', 35, 'z', 'd', 'Y', 78, 'i', 92, 24, 14, 'e', 99, 'K', 43, 62, 'c', 'g', 'C', 91, 83, 't', 'O', 'w', 'C', 'f', 'F', 74, 'P', 'i', 'X', 'T', 77, 'e', 'W', 25, 86, 68, 96, 'n', 61, 66, 97, 97, 'x', 11, 'g', 't', 'p', 19, 16, 'E', 18, 'l', 'T', 'H', 'C', 100, 'l', 93, 49, 28, 'R', 'k', 'L', 'g', 'a', 22, 'l', 'O', 'E', 10, 'L', 'S', 'o', 'u', 'R', 72, 'q', 'd', 65, 'Y', 'd', 'h', 'G', 'f', 'F', 80, 'l', 'P', 'g', 't', 'e', 'Y', 'x', 'W', 'M', 'H', 'D', 'H', 71, 95, 'B', 'a', 'q', 68, 77, 25, 'L', 23, 's', 'm', 'f', 'W', 9, 'N', 'L', 'F', 'W', 'B', 'r', 'T', 'C', 'Z', 95, 'W', 'W', 'u', 'Z', 'e', 'E', 'N', 50, 30, 42, 'T', 33, 'v', 'I', 31, 'e', 'x', 'd', 69, 'w', 63, 'k', 'G', 'b', 'C', 'H', 75, 'c', 'h', 75, 73, 'p', 'N', 'w', 'o', 44, 'r', 'K', 'c', 'L', 'V', 'd', 'p', 10, 'N', 54, 'p', 41, 'k', 70, 'X', 88, 62, 't', 'n', 91, 85, 'Q', 'D', 70, 8, 'l', 'e', 'L', 'T', 48, 2, 'u', 'J', 'A', 37, 'j', 'e', 65, 'U', 'm', 30, 'w', 96, 't', 'Q', 'g', 'r', 68, 'z', 17, 11, 'A', 'B', 'L', 85, 23, 73, 'X', 'P', 94, 'X', 'o', 'E', 'z', 'V', 's', 72, 28, 'u', 'j', 'f', 'E', 'P', 70, 'u', 78, 'V', 'K', 'C', 'o', 9, 'p', 'T', 'o', 94, 'v', 'g', 'o', 'E', 'l', 50, 77, 'A', 'M', 'k', 64, 'X', 'S', 33, 'j', 'K', 'z', 'A', 'H', 'i', 'R', 40, 45, 11, 'N', 'X', 26, 45, 'I', 100, 65, 'v', 'A', 31, 'f', 'q', 'A', 'h', 94, 83, 27, 91, 'e', 98, 'J', 'Z', 63, 'r', 'd', 'w', 64, 'a', 'G', 'V', 90, 5, 'J', 25, 'L', 'X', 'x', 'S', 'v', 'S', 'd', 'k', 'w', 99, 'o', 61, 12, 78, 'M', 'O', 'g', 39, 'z', 'm', 'L', 'q', 'W', 'S', 72, 79, 12, 83, 'J', 'Y', 14, 78, 'W', 'A', 'v', 89, 'F', 'q', 'E', 'N', 52, 'm', 'E', 'T', 'T', 'q', 'A', 'O', 'O', 's', 'l', 'Q', 'j', 'e', 'X', 'h', 'o', 76, 'H', 's', 'H', 'J', 49, 'O', 82, 'f', 64, 'L', 'D', 87, 20, 'U', 'r', 22, 100, 'u', 'E', 'H', 36, 'P', 'H', 'f', 'C', 'Y', 'T', 's', 82, 41, 'i', 70, 37, 'X', 'F', 'D', 'Z', 12, 'Z', 85, 30, 'K', 'J', 'p', 'O', 20, 'C', 66, 'p', 15, 'z', 72, 'S', 9, 31, 75, 58, 'n', 'K', 'b', 'P', 46, 'k', 'i', 'J', 'g', 82, 'Q', 12, 'g', 'u', 40, 43, 'S', 'V', 'W', 97, 'G', 'L', 's', 't', 'P', 'z', 'X', 22, 72, 'a', 'Y', 'B', 'I', 'y', 'M', 96, 'R', 'X', 40, 75, 'V', 'M', 'a', 4, 64, 35, 'Q', 'K', 'i', 'R', 50, 65, 'R', 77, 'S', 'P', 'F', 't', 36, 84, 'e', 'g', 100, 'R', 58, 'z', 'r', 'l', 20, 99, 's', 36, 'x', 'Y', 68, 'z', 'W', 'V', 'Z', 'Q', 'K', 'j', 11, 'x', 26, 16, 87, 'c', 'B', 'i', 'm', 'J', 'J', 'b', 'H', 'X', 64, 'Z', 80, 55, 'k', 87, 'J', 'o', 16, 'o', 'r', 'W', 'x', 'l', 'F', 54, 'h', 'n', 34, 73, 29, 'Y', 'b', 'r', 'U', 41, 'o', 't', 'F', 'o', 'B', 'R', 'B', 'p', 'x', 'z', 'r', 'y', 'p', 5, 92, 56, 76, 'q', 'B', 'g', 'R', 'R', 70, 'G', 'p', 'z', 'A', 98, 54, 48, 20, 52, 'N', 'Q', 91, 'U', 'E', 'J', 's', 'D', 'n', 'y', 'l', 'y', 'r', 'C', 62, 'A', 'M', 80, 25, 'c', 'l', 18, 'V', 48, 92, 'c', 'P', 'd', 'U', 'q', 'U', 'M', 'G', 'o', 'P', 'r', 'E', 59, 95, 96, 33, 'V', 'V', 'i', 'J', 76, 45, 20, 9, 'v', 90, 75, 'u', 'g', 't', 'A', 'k', 72, 'O', 89, 'A', 82, 'B', 50, 'r', 'c', 47, 96, 'M', 9, 'x', 'h', 61, 'R', 'j', 'V', 'w', 'd', 'o', 'W', 'e', 38, 'L', 'b', 's', 'L', 7, 'w', 'i', 'u', 'Z', 'w', 88, 'R', 'd', 'L', 'I', 13, 'O', 'Q', 13, 'L', 'L', 'w', 'B', 'k', 20, 86, 'K', 41, 86, 'T', 50, 'e', 'Z', 4, 'e', 61, 'f', 'P', 87, 16, 'v', 65, 'I', 'Y', 'g', 'Y', 'w', 'L', 'X', 26, 19, 'e', 'X', 'C', 'd', 'A', 56, 'K', 'l', 'L', 78, 56, 70, 52, 20, 55, 'l', 'x', 'o', 97, 'o', 69, 27, 38, 'k', 'c', 37, 'K', 'N', 'j', 86, 'y', 'm', 3, 'd', 75, 30, 'w', 'f', 'k', 'W', 43, 'q', 'S', 'R', 45, 's', 36, 'A', 60, 'f', 'k', 'D', 'M', 'r', 'D', 'N', 'S', 'w', 'S', 'F', 56, 39, 54, 'I', 'X', 'E', 'd', 'p', 'u', 'B', 98, 's', 'T', 'Q', 'Y', 20, 'J', 50, 'e', 'p', 29, 'S', 'w', 25, 'o', 'P', 'B', 'M', 'v', 86, 'd', 'p', 'C', 8, 61, 'x', 90, 95, 'N', 'h', 'z', 'v', 'g', 89, 's', 'j', 'v', 'R', 'j', 'P', 'd', 'j', 52, 'w', 'e', 'A', 94, 98, 79, 'r', 'z', 'G', 'f', 1, 'e', 'Y', 64, 'C', 't', 'M', 'y', 92, 'I', 4, 90, 'v', 'K', 'p', 77, 'n', 'F', 10, 47, 'C', 'V', 'N', 'Q', 'O', 18, 'R', 'D', 'P', 'm', 'V', 'F', 'U', 'O', 34, 'P', 'j', 'E', 'N', 99, 'M', 'Y', 57, 65, 66, 'f', 'g', 57, 22, 'F', 'O', 'f', 'q', 'H', 'b', 'C', 'J', 'F', 31, 26, 94, 'Z', 64, 'K', 'A', 'k', 'c', 'U', 'x', 63, 36, 'K', 'S', 62, 'i', 'T', 'T', 71, 74, 'V', 'Y', 38, 'd', 46, 29, 'l', 66, 'i', 'P', 34, 'L', 'Y', 79, 81, 'W', 'W', 'S', 'S', 'p', 29, 69, 83, 46, 20, 'P', 'F', 'n', 'W', 'L', 'r', 'R', 'd', 'y', 'F', 'Y', 27, 'u', 'h', 79, 'R', 'f', 'O', 88, 'c', 'j', 'z', 100, 'Z', 'r', 60, 's', 39, 'q', 'l', 'o', 'r', 'v', 'Q', 39, 60, 54, 'B', 'C', 't', 'Q', 1, 'k', 'h', 'u', 'k', 'F', 55, 82, 92, 'E', 'Y', 'k', 3, 'u', 'p', 'f', 56, 66, 'o', 'C', 'D', 'e', 91, 'M', 'z', 'h', 'B', 'j', 59, 'w', 'G', 55, 'A', 'C', 'O', 'O', 'n', 'D', 'e', 'v', 'I', 35, 'G', 82, 'G', 'u', 'S', 4, 'D', 'k', 12, 'o', 'm', 'n', 'a', 69, 28, 't', 52, 'M', 'u', 'D', 5, 30, 2, 'N', 'F', 'c', 'W', 'i', 'u', 24, 'W', 'K', 'Y', 'e', 'q', 61, 'l', 'r', 'G', 63, 'r', 'l', 69, 'J', 46, 10, 4, 'x', 'q', 8, 48, 76, 'F', 'l', 'U', 'u', 23, 'J', 82, 'M', 'I', 'W', 73, 63, 'k', 'z', 'b', 'j', 23, 'R', 'z', 'J', 'b', 'M', 55, 'G', 'C', 19, 35, 85, 47, 'T', 'R', 77, 'C', 50, 48, 58, 'G', 35, 43, 'P', 'Q', 'x', 't', 8, 'A', 'F', 'n', 27, 'y', 44, 't', 'i', 't', 27, 32, 'd', 63, 'j', 'J', 'D', 'z', 35, 'H', 't', 76, 'u', 85, 20, 'L', 62, 44, 84, 89, 'p', 13, 'Y', 'C', 13, 'Q', 83, 'f', 9, 12, 87, 'k', 44, 79, 55, 'g', 'e', 'R', 'm', 'e', 97, 'i', 'C', 'h', 9, 'Y', 's', 'e', 'S', 'A', 84, 'Y', 'p', 59, 'Y', 9, 45, 'Y', 66, 'v', 12, 'Y', 91, 'E', 41, 's', 19, 'n', 9, 'H', 'N', 'W', 16, 'u', 'X', 'B', 'k', 94, 'V', 'D', 25, 90, 'Q', 'P', 82, 'T', 'l', 'U', 'j', 'z', 59, 'y', 'z', 'Q', 'i', 'r', 48, 20, 18, 68, 'U', 'V', 6, 'W', 1, 50, 35, 'X', 10, 68, 48, 16, 50, 'i', 75, 90, 'X', 54, 81, 'M', 'k', 56, 'w', 'l', 'h', 'd', 'N', 93, 'G', 73, 68, 'q', 33, 'x', 'd', 12, 'C', 'k', 99, 64, 'b', 'L', 'o', 'a', 'x', 'T', 95, 'E', 32, 'd', 'N', 4, 'C', 100, 'v', 'g', 'o', 1, 'H', 'j', 97, 43, 'r', 'I', 44, 'h', 85, 'r', 'A', 'c', 'p', 29, 'L', 'H', 37, 'h', 'd', 'w', 'V', 'e', 'i', 'G', 't', 'T', 'F', 'o', 'O', 2, 96, 'I', 'j', 'f', 'M', 'q', 'g', 'g', 67, 'T', 'd', 11, 'e', 25, 'Q', 'e', 98, 'I', 25, 23, 65, 'G', 16, 'Q', 'w', 90, 'B', 12, 66, 'A', 'H', 70, 'n', 'T', 'n', 'E', 67, 13, 66, 'p', 'y', 100, 42, 'V', 1, 'M', 86, 'T', 2, 'C', 't', 'q', 'p', 'D', 'z', 'a', 'x', 'u', 'E', 'b', 'T', 'N', 's', 'G', 'O', 6, 'B', 'v', 'U', 87, 33, 44, 'L', 'J', 'N', 'r', 17, 'w', 't', 73, 'T', 71, 86, 'Q', 'l', 15, 'g', 32, 'n', 'u', 'S', 13, 79, 'r', 'B', 64, 'h', 'q', 36, 39, 'Y', 'H', 29, 'C', 'a', 'y', 43, 'V', 'E', 64, 66, 'T', 'Q', 'n', 89, 'W', 'H', 'r', 34, 'f', 'n', 67, 'L', 'n', 43, 66, 'c', 't', 'E', 'C', 'l', 'l', 'P', 64, 27, 'O', 'B', 25, 'E', 83, 'J', 44, 'o', 85, 10, 'c', 'y', 'C', 28, 48, 49, 39, 69, 'u', 'i', 'i', 'z', 'I', 'p', 17, 9, 72, 'k', 0, 'V', 42, 'w', 'L', 56, 26, 53, 'L', 'A', 'd', 64, 'X', 26, 'f', 14, 'z', 'L', 92, 'f', 's', 75, 'q', 83, 'Y', 46, 56, 36, 'j', 'w', 'g', 'A', 63, 54, 'j', 'f', 60, 93, 51, 'c', 48, 'w', 'm', 's', 51, 32, 'k', 99, 'E', 51, 'k', 69, 't', 'z', 'I', 'o', 'B', 'V', 'n', 62, 82, 'l', 68, 63, 63, 'x', 21, 33, 'c', 'Q', 'i', 'P', 'j', 'g', 'z', 't', 52, 'G', 't', 2, 'x', 2, 13, 40, 'L', 'n', 'e', 'J', 'z', 'i', 27, 'd', 10, 'p', 'l', 'u', 31, 59, 'X', 'Y', 'm', 'Q', 'b', 'n', 72, 'I', 'h', 'q', 'X', 'c', 95, 'h', 40, 'y', 'A', 'h', 'G', 'D', 'x', 80, 11, 'G', 'l', 'X', 't', 97, 'i', 'o', 17, 'l', 'r', 't', 'd', 'x', 'a', 'c', 'u', 'J', 31, 73, 'N', 63, 's', 37, 1, 26, 93, 'X', 'e', 'v', 12, 'Z', 'r', 'p', 'z', 'p', 'x', 'M', 78, 'r', 'b', 'Z', 't', 'd', 12, 'a', 'F', 68, 'X', 't', 66, 'P', 'j', 'G', 'g', 'N', 'j', 23, 'm', 'P', 84, 60, 'U', 'l', 'M', 31, 'T', 'g', 'N', 'a', 'V', 40, 84, 't', 'i', 'u', 'z', 'p', 'l', 'g', 62, 'N', 'I', 'g', 'I', 'v', 'E', 'f', 71, 8, 87, 'k', 'r', 'D', 41, 68, 26, 'V', 'l', 'n', 'm', 'z', 'i', 's', 37, 'n', 'E', 's', 'm', 5, 'R', 51, 'A', 'P', 'K', 24, 'X', 'x', 'r', 47, 56, 'b', 'u', 41, 'u', 'V', 7, 'i', 83, 'e', 'q', 61, 'E', 'u', 'I', 'w', 's', 'K', 'M', 5, 'R', 'l', 'e', 's', 97, 'f', 'b', 'x', 'h', 'k', 'w', 'D', 'K', 'd', 'z', 'r', 'm', 'G', 'b', 57, 'E', 96, 'N', 58, 'b', 12, 'C', 50, 'r', 'O', 'x', 59, 'O', 'O', 'z', 'e', 'R', 'x', 'Y', 'e', 'J', 58, 60, 38, 29, 'u', 'g', 0, 'w', 87, 'I', 'W', 88, 'V', 'M', 'V', 3, 69, 'C', 'w', 0, 26, 40, 'R', 12, 'H', 'D', 'n', 21, 'c', 'I', 83, 29, 39, 'p', 48, 77, 'k', 'p', 'c', 'o', 'P', 'Q', 70, 'r', 'M', 16, 'l', 'r', 'L', 5, 31, 'j', 'v', 89, 'O', 75, 93, 'o', 'G', 81, 'p', 76, 'D', 74, 'J', 'M', 'M', 'p', 'C', 56, 64, 'V', 'A', 89, 'L', 'A', 70, 'E', 'e', 'I', 2, 'F', 79, 'Y', 88, 71, 'P', 'F', 'u', 58, 'l', 'L', 'w', 71, 30, 'v', 'U', 38, 'F', 'C', 'M', 16, 'm', 'v', 65, 'f', 'v', 'W', 'h', 88, 'Q', 'h', 's', 37, 'w', 'j', 'f', 95, 66, 'Z', 74, 59, 'd', 'g', 'C', 45, 'I', 44, 'e', 0, 82, 87, 'W', 'O', 'v', 'a', 45, 'j', 'G', 21, 'k', 28, 5, 'U', 'G', 5, 56, 'E', 15, 'g', 'b', 'y', 'U', 'z', 'x', 'r', 'L', 'V', 18, 'u', 'K', 18, 56, 'u', 21, 'W', 'C', 'y', 42, 'i', 'J', 'c', 'A', 'C', 'M', 'U', 45, 'j', 'W', 'D', 89, 28, 'm', 'X', 'j', 'R', 'h', 'Z', 73, 50, 't', 'k', 14, 'X', 'W', 44, 80, 85, 67, 78, 'p', 'T', 'd', 'm', 'q', 'j', 'F', 'v', 'H', 16, 'L', 'k', 45, 'B', 'v', 38, 33, 'e', 76, 26, 'r', 43, 'w', 'U', 'y', 's', 'y', 'A', 'N', 'R', 'h', 'T', 82, 'i', 'h', 'p', 'o', 'T', 'X', 99, 'n', 11, 'J', 'z', 64, 'T', 'm', 67, 'V', 42, 31, 'L', 14, 'X', 58, 'L', 93, 'B', 'u', 67, 41, 'M', 40, 'e', 'd', 'C', 'L', 27, 'q', 44, 86, 'F', 0, 'D', 20, 'f', 36, 'P', 'Z', 'S', 'r', 53, 65, 44, 's', 'U', 44, 89, 'F', 'i', 1, 'X', 'j', 42, 'W', 52, 98, 'c', 61, 44, 'p', 'd', 'E', 78, 'A', 'Y', 'N', 'A', 'Q', 'C', 't', 'Q', 54, 'S', 'q', 'C', 'R', 'u', 'D', 'l', 'Y', 't', 'Q', 'E', 29, 'i', 53, 'i', 'c', 32, 'j', 49, 'q', 19, 'l', 'm', 'w', 'M', 'l', 'N', 'Q', 'R', 54, 'H', 1, 'r', 'h', 5, 'k', 'j', 'g', 'D', 59, 'W', 'z', 12, 80, 'T', 'w', 'a', 45, 'H', 'S', 15, 'F', 'g', 32, 'B', 'I', 94, 'k', 100, 'e', 'b', 'V', 'b', 'b', 84, 55, 20, 'G', 'F', 41, 'R', 'J', 'A', 'P', 'a', 'o', 22, 'i', 'q', 97, 'r', 26, 'O', 68, 'L', 85, 'E', 'L', 'T', 78, 'A', 'Q', 'P', 90, 46, 'l', 'u', 'A', 'y', 'T', 77, 'A', 'q', 'N', 25, 10, 'W', 5, 'G', 'w', 75, 68, 4, 'd', 100, 'L', 'R', 'p', 63, 'S', 'd', 'G', 68, 'g', 't', 'B', 10, 'w', 'f', 'W', 'R', 15, 18, 'V', 'D', 'q', 'd', 'i', 'k', 100, 'j', 's', 'N', 14, 'e', 'm', 'S', 'b', 'a', 31, 'Y', 'x', 100, 12, 'P', 'Y', 76, 61, 't', 'K', 'm', 'j', 98, 'y', 'Z', 'j', 'H', 32, 'H', 'p', 'u', 'c', 'N', 's', 'r', 25, 'G', 88, 'O', 'B', 'P', 'I', 'C', 'V', 'a', 'c', 'I', 'S', 12, 'w', 'h', 'h', 87, 63, 'k', 'q', 'G', 'M', 40, 'x', 66, 'Y', 22, 't', 'P', 'A', 'g', 86, 'C', 28, 'y', 98, 'J', 'y', 51, 'x', 'g', 54, 'J', 'd', 'a', 'j', 'u', 'R', 'q', 11, 'b', 33, 'h', 41, 48, 'H', 'k', 'P', 69, 's', 'e', 'B', 'r', 'A', 'L', 'h', 'S', 30, 'f', 'f', 'U', 'L', 33, 80, 'i', 'g', 9, 11, 42, 'L', 'w', 'V', 'G', 'v', 'f', 'G', 't', 'i', 90, 73, 72, 'V', 'F', 57, 't', 'd', 'E', 'E', 74, 'q', 74, 19, 18, 58, 'K', 'o', 36, 'y', 86, 'Z', 27, 65, 'i', 'S', 'G', 'I', 'R', 22, 'h', 77, 'O', 97, 6, 'n', 'Q', 'P', 75, 'B', 'x', 54, 31, 53, 'y', 7, 'P', 'y', 'p', 'X', 'C', 'y', 'J', 29, 'U', 's', 'U', 'L', 'w', 'I', 'r', 'x', 'F', 'c', 'C', 'w', 'm', 24, 'w', 'x', 45, 'n', 'c', 'X', 'y', 32, 'G', 97, 'T', 51, 'E', 'C', 40, 'P', 60, 25, 'B', 'P', 'd', 1, 'i', 'S', 'K', 'd', 57, 94, 'g', 'j', 'F', 'Y', 'R', 'k', 'y', 'o', 'u', 'l', 's', 31, 54, 'l', 46, 'S', 'e', 'Z', 88, 'd', 34, 90, 'M', 'F', 'P', 'J', 59, 64, 30, 'B', 'K', 'F', 'X', 'q', 87, 'P', 89, 26, 69, 'k', 'O', 42, 'i', 3, 'w', 64, 39, 'V', 30, 's', 'P', 'Z', 's', 's', 'P', 'k', 'S', 'c', 'O', 'M', 'P', 'e', 'S', 78, 'u', 'g', 12, 91, 11, 75, 'K', 'v', 'n', 'l', 83, 'i', 59, 'Z']

```python
d = dict()
for ele in lst:
    if ele in d:
        d[ele] += 1
    else:
        d[ele] = 1
print(d)

```

    {'T': 44, 'J': 40, 'R': 42, 'g': 47, 'l': 45, 'v': 30, 'j': 45, 'M': 41, 'd': 43, 28: 11, 'Q': 36, 23: 8, 'I': 36, 'u': 47, 'n': 32, 'V': 43, 'o': 42, 'f': 39, 'p': 45, 't': 44, 'b': 29, 'N': 31, 'X': 40, 'U': 31, 0: 6, 3: 6, 46: 9, 84: 8, 48: 14, 'S': 39, 's': 41, 68: 20, 'y': 34, 64: 18, 51: 9, 'c': 33, 24: 7, 'P': 52, 'k': 43, 'w': 46, 93: 9, 57: 7, 'r': 54, 'D': 39, 80: 8, 95: 11, 'O': 33, 'K': 30, 96: 9, 70: 12, 'm': 27, 'E': 47, 'x': 39, 58: 10, 100: 14, 56: 17, 7: 7, 99: 8, 44: 15, 39: 11, 97: 12, 'h': 33, 8: 7, 'a': 22, 15: 8, 'W': 38, 5: 11, 'q': 34, 81: 5, 19: 7, 'A': 44, 'B': 36, 59: 11, 45: 15, 'z': 44, 88: 9, 91: 12, 21: 7, 29: 13, 'L': 52, 43: 9, 31: 14, 'G': 41, 73: 11, 74: 8, 37: 9, 53: 8, 2: 8, 54: 15, 'Z': 28, 'Y': 41, 25: 16, 38: 9, 50: 13, 72: 13, 76: 12, 9: 14, 27: 12, 33: 10, 'H': 36, 61: 11, 36: 10, 6: 7, 49: 6, 14: 7, 'C': 47, 63: 14, 71: 8, 'i': 39, 16: 11, 60: 8, 18: 9, 40: 12, 13: 8, 89: 12, 'e': 47, 'F': 37, 86: 11, 1: 10, 67: 7, 12: 18, 79: 8, 17: 5, 85: 11, 42: 9, 94: 11, 62: 9, 69: 12, 26: 13, 47: 6, 66: 14, 41: 12, 22: 8, 92: 7, 90: 11, 20: 14, 10: 10, 32: 10, 35: 7, 78: 10, 83: 10, 77: 9, 11: 10, 65: 10, 30: 9, 75: 12, 98: 8, 52: 7, 82: 11, 87: 11, 4: 7, 55: 7, 34: 5}

```python
lst = [1, 2, 3, 4]
it = iter(lst) #创建迭代器对象
print(next(it)) #输出下一个元素
print(next(it))
```

    1
    2

```python
lst = [1, 2, 3, 4]
it = iter(lst)
for i in it:
    print(i, end="")
```

    1234

```python
def lydlwy():
    print("xxl")

lydlwy()
```

    xxl

```python
def area(width,length):
    return width*length

def wel_name(name):
    print("welcome:",name)

wel_name("xxl")
w = 4
n = 5
print("width = ", w, "length=", n, "area=", area(w,n) )
```

    welcome: xxl
    width =  4 length= 5 area= 20

```python
a = 4
def prnt_func1():
    a = 19
    print("in prnt_func a = ",a)
def prnt_func2():
    print("in prnt_func a = ",a)

prnt_func1()
prnt_func2()
print("a = ",a)
```

    in prnt_func a =  19
    in prnt_func a =  4
    a =  4

```python
def pow(x, n=2):
    return x**n

print(pow(10))
print(pow(10, 3))
```

    100
    1000

```python
def sum(x, y):
    c = x + y
    return

s = sum(4, 5)
print(s)
```

    None

```python
def test(n, m, *args):
    result = 0
    for i in args:
        result += i
    return result/n + m

print(test(2, 1, 2, 3, 4, 5))
```

    8.0

```python
def test(*sums):
    result = 0
    for i in sums:
        result += i
    return result

r = test(1,2,3,4,5,6)
print(r)
r = test(1,2,3)
print(r)
```

    21
    6

```python
def test(num):
    while True:
        num /= 2
        yield num

it = test(33554432)
for i in it:
    if i<1e-8:
        break
    print(i, end=", ")
```

    16777216.0, 8388608.0, 4194304.0, 2097152.0, 1048576.0, 524288.0, 262144.0, 131072.0, 65536.0, 32768.0, 16384.0, 8192.0, 4096.0, 2048.0, 1024.0, 512.0, 256.0, 128.0, 64.0, 32.0, 16.0, 8.0, 4.0, 2.0, 1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625, 0.0078125, 0.00390625, 0.001953125, 0.0009765625, 0.00048828125, 0.000244140625, 0.0001220703125, 6.103515625e-05, 3.0517578125e-05, 1.52587890625e-05, 7.62939453125e-06, 3.814697265625e-06, 1.9073486328125e-06, 9.5367431640625e-07, 4.76837158203125e-07, 2.384185791015625e-07, 1.1920928955078125e-07, 5.960464477539063e-08, 2.9802322387695312e-08, 1.4901161193847656e-08,

```python
def add1(lst):
    lst.append(1)

lst = [1, 2, 3, 4, 5]
lst.reverse()
add1(lst)
print(lst)

```

    [5, 4, 3, 2, 1, 1]

```python
s = b'\xe6\x88\x91\xe7\x88\xb1\xe6\x9d\x8e\xe6\x9c\xaa\xe6\x99\x8f'
print(s.decode("utf-8"))
```

    我爱李未晏

```python
lst = [1, 2, 3]
lst1 = [2, 6, 7]
print([x for x in lst])
print([x**2 for x in lst if x > 1])
print([x+y for x in lst for y in lst1])
```

    [1, 2, 3]
    [4, 9]
    [3, 7, 8, 4, 8, 9, 5, 9, 10]

```python
import numpy as np
import sympy as sp
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]
M = sp.Matrix(matrix)
print(sp.pretty(M))
```

    ⎡1  2  3⎤
    ⎢       ⎥
    ⎢4  5  6⎥
    ⎢       ⎥
    ⎣7  8  9⎦

```python
print([str(round(355/133, i)) for i in range(1, 6)])
```

    ['2.7', '2.67', '2.669', '2.6692', '2.66917']

```python
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]

print([[ row[i] for row in matrix ] for i in range(3)])

```

    [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

```python
lst = [2, 5, 8, 9]
print(lst.pop(0))
print(lst)
del lst[0]
print(lst)
```

    2
    [5, 8, 9]
    [8, 9]

```python
a = {x for x in "anshfjkjfalna" if x not in "abc"}
print(a)
```

    {'l', 's', 'h', 'j', 'n', 'k', 'f'}

```python
from pprint import pprint
dct = dict([ [3,4], ["key",8], [2,3] ])
pprint(dct)
del dct["key"]
print(dct)

```

    {2: 3, 3: 4, 'key': 8}
    {3: 4, 2: 3}

```python
from pprint import pprint
dct = {'3':4, "liang":9, "o":2}
print(dct)
d = {i:i**i for i in range(24)}
pprint(d)
for k, v in dct.items():
    print(k, v)

```

    {'3': 4, 'liang': 9, 'o': 2}
    {0: 1,
     1: 1,
     2: 4,
     3: 27,
     4: 256,
     5: 3125,
     6: 46656,
     7: 823543,
     8: 16777216,
     9: 387420489,
     10: 10000000000,
     11: 285311670611,
     12: 8916100448256,
     13: 302875106592253,
     14: 11112006825558016,
     15: 437893890380859375,
     16: 18446744073709551616,
     17: 827240261886336764177,
     18: 39346408075296537575424,
     19: 1978419655660313589123979,
     20: 104857600000000000000000000,
     21: 5842587018385982521381124421,
     22: 341427877364219557396646723584,
     23: 20880467999847912034355032910567}
    3 4
    liang 9
    o 2

```python
questions = ['name', 'home', 'gender', 'language']
answers = ['lyd', 'shandong', 'male', 'chinese']
for i, j in zip(questions, answers):
    print("what is your %s, it is %s"  % (i, j))

```

    what is your name, it is lyd
    what is your home, it is shandong
    what is your gender, it is male
    what is your language, it is chinese

```python
from utils import fib

help(fib.fib)
help(fib.fibab)
for i in range(16):
    print(fib.fib(i), end=", ")
```

    Help on function fib in module utils.fib:

    fib(n)
        This is fib method.

    Help on function fibab in module utils.fib:

    fibab(n, a, b)
        This is general fib method.

    1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141,

```python
from utils import pow
help(pow)

print(pow.sqrt(-1))
```

    Help on module utils.pow in utils:

    NAME
        utils.pow

    FUNCTIONS
        cube(x)
            Cube.

        pow(x, n)
            Power.

        sqrt(x)
            Square root.

        square(x)
            Square.

    FILE
        c:\users\苏苏\desktop\打倒李未晏\utils\pow.py

    (6.123233995736766e-17+1j)

```python
from utils.fib import fib as whatever

print(whatever(10))
```

    89

```python
import this
```

    The Zen of Python, by Tim Peters

    Beautiful is better than ugly.
    Explicit is better than implicit.
    Simple is better than complex.
    Complex is better than complicated.
    Flat is better than nested.
    Sparse is better than dense.
    Readability counts.
    Special cases aren't special enough to break the rules.
    Although practicality beats purity.
    Errors should never pass silently.
    Unless explicitly silenced.
    In the face of ambiguity, refuse the temptation to guess.
    There should be one-- and preferably only one --obvious way to do it.
    Although that way may not be obvious at first unless you're Dutch.
    Now is better than never.
    Although never is often better than *right* now.
    If the implementation is hard to explain, it's a bad idea.
    If the implementation is easy to explain, it may be a good idea.
    Namespaces are one honking great idea -- let's do more of those!

```python

```


Osnabrück University - Computer Vision (Winter Term 2020/21) - Prof. Dr.-Ing. G. Heidemann, Ulf Krumnack, Axel Schaffland

# Exercise Sheet 03: Morphological Operations¶

## Introduction

This week's sheet should be solved and handed in before the end of **Saturday, November 21, 2020**. If you need help (and Google and other resources were not enough), feel free to contact your groups' designated tutor or whomever of us you run into first. Please upload your results to your group's Stud.IP folder.

## Assignment 0: Math recap (complex numbers) [0 Points]

This exercise is supposed to be very easy, does not give any points, and is voluntary. There will be a similar exercise on every sheet. It is intended to revise some basic mathematical notions that are assumed throughout this class and to allow you to check if you are comfortable with them. Usually you should have no problem to answer these questions offhand, but if you feel unsure, this is a good time to look them up again. You are always welcome to discuss questions with the tutors or in the practice session. Also, if you have a (math) topic you would like to recap, please let us know.

**a)** What is a *complex number*, what is the *complex plane*, how are complex numbers usually denoted?

YOUR ANSWER HERE

**b)** What is the *real* and the *imaginary* part of a complex number? What is the *absolute value* of a complex number? What is the *complex conjugate*?

YOUR ANSWER HERE

**c)** What are polar coordinates? What are their advantages? Can you convert between cartesian and polar coordinates? Can you write down $i=\sqrt{-1}$ in polar coordinates? What about $\sqrt{i}$?

YOUR ANSWER HERE

**d)** Python, and also numpy, support calculations with complex numbers. Consult the documentation to find out details. Notice that $i$ is substituted by $j$ in Python.

```python
# YOUR CODE HERE
```

## Assignment 1: Properties of morphological operators [5 Points]

This exercise will elaborate on the basic morphological operators of *erosion* and *dilation* (cf. CV-05 slides 4-14).

### a) Duality

Proof that *erosion* and *dilation* are *dual* operators, i.e.

$ g^{\ast}\oplus S = (g\ominus S)^{\ast}\qquad\text{and}\qquad
g^{\ast}\ominus S = (g\oplus S)^{\ast}$

here $g^{\ast}$ denotes the inverted binary image, i.e. $g^{\ast}(x,y) = 1 - g(x,y) = \neg g(x,y)$, i.e. 1-pixel become 0 and 0-pixel become 1.

$(g^{\ast}\oplus S)(x, y) = \bigvee_{k \in [-m, m]} \bigvee_{l \in [-n, n]} S(k+m, l+n) \land g^*(x+k, y+l)$
$\quad\quad\quad\quad\quad\quad = \bigvee_{k \in [-m, m]} \bigvee_{l \in [-n, n]} S(k+m, l+n) \land \lnot g(x+k, y+l)$
$\quad\quad\quad\quad\quad\quad = \bigvee_{k \in [-m, m]} \bigvee_{l \in [-n, n]} \lnot (\lnot S(k+m, l+n) \lor g(x+k, y+l)$
$\quad\quad\quad\quad\quad\quad = \lnot \bigwedge_{k \in [-m, m]} \bigwedge_{l \in [-n, n]} (\lnot S(k+m, l+n) \lor g(x+k, y+l)$
$\quad\quad\quad\quad\quad\quad = \lnot \bigwedge_{k \in [-m, m]} \bigwedge_{l \in [-n, n]} (S(k+m, l+n) \rightarrow g(x+k, y+l)$
$\quad\quad\quad\quad\quad\quad = \lnot (g\ominus S)(x, y)$
$\quad\quad\quad\quad\quad\quad = (g\ominus S)^{\ast}(x, y)$

$(g^{\ast}\ominus S)(x, y) = \bigwedge_{k \in [-m, m]} \bigwedge_{l \in [-n, n]} (S(k+m, l+n) \rightarrow g^*(x+k, y+l))$
$\quad\quad\quad\quad\quad\quad = \bigwedge_{k \in [-m, m]} \bigwedge_{l \in [-n, n]} (S(k+m, l+n) \rightarrow \lnot g(x+k, y+l))$
$\quad\quad\quad\quad\quad\quad = \bigwedge_{k \in [-m, m]} \bigwedge_{l \in [-n, n]} (\lnot S(k+m, l+n) \lor \lnot g(x+k, y+l))$
$\quad\quad\quad\quad\quad\quad = \bigwedge_{k \in [-m, m]} \bigwedge_{l \in [-n, n]} \lnot(S(k+m, l+n) \land g(x+k, y+l))$
$\quad\quad\quad\quad\quad\quad = \lnot \bigvee_{k \in [-m, m]} \bigvee_{l \in [-n, n]} (S(k+m, l+n) \land g(x+k, y+l))$
$\quad\quad\quad\quad\quad\quad = \lnot (g\oplus S)(x, y)$
$\quad\quad\quad\quad\quad\quad = (g\oplus S)^{\ast}(x, y)$

### b) Superposition

As *erosion* and *dilation* have been introduced for binary images, the notion of *linearity* is not really appropriate here. However, some weaker version, called *superposition* can be defined: instead of forming linear combination, one takes the logical disjunction:

$$(g_1\lor g_2)(x,y) := g_1(x,y)\lor g_2(x,y)$$

Check for both operations if *erosion* and *dilation* are "compatible" with superposition, i.e. if first *eroding* (or *dilating*) two images and superposing the result is the same as first superposing the images and then *eroding* (or *dilating*) the result.

**Dilation**

$((g_1 \lor g_2) \oplus S)(x, y) =  \bigvee_{k \in [-m, m]} \bigvee_{l \in [-n, n]} S(k+m, l+n) \land (g_1 \lor g_2)(x+k, y+l)$
$\quad\quad\quad\quad\quad\quad\quad\quad\quad = \bigvee_{k \in [-m, m]} \bigvee_{l \in [-n, n]} S(k+m, l+n) \land (g_1(x+k, y+l) \lor g_2(x+k, y+l))$
$\quad\quad\quad\quad\quad\quad\quad\quad\quad = (\bigvee_{k \in [-m, m]} \bigvee_{l \in [-n, n]} S(k+m, l+n) \land g_1(x+k, y+l)) \lor (\bigvee_{k \in [-m, m]} \bigvee_{l \in [-n, n]} S(k+m, l+n) \land g_2(x+k, y+l))$
$\quad\quad\quad\quad\quad\quad\quad\quad\quad = (g_1 \oplus S)(x, y) \lor (g_2 \oplus S)(x, y)$

$\rightarrow$ dilation is compatible with superposition

**Erosion**

$((g_1 \lor g_2) \ominus S)(x, y) =  \bigwedge_{k \in [-m, m]} \bigwedge_{l \in [-n, n]} S(k+m, l+n) \rightarrow (g_1 \lor g_2)(x+k, y+l)$
$\quad\quad\quad\quad\quad\quad\quad\quad\quad = \bigwedge_{k \in [-m, m]} \bigwedge_{l \in [-n, n]} S(k+m, l+n) \rightarrow (g_1(x+k, y+l) \lor g_2(x+k, y+l))$
$\quad\quad\quad\quad\quad\quad\quad\quad\quad = \bigwedge_{k \in [-m, m]} \bigwedge_{l \in [-n, n]} \lnot S(k+m, l+n) \lor g_1(x+k, y+l) \lor g_2(x+k, y+l)$
$\quad\quad\quad\quad\quad\quad\quad\quad\quad \neq (\bigwedge_{k \in [-m, m]} \bigwedge_{l \in [-n, n]} \lnot S(k+m, l+n) \lor g_1(x+k, y+l)) \lor (\bigwedge_{k \in [-m, m]} \bigwedge_{l \in [-n, n]} \lnot S(k+m, l+n) \lor g_2(x+k, y+l))$

### c) Chaining

Show that *dilation* and *erosion* have the following properties: given two structering elements $S_1$ and $S_2$, it holds

\begin{align}
  (g\oplus S_1)\oplus S_2 & & = & g\oplus (S_1\oplus S_2) && = (g\oplus S_2)\oplus S_1 \\
  (g\ominus S_1)\ominus S_2 & & = & g\ominus (S_1\ominus S_2) && = (g\ominus S_2)\ominus S_1 \\
\end{align}

What are the practical consequences?

**Dilation**

$((g \oplus S_1) \oplus S_2)(x, y) = \bigvee_{k \in [-m_2, m_2]} \bigvee_{l \in [-n_2, n_2]} S_2(k+m_2, l+n_2) \land (g \oplus S_1)(x+k, y+l)$
$\quad\quad\quad\quad\quad\quad\quad\quad\quad = \bigvee_{k \in [-m_2, m_2]} \bigvee_{l \in [-n_2, n_2]} S_2(k+m_2, l+n_2) \land (\bigvee_{i \in [-m_1, m_1]} \bigvee_{j \in [-n_1, n_1]} S_1(i+m_1, j+n_1) \land g(x+i+k, y+j+l))$
$\quad\quad\quad\quad\quad\quad\quad\quad\quad = \bigvee_{i \in [-m_1, m_1]} \bigvee_{j \in [-n_1, n_1]} \bigvee_{k \in [-m_2, m_2]} \bigvee_{l \in [-n_2, n_2]} S_1(i+m_1, j+n_1) \land S_2(k+m_2, l+n_2) \land g(x+i+k, y+j+l)$
$\quad\quad\quad\quad\quad\quad\quad\quad\quad = ((g\oplus S_2)\oplus S_1)(x,y)$

$\rightarrow$ the order doesn't matter

$g\oplus (S_1\oplus S_2)$ holds as well, we're just changing the order in which the indices are added and addition is commutative.

**Erosion**

The proof for the erosion operation works basically the same (cf. task 1a).

## Assignment 2: Application [5 Points]

### a) Boundary extraction

Extract the boundary of a shape using opening or closing. You may use `binary_dilation` or `binary_erosion` from `scipy.ndimage.morphology`. Can you achieve a thicker boundary?

```python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['image.cmap'] = 'gray'
import scipy.ndimage.morphology as morph
from imageio import imread

def my_boundary(img, structuring_elem=[]):
    """
    Compute boundary of binary image.

    Parameters
    ----------
    img : ndarray of bools
        A binary image.
    structuring_elem: array_like, optional
        Structuring element used for the erosion.

    Returns
    -------
    boundary : ndarray of bools
        The boundary as a binary image.
    """

    boundary = np.zeros(img.shape,np.bool)
    # YOUR CODE HERE
    if len(structuring_elem) > 0:
        erosion = morph.binary_erosion(img, structuring_elem)
    else:
        erosion = morph.binary_erosion(img)
    boundary = np.logical_xor(erosion, img)

    return boundary

fig = plt.figure(figsize=(15,7))

img = imread("images/engelstrompete.png") > 0

fig.add_subplot(1,3,1)
plt.imshow(img, cmap = 'gray')
plt.title('image')

fig.add_subplot(1,3,2)
plt.imshow(my_boundary(img), cmap = 'gray')
plt.title('boundary')

fig.add_subplot(1,3,3)
# larger structuring element
plt.imshow(my_boundary(img, np.ones((10, 10))), cmap = 'gray')
plt.title('thicker boundary')

plt.show()
```

### b)  Distance transform

Implement distance transform according to the ideas of (CV-05 slides 34ff).  Discuss the effect of different structuring elements.

```python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import morphology as morph, generate_binary_structure
from imageio import imread

def my_distance_transform(img):
    """Distance transform of binary image.

    Args:
    img (ndarray of bools): A binary image.

    Returns:
    dt (ndarray of ints): The distance transform of the input image.
    """

    dt = np.zeros(img.shape,np.int32)
    # YOUR CODE HERE
    lvl = 1
    # erode until nothing is left
    while np.any(img):
        boundary = my_boundary(img)
        # pixels with manhattan distance lvl to the boundary
        dt[boundary] = lvl
        # object without boundary
        img = morph.binary_erosion(img)
        lvl += 1

    return dt

img = imread("images/engelstrompete.png") > 0
fig = plt.figure(figsize=(10,10))

fig.add_subplot(1,2,1)
plt.imshow(img, cmap = 'gray')
plt.title('image')

fig.add_subplot(1,2,2)
plt.imshow(my_distance_transform(img) + 50 * img)
plt.title('distance transform')

plt.show()
```

Different structuring elements implement different metrics, e.g.:
- manhattan distance
- chessboard distance

### c) Morphing

Write a function `my_morph` that implements morphing according to (CV-05 slide 41). You may use your function `my_distance_transform` from part b), or the function `distance_transform_edt` from `scipy.ndimage.morphology`.

```python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import scipy.ndimage.morphology as morph
from imageio import imread

def my_morph(A,B,ratio):
    """Morphing from binary image A to image B.

    Args:
        A (ndarray of bools): A binary image (start).
        B (ndarray of bools): A binary image (target), same shape as A.
        ratio (float from 0.0 to 1.0): The ratio of image A and image B.
            0.0=only image A, 1.0=only image B.

    Returns:
        morph (ndarray of bools): A binary intermediate image between A and B.

    """

    result = np.zeros(A.shape,np.bool)
    # YOUR CODE HERE
    D_a = my_distance_transform(A) - my_distance_transform(np.invert(A))
    D_b = my_distance_transform(B) - my_distance_transform(np.invert(B))
    result = (ratio * D_b + (1 - ratio) * D_a)
    # element-wise applied
    return result > 0

img1 = imread("images/kreis.png") > 0
img2 = imread("images/engelstrompete.png") > 0

plt.gray()
plt.figure(figsize=(10,10))
for i, ratio in enumerate(np.linspace(0, 1, 6), 1):
    plt.subplot(2, 3, i)
    plt.imshow(my_morph(img1, img2, ratio))
    plt.title('ratio:' + str(round(ratio, 2)))
    plt.axis('off')
plt.show()
```

```python
# If you want to see your morph as an animation, run this cell.
# Close the output (press the blue "Stop interaction" button) once you are done!

# Due to some matplotlib problem you may have to restart your kernel!
%matplotlib inline
import matplotlib.animation as animation
fig = plt.figure()

ims = []
for i, ratio in enumerate(np.linspace(0, 1, 24), 1):
    plt.axis('off')
    im = plt.imshow(my_morph(img1, img2, ratio), cmap='gray', animated=True)
    ims.append([im])

ani = animation.ArtistAnimation(fig, ims + list(reversed(ims)), interval=100, blit=True)

plt.show()
```

## Assignment 3: Implementation: Skeletonization [5 Points]

### a) Skeletonization with hit-or-miss

Explain in your own words, how the hit-or-miss operator can be used for skeletonization (cf CV-05 slide 49).

If we want to extract a particular kind of pattern from an image, we can use the hit-or-miss operation.
So, if we know exactly what we are looking for, this is highly efficient.
3 steps:
- **hit:** find candidate locations (where the pattern might be in the image)
    - removes everything that is too small by erosion (what remains are candidates)
- **miss:** removes everything that is too large
- **intersection:** intersect the two previous results

Now we can combine distance transform and hit-or-miss to do skeletonization.
A skeleton provides a meaningful and concise description of a binary shape, e.g. for classification.
To compute the skeleton of some binary segment, we would have to find all the bi-tangent circles. We can get this quite easily using the
distance transform.
The ridges are already the skeleton, we just need to find the ridges using the hit-or-miss operation.

The shape of the ridges is a priori unknown. We'd just remove iteratively all pixels from the distance transform where we know that they are not ridges. This can be done using the $8$ operators (left, right, up, down, and the four diagonals) which are designed to detect structures that stay connected after removing the central pixel.

Those operators are applied iteratively until only the skeleton remains.

### b) Implementation of skeletonization

Now use this method to implement your own skeletonization function. It is ok to use
`scipy.ndimage.morphology.binary_hit_or_miss` here (but of course *not* `skimage.morphology.skeletonize` or similar functions). Compare your result with (CV-05 slide 50). Note that computing the skeleton using this method may take some time ...

```python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import scipy.ndimage.morphology as morph
from imageio import imread

def my_skeletonize(img):
    """
    Compute the skeleton of a binary image using hit_or_miss operator.

    Parameters
    ----------
    img : ndarray of bools
        Binary image to be skeletonized.

    Returns
    -------
    skeleton : ndarray of bools
        The skeleton of the input image.
    """
    # YOUR CODE HERE

    # based on 2 ideas:
    #   - ridges of the distance transform are the skeleton
    #   - find ridges using the hit-or-miss operation

    # 'X' is always 0 and the other elements are inverted for this miss structuring elements

    # hit structuring elements
    l  = np.array([[0,0,1], [0,1,1], [0,0,1]])
    r  = np.array([[1,0,0], [1,1,0], [1,0,0]])
    o  = np.array([[0,0,0], [0,1,0], [1,1,1]])
    u  = np.array([[1,1,1], [0,1,0], [0,0,0]])
    lu = np.array([[0,1,1], [0,1,1], [0,0,0]])
    lo = np.array([[0,0,0], [0,1,1], [0,1,1]])
    ru = np.array([[1,1,0], [1,1,0], [0,0,0]])
    ro = np.array([[0,0,0], [1,1,0], [1,1,0]])

    # miss structuring elements
    l_m  = np.array([[1,0,0], [1,0,0], [1,0,0]])
    r_m  = np.array([[0,0,1], [0,0,1], [0,0,1]])
    o_m  = np.array([[1,1,1], [0,0,0], [0,0,0]])
    u_m  = np.array([[0,0,0], [0,0,0], [1,1,1]])
    lu_m = np.array([[0,0,0], [1,0,0], [1,1,0]])
    lo_m = np.array([[1,1,0], [1,0,0], [0,0,0]])
    ru_m = np.array([[0,0,0], [0,0,1], [0,1,1]])
    ro_m = np.array([[0,1,1], [0,0,1], [0,0,0]])

    hit_structs = [l, r, o, u, lu, lo, ru, ro]
    miss_structs = [l_m, r_m, o_m, u_m, lu_m, lo_m, ru_m, ro_m]

    distance_transform = my_distance_transform(img)
    skeleton = img.copy()
    prev = np.zeros(skeleton.shape)

    while not(np.array_equal(skeleton, prev)):
        prev = skeleton.copy()
        for hit, miss in zip(hit_structs, miss_structs):
            hit_or_miss_transform = morph.binary_hit_or_miss(distance_transform, structure1=hit, structure2=miss)
            skeleton[hit_or_miss_transform] = 0
            distance_transform[hit_or_miss_transform] = 0

    return skeleton

img = imread("images/engelstrompete.png") > 0
skel = my_skeletonize(img)
result = morph.distance_transform_cdt(img, metric='taxicab') + (50 * img)
result[morph.binary_dilation(skel)] = 0
plt.figure(figsize=(10,10))
plt.gray()
plt.imshow(result)
plt.show()
```

## Assignment 4: Custom Structuring Element [5 points]

Landsat 7 is a satelite mission for acquisition of satellite imagery of Earth. Unfortunately the Scan Line Corrector failed, resulting in black stripes on the aquired images. More information: https://landsat.usgs.gov/slc-products-background

### a) A first fix

A rather crude fix is to apply a custom structuring element for dilation and erosion (see CV-05, 24ff). Complement the code below (in part (b)) in the following way:
* Rotate the image such that the gaps are horizontal.
* Dilate the rotated image with a vertical structuring element. I.e. take the maximum of an area of size $7 \times1$ and assign it to the center pixel. Repeat for all pixels.
* Erode the dilated image.
* Rotate the result back.

Remark: this exercise applies morphological operator to color images. This extends the idea of generalizing morphological operators to gray value images (CV-05, slide 51).

### b) Improving the solution
You may get better results by thresholding and applying the morphological operations only to pixels below a threshold, i.e. gap pixels. Compliment your solution from a).

```python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import scipy.ndimage.morphology as morph
import scipy.ndimage as ndimg
from skimage import color
from skimage.transform import rescale as rescale
from skimage.transform import rotate as rotate
from imageio import imread

angle = 15
thresh = .4
struc_elem = np.ones((7,1), dtype=np.bool)

img = imread("images/landsat_stack2.png")
img2 = img.copy()
img3 = img.copy()

# YOUR CODE HERE
# rotate image
img2 = rotate(img2, angle, resize=True)

# from [0.0, 1.0] to [0, 255]
img2 = (img2 * 255).astype(np.uint8)

# dilation for each color channel
img2[:,:,0] = morph.grey_dilation(img2[:,:,0], structure=struc_elem)
img2[:,:,1] = morph.grey_dilation(img2[:,:,1], structure=struc_elem)
img2[:,:,2] = morph.grey_dilation(img2[:,:,2], structure=struc_elem)

# erosion for each color channel
img2[:,:,0] = morph.grey_erosion(img2[:,:,0], structure=struc_elem)
img2[:,:,1] = morph.grey_erosion(img2[:,:,1], structure=struc_elem)
img2[:,:,2] = morph.grey_erosion(img2[:,:,2], structure=struc_elem)

# rotate back
img2 = rotate(img2, -angle, resize=True)

# rotate returns again values from [0.0, 1.0]

# get a copy of the original image that is of the same size as the rotated image
original = img.copy()
original = rotate(original, angle, resize=True)
original = rotate(original, -angle, resize=True)

img3 = img2.copy()
for x in range(original.shape[0]):
    for y in range(original.shape[1]):
        for i in range(3):
            # use original value above threshold
            if original[x][y][i] >= thresh:
                img3[x][y][i] = original[x][y][i]

img = (img - np.min(img)) / np.ptp(img)
img2 = (img2 - np.min(img2)) / np.ptp(img2)
img3 = (img3 - np.min(img3)) / np.ptp(img3)

plt.figure(figsize=(30,90))
plt.subplot(1,3,1); plt.title('original'); plt.imshow(img); plt.axis('off')
plt.subplot(1,3,2); plt.title('first fix'); plt.imshow(img2); plt.axis('off')
plt.subplot(1,3,3); plt.title('thresh fix'); plt.imshow(img3); plt.axis('off')
plt.show()

```

### c) Bonus
Can you think of other ways to add the missing data?

- fill up missing information with information from other satellites
- use image destriping algorithms (e.g. Fourier filtering)


# Just Euler's method

```python
from IPython.core.display import HTML
css_file = 'https://raw.githubusercontent.com/ngcm/training-public/master/ipython_notebook_styles/ngcmstyle.css'
HTML(url=css_file)
```

<link href='http://fonts.googleapis.com/css?family=Open+Sans:100,300,400,500,700,800,900,100italic,300italic,400italic,500italic,700italic,800italic,900italic' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Arvo:400,700,400italic' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=PT+Mono' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Shadows+Into+Light' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Nixie+One' rel='stylesheet' type='text/css'>
<style>

@font-face {
    font-family: "Computer Modern";
    src: url('http://mirrors.ctan.org/fonts/cm-unicode/fonts/otf/cmunss.otf');
}

#notebook_panel { /* main background */
    background: rgb(245,245,245);
}

div.cell { /* set cell width */
    width: 1000px;
}

div #notebook { /* centre the content */
    background: #fff; /* white background for content */
    width: 1200px;
    margin: auto;
    padding-left: 0em;
}

#notebook li { /* More space between bullet points */
margin-top:0.8em;
}

/* draw border around running cells */
div.cell.border-box-sizing.code_cell.running {
    border: 1px solid #111;
}

/* Put a solid color box around each cell and its output, visually linking them*/
div.cell.code_cell {
    background-color: rgb(256,256,256);
    border-radius: 0px;
    padding: 0.5em;
    margin-left:1em;
    margin-top: 1em;
}

div.text_cell_render{
    font-family: 'Open Sans' sans-serif;
    line-height: 140%;
    font-size: 125%;
    font-weight: 400;
    width:900px;
    margin-left:auto;
    margin-right:auto;
}

/* Formatting for header cells */
.text_cell_render h1 {
    font-family: 'Arvo', serif;
    font-style:regular;
    font-weight: 400;
    font-size: 45pt;
    line-height: 100%;
    color: rgb(0,51,102);
    margin-bottom: 0.5em;
    margin-top: 0.5em;
    display: block;
}
.text_cell_render h2 {
    font-family: 'Arvo', serif;
    font-weight: 400;
    font-size: 30pt;
    line-height: 100%;
    color: rgb(0,51,102);
    margin-bottom: 0.1em;
    margin-top: 0.3em;
    display: block;
}

.text_cell_render h3 {
    font-family: 'Arvo', serif;
    margin-top:16px;
	font-size: 22pt;
    font-weight: 600;
    margin-bottom: 3px;
    font-style: regular;
    color: rgb(102,102,0);
}

.text_cell_render h4 {    /*Use this for captions*/
    font-family: 'Arvo', serif;
    font-size: 14pt;
    text-align: center;
    margin-top: 0em;
    margin-bottom: 2em;
    font-style: regular;
}

.text_cell_render h5 {  /*Use this for small titles*/
    font-family: 'Arvo', sans-serif;
    font-weight: 400;
    font-size: 16pt;
    color: rgb(163,0,0);
    font-style: italic;
    margin-bottom: .1em;
    margin-top: 0.8em;
    display: block;
}

.text_cell_render h6 { /*use this for copyright note*/
    font-family: 'PT Mono', sans-serif;
    font-weight: 300;
    font-size: 9pt;
    line-height: 100%;
    color: grey;
    margin-bottom: 1px;
    margin-top: 1px;
}

.CodeMirror{
        font-family: "PT Mono";
        font-size: 90%;
}

</style>

$$
\newcommand{\dt}{\Delta t}
\newcommand{\udt}[1]{u^{({#1})}(T)}
\newcommand{\Edt}[1]{E^{({#1})}}
\newcommand{\uone}[1]{u_{1}^{({#1})}}
$$

In the previous cases we've focused on the *behaviour* of the algorithm: whether it will give the correct answer in the limit, or whether it converges as expected.  This is really what you want to do: you're trying to do science, to get an answer, and so implementing the precise algorithm should be secondary.  If you are trying to implement a precise algorithm, it should be because of its (expected) behaviour, and so you should be testing for that!

However, let's put that aside and see if we can work out how to test whether we've implemented exactly the algorithm we want: Euler's method. Checking convergence alone is not enough: the [Backwards Euler method](http://en.wikipedia.org/wiki/Backward_Euler_method) has identical convergence behaviour, as do whole families of other methods. We need a check that characterizes the method uniquely.

The *local truncation error* $\Edt{\dt}$ would be exactly such a check. This is the error produced by a single step from exact data, eg

$$
\begin{equation}
  \Edt{\dt} = u_1 - u(\dt).
\end{equation}
$$

For Euler's method we have

$$
\begin{equation}
  u_{n+1} = u_n + \dt f(t_n, u_n)
\end{equation}
$$

and so

$$
\begin{equation}
  \Edt{\dt} = \left| u_0 + \dt f(0, u_0) - u(\dt) \right| =  \left| \frac{\dt^2}{2} \left. u''\right|_{t=0} \right| + {\cal O}(\dt^3).
\end{equation}
$$

This is all well and good, but we don't know the exact solution (in principle) at any point other than $t=0$, so cannot compute $u(\dt)$, so cannot compute $\Edt{\dt}$. We only know $\uone{\dt}$ for whichever values of $\dt$ we wish to compute.

We can use repeated Richardson extrapolation to get the solution $u(\dt)$ to sufficient accuracy, however. On the *assumption* that the algorithm is first order (we can use the previous techniques to check this), we can use Richardson extrapolation to repeatedly remove the highest order error terms. We can thus find the local truncation errors.

```python
from math import sin, cos, log, ceil
import numpy
from matplotlib import pyplot
%matplotlib inline
from matplotlib import rcParams
rcParams['font.family'] = 'serif'
rcParams['font.size'] = 16
```

```python
# model parameters:
g = 9.8      # gravity in m s^{-2}
v_t = 30.0   # trim velocity in m s^{-1}
C_D = 1/40.  # drag coefficient --- or D/L if C_L=1
C_L = 1.0    # for convenience, use C_L = 1

### set initial conditions ###
v0 = v_t     # start at the trim velocity (or add a delta)
theta0 = 0.0 # initial angle of trajectory
x0 = 0.0     # horizotal position is arbitrary
y0 = 1000.0  # initial altitude
```

```python
def f(u):
    """Returns the right-hand side of the phugoid system of equations.

    Parameters
    ----------
    u : array of float
        array containing the solution at time n.

    Returns
    -------
    dudt : array of float
        array containing the RHS given u.
    """

    v = u[0]
    theta = u[1]
    x = u[2]
    y = u[3]
    return numpy.array([-g*sin(theta) - C_D/C_L*g/v_t**2*v**2,
                      -g*cos(theta)/v + g/v_t**2*v,
                      v*cos(theta),
                      v*sin(theta)])
```

```python
def euler_step(u, f, dt):
    """Returns the solution at the next time-step using Euler's method.

    Parameters
    ----------
    u : array of float
        solution at the previous time-step.
    f : function
        function to compute the right hand-side of the system of equation.
    dt : float
        time-increment.

    Returns
    -------
    u_n_plus_1 : array of float
        approximate solution at the next time step.
    """

    return u + dt * f(u)
```

```python
T_values = numpy.array([0.001*2**(i) for i in range(10)])
lte_values = numpy.zeros_like(T_values)
for j, T in enumerate(T_values):
    dt_values = numpy.array([T*2**(i-8) for i in range(8)])
    v_values = numpy.zeros_like(dt_values)
    for i, dt in enumerate(dt_values):
        N = int(T/dt)+1
        t = numpy.linspace(0.0, T, N)
        u = numpy.empty((N, 4))
        u[0] = numpy.array([v0, theta0, x0, y0])
        for n in range(N-1):
            u[n+1] = euler_step(u[n], f, dt)
        v_values[i] = u[-1,0]
    v_next = v_values
    for s in range(1, len(v_values-1)):
        v_next = (2**s*v_next[1:]-v_next[0:-1])/(2**s-1)
    lte_values[j] = abs(v_values[0]-v_next)
```

```python
lte_values
```

    array([  1.99954897e-09,   8.05573563e-09,   3.26825287e-08,
             1.34407252e-07,   5.67045063e-07,   2.50349015e-06,
             1.18961299e-05,   6.26360623e-05,   3.70836832e-04,
             2.44291651e-03])

We now have four values for the local truncation error. We can thus compute the convergence rate of the local truncation error itself (which should be two), and check that it is close enough to the expected value using the previous techniques:

```python
s_m = numpy.zeros(2)
for i in range(2):
    s_m[i] = log(abs((lte_values[2+i]-lte_values[1+i])/
                     (lte_values[1+i]-lte_values[0+i]))) / log(2.0)
    print("Measured convergence rate (base dt {}) is {:.6g} (error is {:.4g}).".format(
            T_values[i], s_m[i], abs(s_m[i]-2)))
print("Convergence error has reduced by factor {:.4g}.".format(
        abs(s_m[0]-2)/abs(s_m[1]-2)))
```

    Measured convergence rate (base dt 0.001) is 2.02375 (error is 0.02375).
    Measured convergence rate (base dt 0.002) is 2.04637 (error is 0.04637).
    Convergence error has reduced by factor 0.5121.

So the error has gone down considerably, and certainly $0.51 < 2/3$, so the convergence rate of the local truncation error is close enough to 2.

However, that alone isn't enough to determine that this really is Euler's method: as noted above, the convergence rate of the local truncation error isn't the key point: the key point is that we can predict its *actual value* as

$$
\begin{equation}
  \Edt{\dt} =  \frac{\dt^2}{2} \left| \left. u''\right|_{t=0} \right| + {\cal O}(\dt^3) = \frac{\dt^2}{2} \left| \left( \left. \frac{\partial f}{\partial t} \right|_{t=0} + f(0, u_0) \left. \frac{\partial f}{\partial u} \right|_{t=0, u=u_0} \right) \right|.
\end{equation}
$$

For the specific problem considered here we have

$$
\begin{equation}
  u = \begin{pmatrix} v \\ \theta \\ x \\ y \end{pmatrix}, \quad f = \begin{pmatrix} -g\sin \theta - \frac{C_D}{C_L} \frac{g}{v_t^2} v^2 \\ -\frac{g}{v}\cos \theta + \frac{g}{v_t^2} v \\ v \cos \theta \\ v \sin \theta \end{pmatrix}.
\end{equation}
$$

We note that $f$ does not explicitly depend on $t$ (so $\partial f / \partial t \equiv 0$), and that the values of the parameters $g, C_D, C_L$ and $v_t$ are given above, along with the initial data $u_0 = (v_0, \theta_0, x_0, y_0)$.

So, let's find what the local truncation error should be.

```python
import sympy
sympy.init_printing()
v, theta, x, y, g, CD, CL, vt, dt = sympy.symbols('v, theta, x, y, g, C_D, C_L, v_t, {\Delta}t')
u = sympy.Matrix([v, theta, x, y])
f = sympy.Matrix([-g*sympy.sin(theta)-CD/CL*g/vt**2*v**2,
                  -g/v*sympy.cos(theta)+g/vt**2*v,
                  v*sympy.cos(theta),
                  v*sympy.sin(theta)])
dfdu = f.jacobian(u)
lte=dt**2/2*dfdu*f
```

```python
lte_0=lte.subs([(g,9.8),(vt,30.0),(CD,1.0/40.0),(CL,1.0),(v,30.0),(theta,0.0),(x,0.0),(y,1000.0)])
lte_0
```

So let us check the local truncation error values, which are computed for `v`:

```python
lte_exact = float(lte_0[0]/dt**2)
lte_values/T_values**2
```

    array([ 0.00199955,  0.00201393,  0.00204266,  0.00210011,  0.00221502,
            0.00244481,  0.00290433,  0.003823  ,  0.00565852,  0.00931899])

These are indeed converging towards $0.002 \dt^2$ as they should. To check this quantitatively, we use that our model is

$$
\begin{equation}
  \Edt{\dt} = \alpha \dt^2 + {\cal O}(\dt^3),
\end{equation}
$$

with the exact value $\alpha_e \simeq 0.002$. So we can use our usual Richardson extrapolation methods applied to $\Edt{\dt}/\dt^2$, to get a measured value for $\alpha$ with an error interval:

$$
\begin{equation}
  \alpha_m  = \frac{8\Edt{\dt} - \Edt{2\dt} \pm \left| \Edt{\dt} - \Edt{2\dt} \right|}{4\dt^2}.
\end{equation}
$$

```python
for i in range(len(lte_values)-1):
    Edt = lte_values[i]
    E2dt = lte_values[i+1]
    dt = T_values[i]
    err1 = abs(Edt - E2dt)
    a_lo = (8.0*Edt - E2dt - err1)/(4.0*dt**2)
    a_hi = (8.0*Edt - E2dt + err1)/(4.0*dt**2)
    print("Base dt={:.4g}: the measured alpha is in [{:.5g}, {:.5g}]".format(
            dt, a_lo, a_hi))
    print("Does this contain the exact value? {}".format(
            a_lo <= lte_exact <= a_hi))
```

    Base dt=0.001: the measured alpha is in [0.00047112, 0.0034992]
    Does this contain the exact value? True
    Base dt=0.002: the measured alpha is in [0.00044604, 0.0035244]
    Does this contain the exact value? True
    Base dt=0.004: the measured alpha is in [0.00039575, 0.0035747]
    Does this contain the exact value? True
    Base dt=0.008: the measured alpha is in [0.00029522, 0.0036752]
    Does this contain the exact value? True
    Base dt=0.016: the measured alpha is in [9.4165e-05, 0.0038763]
    Does this contain the exact value? True
    Base dt=0.032: the measured alpha is in [-0.00030782, 0.0042784]
    Does this contain the exact value? True
    Base dt=0.064: the measured alpha is in [-0.0011113, 0.0050826]
    Does this contain the exact value? True
    Base dt=0.128: the measured alpha is in [-0.0027153, 0.0066903]
    Does this contain the exact value? True
    Base dt=0.256: the measured alpha is in [-0.0059063, 0.0099024]
    Does this contain the exact value? True

So, to the limits that we can measure the local truncation error, we have implemented Euler's method.


```python
import random as rd
import numpy as np
import sympy as spy
import datetime as dt
import base64

from jdk2py_MD import *
```

```python
miformula = "8*x**5-14*x**4-22*x**3+57*x**2-35*x+6"
```

```python
grafica(miformula, name="001", micolor="red");
```

```python

```

```python

```


# PHY321: Classical Mechanics 1

**Solution Homework 9, due Monday  April 5**

Date: **Apr 11, 2021**

### Introduction to homework 9

This week's exercises focus on solving
two-body  problems with central forces. It is based on what you did in hw7 and hw8, see also their respective solutions.

### Exercise 1: Attractive Potential (10pt)

Consider a particle in an attractive potential

$$
U(r)=-\alpha/r.
$$

The quantity $r$ is the absolute value of the relative position. We
will use the reduced mass $\mu$ and the angular momentum $L$, as
discussed during the lectures. With the transformation of a two-body
problem to the center-of-mass frame, the actual equations look like an
*effective* one-body problem. The energy of the system is $E$ and the
minimum of the effective potential is $r_{\rm min}$.

The analytical solution to the radial equation of motion is

$$
r(\phi) = \frac{1}{\frac{\mu\alpha}{L^2}+A\cos{(\phi)}}.
$$

Find the value of $A$. Hint: Use the fact that at $r_{\rm min}$
there is no radial kinetic energy and $E=-\alpha/r_{\rm min}+L^2/2mr_{\rm min}^2$.

At  $r_{\mathrm{min}}$  and $r_{\mathrm{max}}$ , all the kinetic energy is stored in the velocity in the direction perpendicular to $r$  since the radial velocity is set to zero . We can calculate using angular momentum and from there, find  𝐴  in terms of the energy  $E$  which is constant. But first, we need to find $r_{\mathrm{min}}$  from the conservation of energy (noting that the radial velocity $\ddot{r}$ at the mininum is zero):

$$
E = U(r) + \frac{1}{2} \mu(\ddot{r}^2 + (r\ddot{\phi})^2)
\\
E = \frac{-\alpha}{r_{\min}} + \frac{1}{2} \mu\left( \frac{L}{\mu r_{\min}}\right) ^2
\\
E r_{\min}^2 - \frac{1}{2}\mu\left( \frac{L}{\mu}\right) ^2 + \alpha r_{\min} = 0
\\
r_{\min}^2 + \frac{\alpha}{E} r_{\min} - \frac{L^2}{2E\mu} = 0
\\
r_{\min} = - \frac{\alpha}{2E} \pm \frac{1}{2} \sqrt{\frac{\alpha^2}{E^2} + 2\frac{L^2}{E\mu}}
$$

Since we're looking for the minimum, the  ±  sign must be negative (then  𝑟min  will not be negative since  𝐸<0 ). Therefore, we have

$$
\frac{1}{\frac{\mu\alpha}{L^2}+A} = -\frac{\alpha}{2E} - \frac{1}{2} \sqrt{\frac{\alpha^2}{E^2} + 2\frac{L^2}{E\mu}}
\\
A = - \frac{\mu\alpha}{L^2} - \frac{2E}{\alpha + \sqrt{\alpha^2 + 2\frac{L^2E}{\mu}}}
$$

### Exercise 2 (20pt) Inverse-square force

Consider again the same effective potential as in exercise 1. This leads to an attractive inverse-square-law force, $F=-\alpha/r^2$. Consider a particle of mass $m$ with angular momentum $L$. Taylor sections 8.4-8.7 are relevant background material.  See also the harmonic oscillator potential from hw8. The equation of motion for the radial degrees of freedom is (see also hw8) in the center-of-mass frame in two dimensions with $x=r\cos{(\phi)}$ and $y=r\sin{(\phi)}$ and
$r\in [0,\infty)$, $\phi\in [0,2\pi]$ and $r=\sqrt{x^2+y^2}$ are given by

$$
\ddot{r}=-\frac{1}{m}\frac{dV(r)}{dr}+r\dot{\phi}^2,
$$

and

$$
\dot{\phi}=\frac{L}{m r^2}.
$$

Here $V(r)$ is any central force which depends only on the relative coordinate.

* 2a (5pt)  Find the radius of a circular orbit by solving for the position of the minimum of the effective potential.

$$
\begin{equation}
\frac{1}{m}\frac{dV(r)}{dr}  = r\dot{\phi}^2
\label{_auto1} \tag{1}
\end{equation}
$$

$$
\begin{equation}  \frac{1}{m}\left( -\frac{-\alpha}{r^2}\right)   = r \frac{L^2}{m^2r^4}
\label{_auto2} \tag{2}
\end{equation}
$$

$$
\begin{equation}  \frac{\alpha}{mr^2}  = \frac{L^2}{m^2r^3}
\label{_auto3} \tag{3}
\end{equation}
$$

$$
\begin{equation}  r  = \frac{L^2}{m\alpha}
\label{_auto4} \tag{4}
\end{equation}
$$

* 2b (5pt) At the minimum, the radial velocity is zero and it is only the [centripetal velocity](https://en.wikipedia.org/wiki/Centripetal_force) which is nonzero. This implies that $\ddot{r}=0$.  What is the angular frequency, $\dot{\theta}$, of the orbit? Solve this by setting $\ddot{r}=0=F/m+\dot{\theta}^2r$.

$$
\begin{equation}
\dot{\theta}^2 r  = - \frac{F}{m}
\label{_auto5} \tag{5}
\end{equation}
$$

$$
\begin{equation}  \dot{\theta}^2 r  = - \frac{-\frac{\alpha}{r^2}}{m}
\label{_auto6} \tag{6}
\end{equation}
$$

$$
\begin{equation}  \dot{\theta}^2  = \frac{\alpha}{mr^3}
\label{_auto7} \tag{7}
\end{equation}
$$

$$
\begin{equation}  \dot{\theta}  = \pm \sqrt{\frac{\alpha}{mr^3}}
\label{_auto8} \tag{8}
\end{equation}
$$

$$
\begin{equation}  \dot{\theta}  = \pm \sqrt{\frac{\alpha}{m\frac{L^6}{m^3\alpha^3}}}
\label{_auto9} \tag{9}
\end{equation}
$$

$$
\begin{equation}  \dot{\theta}  = \pm \sqrt{\frac{\alpha^4m^2}{L^6}}
\label{_auto10} \tag{10}
\end{equation}
$$

$$
\begin{equation}  \dot{\theta}  = \pm \frac{\alpha^2m}{L^3}
\label{_auto11} \tag{11}
\end{equation}
$$

* 2c (5pt) Find the effective spring constant for the particle at the minimum.

We have shown in class that from the taylor expansion, we have

$$
k = \frac{d^2V_{\text{eff}}}{dr^2}
$$

Therefore, all we have to do is find the second derivative of $V_{\text{eff}}$ around the minimum point of $V_{\text{eff}}$ where $\dot{r} = \ddot{r} = 0$.

$$
\begin{equation}
k  = \frac{d^2V_{\text{eff}}}{dr^2}
\label{_auto12} \tag{12}
\end{equation}
$$

$$
\begin{equation}   = \frac{d^2\left( -\frac{\alpha}{r} + \frac{1}{2} \frac{L^2}{mr^2}\right) }{dr^2}
\label{_auto13} \tag{13}
\end{equation}
$$

$$
\begin{equation}   = -\frac{2\alpha}{r^3} + \frac{3L^2}{mr^4}
\label{_auto14} \tag{14}
\end{equation}
$$

$$
\begin{equation}   = -\frac{2\alpha}{\frac{L^6}{m^3\alpha^3}} + \frac{3L^2}{m\frac{L^8}{m^4\alpha^4}}
\label{_auto15} \tag{15}
\end{equation}
$$

$$
\begin{equation}   = -\frac{2m^3\alpha^4}{L^6} + \frac{3m^3\alpha^4}{L^6}
\label{_auto16} \tag{16}
\end{equation}
$$

$$
\begin{equation}   = \frac{m^3\alpha^4}{L^6}
\label{_auto17} \tag{17}
\end{equation}
$$

* 2d (5pt) What is the angular frequency for small vibrations about the minimum? How does this compare with the answer to (3b)?

For small deviations $\delta r$ of $r$,

$$
m\frac{d^2\left(  \delta r \right) }{dt^2} = -k \delta r
$$

The solution of this differential equation is of the form

$$
\delta r = A \cos(\omega t + \phi)
$$

where

$$
\begin{equation}
\omega =  \sqrt{\frac{k}{m}}
\label{_auto18} \tag{18}
\end{equation}
$$

$$
\begin{equation}   = \sqrt{\frac{m^2\alpha^4}{L^6}}
\label{_auto19} \tag{19}
\end{equation}
$$

$$
\begin{equation}   = \frac{m\alpha^2}{L^3}
\label{_auto20} \tag{20}
\end{equation}
$$

This is in fact equal to the expression for $\dot{\theta}$. This means that small perturbations oscillate in sync with the orbit and this traces out an ellipse with a very small eccentricity, a very nice physical result.

### Exercise 3, Inverse-square force again (10pt)

Consider again a  particle of mass $m$ in the same attractive potential, $U(r)=-\alpha/r$, with angular momentum $L$ with just the right energy so that

$$
A=m\alpha/L^2
$$

where $A$ comes from the expression

$$
r=\frac{1}{(m\alpha/L^2)+A\cos{(\phi)}}.
$$

The trajectory can then be rewritten as

$$
r=\frac{2r_0}{1+\cos\theta},~~~r_0=\frac{L^2}{2m\alpha}.
$$

* 3a (5pt) Show that for this case the total energy $E$ approaches zero.

$$
\begin{equation}
E  = - \frac{\alpha}{r} + \frac{1}{2} m \left(  (\dot{\theta}r)^2+\dot{r}^2\right)
\label{_auto21} \tag{21}
\end{equation}
$$

$$
\begin{equation}   = - \frac{\alpha}{r} + \frac{1}{2} m \left[  \left( \frac{L}{mr^2}r\right) ^2+\left( \frac{dr}{d\theta}\dot{\theta}\right) ^2\right]
\label{_auto22} \tag{22}
\end{equation}
$$

$$
\begin{equation}   = - \frac{\alpha}{2r_0}(1+\cos\theta) + \frac{1}{2} m \left[  \left( \frac{L(1+\cos\theta)}{2mr_0}\right) ^2+\left( 2r_0\frac{-1}{(1+\cos\theta)^2}(-\sin\theta)\frac{L}{mr^2}\right) ^2\right]
\label{_auto23} \tag{23}
\end{equation}
$$

$$
\begin{equation}   = - \frac{\alpha}{2r_0}(1+\cos\theta) + \frac{1}{2} m \left[  \left( \frac{L(1+\cos\theta)}{2mr_0}\right) ^2+\left( 2r_0\frac{-1}{(1+\cos\theta)^2}(-\sin\theta)\frac{L(1+\cos\theta)^2}{4mr_0^2}\right) ^2\right]
\label{_auto24} \tag{24}
\end{equation}
$$

$$
\begin{equation}   = - \frac{\alpha}{2r_0}(1+\cos\theta) +
\frac{1}{2} m \left[  \left( \frac{L(1+\cos\theta)}{2mr_0}\right) ^2+\left( \sin\theta\frac{L}{2mr_0}\right) ^2\right]
\label{_auto25} \tag{25}
\end{equation}
$$

$$
\begin{equation}   = - \frac{\alpha}{2r_0}(1+\cos\theta) +
\frac{1}{2} m \left[  \left( \frac{L(1+\cos\theta)}{2mr_0}\right) ^2+\left( \sin\theta\frac{L}{2mr_0}\right) ^2\right]
\label{_auto26} \tag{26}
\end{equation}
$$

$$
\begin{equation}   = - \frac{\alpha}{2r_0}(1+\cos\theta) +
\frac{1}{2} m \frac{L^2}{4m^2r_0^2} \left[  \left( 1+\cos\theta\right) ^2+\left( \sin\theta\right) ^2\right]
\label{_auto27} \tag{27}
\end{equation}
$$

$$
\begin{equation}   = - \frac{\alpha}{2r_0}(1+\cos\theta) +
\frac{1}{2} \frac{L^2}{4mr_0^2} \left(  1 + \cos^2\theta + 2\cos \theta + \sin^2\theta\right)
\label{_auto28} \tag{28}
\end{equation}
$$

$$
\begin{equation}   = - \frac{\alpha}{2r_0}(1+\cos\theta) +
\frac{1}{2} \frac{L^2}{4mr_0^2} \left(  2 + 2\cos \theta \right)
\label{_auto29} \tag{29}
\end{equation}
$$

$$
\begin{equation}   = (1+\cos\theta) \left( - \frac{\alpha}{2r_0} + \frac{L^2}{4mr_0^2}\right)
\label{_auto30} \tag{30}
\end{equation}
$$

$$
\begin{equation}   = (1+\cos\theta) \left( - \frac{\alpha}{2\frac{L^2}{2m\alpha}} + \frac{L^2}{4m\frac{L^4}{4m^2\alpha^2}}\right)
\label{_auto31} \tag{31}
\end{equation}
$$

$$
\begin{equation}   = (1+\cos\theta) \left( - \frac{m\alpha^2}{L^2} + \frac{m\alpha^2}{L^2}\right)
\label{_auto32} \tag{32}
\end{equation}
$$

$$
\begin{equation}   = 0
\label{_auto33} \tag{33}
\end{equation}
$$

* 3b (5pt) With zero energy $E=0$, write this trajectory in a more recognizable parabolic form, that is express $x_0$ and $R$ in terms of $r_0$ using

$$
x=x_0-\frac{y^2}{R}.
$$

We have that

$$
\begin{equation}
x  = r \cos\theta
\label{_auto34} \tag{34}
\end{equation}
$$

$$
\begin{equation}
y  = r \sin \theta.
\label{_auto35} \tag{35}
\end{equation}
$$

Using the general solution with eccintricity $\epsilon=1$, we have

$$
r(\theta)=\frac{c}{1+\cos\theta},
$$

and multiplying both sides with $1+\cos\theta$ and using that $x=r\cos\theta$,

$$
r = c -x,
$$

and using that $r^2=x^2+y^2$, we square both sides

$$
r^2 = x^2+y^2=c^2 +x^2-2cx,
$$

leading to

$$
y^2=c^2-2cx,
$$

and using that we defined

$$
c=2r_0=\frac{L^2}{m\alpha},
$$

we divide by $2c$
and we get the final answer

$$
x = r_0 - \frac{y^2}{4r_0}
$$

### Exercise 4, parabolic and hyperbolic orbits (10pt)

The solution to the radial function for an inverse-square-law force, see for example Taylor equation (8.59) or the equation above, is

$$
r(\phi) = \frac{c}{1+\epsilon\cos{(\phi)}}.
$$

For $\epsilon=1$ (or the energy $E=0$) the orbit reduces to a parabola as we saw in the previous exercise,
while for $\epsilon > 1$ (or energy positive) the orbit becomes a hyperbola. The equation for a hyperbola in Cartesian coordinates is

$$
\frac{(x-\delta)^2}{\alpha^2}-\frac{y^2}{\beta^2}=1.
$$

For a hyperbola, identify the constants $\alpha$, $\beta$ and $\delta$ in terms of the constants $c$ and $\epsilon$ for $r(\phi)$.

$$
\begin{equation}
x  = r\cos\phi
\label{_auto36} \tag{36}
\end{equation}
$$

$$
\begin{equation}   = \frac{c\cos\phi}{1+\epsilon\cos\phi}
\label{_auto37} \tag{37}
\end{equation}
$$

$$
\begin{equation}
y  = r\sin\phi
\label{_auto38} \tag{38}
\end{equation}
$$

$$
\begin{equation}   = \frac{c\sin\phi}{1+\epsilon\cos\phi}
\label{_auto39} \tag{39}
\end{equation}
$$

Here $\epsilon>1$.  We use our equation for $r$, multiply with the denominator $1+\epsilon\cos\phi$ on both sides and have

$$
r(1+\epsilon\cos\phi)=c,
$$

use $x=r\cos\phi$ and square and use that $r^2=x^2+y^2$ and we have

$$
r^2=x^2+y^2=c^2+\epsilon^2x^2-2cx\epsilon,
$$

and reorder

$$
x^2(\epsilon^2-1)-y^2-2cx\epsilon= -c^2.
$$

We complete the square in $x$ by adding and subtracting on both sides $\epsilon^2c^2/(\epsilon^2-1)$
and we obtain

$$
(\epsilon^2-1)(x-\delta)^2-y^2= -c^2+\frac{\epsilon^2c^2}{\epsilon^2-1}.
$$

Here we have defined

$$
\delta = \frac{c\epsilon}{\epsilon^2-1},
$$

and introducing the constants

$$
\alpha = \frac{c}{\epsilon^2-1},
$$

and

$$
\beta = \frac{c}{\sqrt{\epsilon^2-1}},
$$

we can rewrite the above equation as

$$
\frac{(x-\delta)^2}{\alpha^2}-\frac{y^2}{\beta^2}=1,
$$

which is nothing but the equation for a hyperbola.

### Exercise 5, Testing orbit types (50 pt)

In this exercise we can use the program for $r(\phi)$ we developed in hw8. We will use an inverse-square-law force as in exercises 1, 2, 3 and 4. The aim is to see that the orbits we get for $E<0$ become ellipses (or circles), parabola for $E=0$ and hyperbola for $E>0$.  An example code is shown here.

Here we have defined the constants $L=m=\alpha=1$. Feel free to set new values. **You need also to set the initial conditions** in order to study the different types of orbits. It may be useful to plot the potential here and find the values for the initial conditions that fit $E<0$, $E=0$ and $E>0$.

```python
%matplotlib inline

# Common imports
import numpy as np
import pandas as pd
from math import *
import matplotlib.pyplot as plt
# Simple Gravitational Force   -alpha/r

DeltaT = 0.01
#set up arrays
tfinal = 100.0
n = ceil(tfinal/DeltaT)
# set up arrays for t, v and r
t = np.zeros(n)
v = np.zeros(n)
r = np.zeros(n)
# Constants of the model, setting all variables to one for simplicity
alpha = 1.0
AngMom = 1.0  #  The angular momentum
m = 1.0  # scale mass to one
c1 = AngMom*AngMom/(m*m)
c2 = AngMom*AngMom/m
# You need to specify the initial conditions
# Here we have chosen the conditions which lead to circular orbit and thereby a constant r
r0 = (AngMom*AngMom/m/alpha)
v0 = 0.0
r[0] = r0
v[0] = v0
# Start integrating using the Velocity-Verlet  method
for i in range(n-1):
    # Set up acceleration
    a = -alpha/(r[i]**2)+c1/(r[i]**3)
    # update velocity, time and position using the Velocity-Verlet method
    r[i+1] = r[i] + DeltaT*v[i]+0.5*(DeltaT**2)*a
    anew = -alpha/(r[i+1]**2)+c1/(r[i+1]**3)
    v[i+1] = v[i] + 0.5*DeltaT*(a+anew)
    t[i+1] = t[i] + DeltaT
    # Plot position as function of time
fig, ax = plt.subplots(2,1)
ax[0].set_xlabel('time')
ax[0].set_ylabel('radius')
ax[0].plot(t,r)
ax[1].set_xlabel('time')
ax[1].set_ylabel('Velocity')
ax[1].plot(t,v)

plt.show()
```

Run your code and study and discuss the situations where you have
elliptical, parabolic and hyperbolic orbits. Discuss the physics of
these cases. The results from exercises 1, 2, 3 and 4 may be useful
here.  In the code here we have chosen initial conditions which correspond to circular motion.
This corresponds to

$$
r_{\mathrm{min}} = \frac{L^2}{m\alpha}.
$$

Note well that the velocity is now the radial velocity. If we want to study the angular velocity we would need to add the equations for this quantity. The solution to exercises 1-4 give you the minimum $r$ values needed to find the elliptical, parabolic and hyperbolic orbits. For elliptical orbits you should have  $\frac{L^2}{2m\alpha} < r_{\mathrm{min}} <\frac{L^2}{m\alpha}$. For parabolic orbits $r_{\mathrm{min}} =\frac{L^2}{m\alpha}$ and for hyperbolic orbits we have $0<r_{\mathrm{min}} <\frac{L^2}{m\alpha}$. Try out these different initial conditions in order to test these different types of motion.

### Additional Bonus Exercise (10pt)

You don't need to do this exercise, but it gives you a bonus score of 10 points.

This time the additional bonus exercise is a simple survey. We are now moving
into our last month  and we would very much have your feedback on how
things are functioning so that we can improve and correct.

* Is the weekly load with paper and pencil exercises and the numerical exercises reasonable?

* Is there enough material (lectures and lecture material) to get you started with the exercises?  We are thinking of both the paper and pencil and the numerical exercises?

* Is the pace during the lectures reasonable? And do the lectures link well with the exercises?

* In the beginning there will always be some elements of repetition of material many of you have seen before. Do you find the choice of material the first 4 weeks adequate? Too easy? Too difficult?

* For those of you who have taken CMSE 201 Introduction to Computational Modeling, do you feel the material taught there links well with the exercises you have done in this course? Is there is something we are missing?

* Any other topic you would like to comment on?

### Classical Mechanics Extra Credit Assignment: Scientific Writing and attending Talks

The following gives you an opportunity to earn **five extra credit
points** on each of the remaining homeworks and **ten extra credit points**
on the midterms and finals.  This assignment also covers an aspect of
the scientific process that is not taught in most undergraduate
programs: scientific writing.  Writing scientific reports is how
scientist communicate their results to the rest of the field.  Knowing
how to assemble a well written scientific report will greatly benefit
you in you upper level classes, in graduate school, and in the work
place.

The full information on extra credits is found at <https://github.com/mhjensen/Physics321/blob/master/doc/Homeworks/ExtraCredits/>. There you will also find examples on how to write a scientific article.
Below you can also find a description on how to gain extra credits by attending scientific talks.

This assignment allows you to gain extra credit points by practicing
your scientific writing.  For each of the remaining homeworks you can
submit the specified section of a scientific report (written about the
numerical aspect of the homework) for five extra credit points on the
assignment.  For the two midterms and the final, submitting a full
scientific report covering the numerical analysis problem will be
worth ten extra points.  For credit the grader must be able to tell
that you put effort into the assignment (i.e. well written, well
formatted, etc.).  If you are unfamiliar with writing scientific
reports, [see the information here](https://github.com/mhjensen/Physics321/blob/master/doc/Homeworks/ExtraCredits/IntroductionScientificWriting.md)

The following table explains what aspect of a scientific report is due
with which homework.  You can submit the assignment in any format you
like, in the same document as your homework, or in a different one.
Remember to cite any external references you use and include a
reference list.  There are no length requirements, but make sure what
you turn in is complete and through.  If you have any questions,
please contact Julie Butler at butler@frib.msu.edu.

  HW/Project 	 Due Date	 Extra Credit Assignment

   HW 3             	    2-8         	    Abstract

   HW 4             	    2-15        	    Introduction

   HW 5             	    2-22        	    Methods

   HW 6             	    3-1         	    Results and Discussion

   **Midterm 1**    	    **3-12**    	    *Full Written Report*

   HW 7             	    3-22        	    Abstract

   HW 8             	    3-29        	    Introduction

   HW 9             	    4-5         	    Results and Discussion

   **Midterm 2**    	    **4-16**    	    *Full Written Report*

   HW 10            	    4-26        	    Abstract

   **Final**        	    **4-30**    	    *Full Written Report*

You can also gain extra credits if you attend scientific talks.
This is described here.

### Integrating Classwork With Research

This opportunity will allow you to earn up to 5 extra credit points on a Homework per week. These points can push you above 100% or help make up for missed exercises.
In order to earn all points you must:

1. Attend an MSU research talk (recommended research oriented Clubs is  provided below)

2. Summarize the talk using at least 150 words

3. Turn in the summary along with your Homework.

Approved talks:
Talks given by researchers through the following clubs:
* Research and Idea Sharing Enterprise (RAISE): Meets Wednesday Nights Society for Physics Students (SPS): Meets Monday Nights

* Astronomy Club: Meets Monday Nights

* Facility For Rare Isotope Beam (FRIB) Seminars: Occur multiple times a week

If you have any questions please consult Jeremy Rebenstock, rebensto@msu.edu.

All the material on extra credits is at <https://github.com/mhjensen/Physics321/blob/master/doc/Homeworks/ExtraCredits/>.